CEvaluationNode* CEvaluationNodeNormalizer::normalizeMultiplyNode(const CEvaluationNodeOperator* pNode)
{
  CEvaluationNode* pResult = NULL;

  if (pNode != NULL)
    {
      CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()));

      if (pChild1 != NULL)
        {
          CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling()));

          if (pChild2 != NULL)
            {
              // if one of the child nodes is zero, replace the node with a number
              // node of value 0

              // if one of the nodes is a number node of 1, replace the node by the
              // other child
              if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER)
                {
                  if (fabs(pChild1->value() - 1.0) < ZERO)
                    {
                      pResult = pChild2;
                      delete pChild1;
                      pChild1 = NULL;
                      pChild2 = NULL;
                    }
                  else if (fabs(pChild1->value()) < ZERO)
                    {
                      pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0");
                      // we are done
                      delete pChild1;
                      delete pChild2;
                      pChild1 = NULL;
                      pChild2 = NULL;
                    }
                }

              if (pChild2 && CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
                {
                  if (fabs(pChild2->value() - 1.0) < ZERO)
                    {
                      pResult = pChild1;
                      delete pChild2;
                      pChild2 = NULL;
                      pChild1 = NULL;
                    }
                  else if (fabs(pChild2->value()) < ZERO)
                    {
                      pResult = new CEvaluationNodeNumber(CEvaluationNodeNumber::INTEGER, "0");
                      // we are done
                      delete pChild1;
                      delete pChild2;
                      pChild1 = NULL;
                      pChild2 = NULL;
                    }
                }

              if (!pResult)
                {
                  pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::MULTIPLY, "*");
                  pResult->addChild(pChild1);
                  pResult->addChild(pChild2);
                }

              if (pResult->getType() == CEvaluationNode::OPERATOR)
                {
                  // multiply all number nodes in a multiplication chain
                  std::vector<CEvaluationNode*> chainNodes;
                  findChainNodes(dynamic_cast<CEvaluationNodeOperator*>(pResult), chainNodes);
                  CEvaluationNodeNormalizer::eliminateMultipleNumbers((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes);
                  // replace multiplication of identical items by a power node with the
                  // correct power
                  CEvaluationNodeNormalizer::collectIdenticalBranches((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes);
                  // reorder nodes again
                  CEvaluationNodeNormalizer::reorderNodes(chainNodes);
                  // rebuild pResult;
                  CEvaluationNodeOperator::SubType subType = (CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType());
                  delete pResult;
                  pResult = CEvaluationNodeNormalizer::buildOperatorBranchFromChain(subType, chainNodes);
                }
            }
        }

      if (pResult == NULL) pResult = pNode->copyBranch();
    }

  return pResult;
}
CEvaluationNode* CEvaluationNodeNormalizer::normalizePlusNode(const CEvaluationNodeOperator* pNode)
{
  CEvaluationNode* pResult = NULL;

  if (pNode != NULL)
    {
      CEvaluationNode* pChild1 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()));

      if (pChild1 != NULL)
        {
          CEvaluationNode* pChild2 = CEvaluationNodeNormalizer::normalize(dynamic_cast<const CEvaluationNode*>(pNode->getChild()->getSibling()));

          if (pChild2 != NULL)
            {
              // if one of the nodes is a number node of 0, replace the node by the
              // other child
              if (CEvaluationNode::type(pChild1->getType()) == CEvaluationNode::NUMBER)
                {
                  if (fabs(pChild1->getValue()) < ZERO)
                    {
                      pResult = pChild2;
                      delete pChild1;
                      pChild1 = NULL;
                      pChild2 = NULL;
                    }
                }

              if (pChild2 != NULL && CEvaluationNode::type(pChild2->getType()) == CEvaluationNode::NUMBER)
                {
                  if (fabs(pChild2->getValue()) < ZERO)
                    {
                      if (pChild2 != pResult)
                        {
                          pResult = pChild1;
                          delete pChild2;
                        }

                      pChild1 = NULL;
                      pChild2 = NULL;
                    }
                }

              if (!pResult)
                {
                  pResult = new CEvaluationNodeOperator(CEvaluationNodeOperator::PLUS, "+");
                  pResult->addChild(pChild1);
                  pResult->addChild(pChild2);
                }

              if (pResult->getType() == CEvaluationNode::OPERATOR)
                {
                  // add all number nodes in a summation chain
                  std::vector<CEvaluationNode*> chainNodes;
                  findChainNodes(dynamic_cast<CEvaluationNodeOperator*>(pResult), chainNodes);
                  CEvaluationNodeNormalizer::eliminateMultipleNumbers((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes);
                  // replace addition of identical items by a multiplication node with the
                  // correct number
                  CEvaluationNodeNormalizer::collectIdenticalBranches((CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType()), chainNodes);
                  // reorder nodes again
                  CEvaluationNodeNormalizer::reorderNodes(chainNodes);
                  // rebuild pResult;
                  CEvaluationNodeOperator::SubType subType = (CEvaluationNodeOperator::SubType)CEvaluationNode::subType(pResult->getType());
                  delete pResult;
                  pResult = CEvaluationNodeNormalizer::buildOperatorBranchFromChain(subType, chainNodes);
                }
            }
          else
            {
              delete pChild1;
              pChild1 = NULL;
            }
        }

      if (pResult == NULL) pResult = pNode->copyBranch();
    }

  return pResult;
}