bool CNormalSum::simplify()
{
    bool result = true;
    // it is a bad idea to work directly on the items in the set.
    // this messes up the set
    // better copy the set first
    std::set<CNormalFraction*> fractionsCopy(this->mFractions);
    this->mFractions.clear();
    std::set<CNormalFraction*>::iterator it3 = fractionsCopy.begin(), endit3 = fractionsCopy.end();
    CNormalFraction* pTmpFraction = NULL;

    while (it3 != endit3)
    {
        pTmpFraction = *it3;
        pTmpFraction->simplify();
        this->add(*pTmpFraction);
        delete pTmpFraction;
        ++it3;
    }

    std::set<CNormalProduct*, compareProducts>::iterator it = this->mProducts.begin(), endit = this->mProducts.end();
    // add code to find general power items with exponent 1 where the parent
    // power item also has exponent 1
    // if the base of those has a denominator of 1, we add the products of
    // the numerator to this sum, otherwise, we have to add the whole base
    // to the fractions of this sum
    // afterwards, we have to simplify all products and all fractions again
    std::vector<CNormalBase*> newProducts;
    // go through all products and check the denominators
    CNormalProduct* pTmpProduct;

    while (it != endit)
    {
        pTmpProduct = *it;
        pTmpProduct->simplify();

        if (pTmpProduct->getItemPowers().size() == 1 &&
                fabs(((*pTmpProduct->getItemPowers().begin())->getExp() - 1.0) / 1.0) < 1e-12 &&
                (*pTmpProduct->getItemPowers().begin())->getItemType() == CNormalItemPower::POWER &&
                ((CNormalGeneralPower&)(*pTmpProduct->getItemPowers().begin())->getItem()).getRight().checkNumeratorOne() &&
                ((CNormalGeneralPower&)(*pTmpProduct->getItemPowers().begin())->getItem()).getRight().checkDenominatorOne()
           )
        {
            if (((CNormalGeneralPower&)(*pTmpProduct->getItemPowers().begin())->getItem()).getLeft().checkDenominatorOne())
            {
                newProducts.push_back(((CNormalGeneralPower&)(*pTmpProduct->getItemPowers().begin())->getItem()).getLeft().getNumerator().copy());
            }
            else
            {
                newProducts.push_back(((CNormalGeneralPower&)(*pTmpProduct->getItemPowers().begin())->getItem()).getLeft().copy());
            }

            delete pTmpProduct;
        }
        else
        {
            // if the denominator is not NULL, transform the product to a fraction
            CNormalGeneralPower* pDenom = pTmpProduct->getDenominator();

            if (pDenom == NULL || pDenom->checkIsOne())
            {
                newProducts.push_back(pTmpProduct);
            }
            else
            {
                // before creating the product, the denominators of all general items in
                // the product have to be set to 1 by calling setDenominatorsOne on the product
                pTmpProduct->setDenominatorsOne();
                CNormalFraction* pFraction = NULL;

                if (pDenom->getRight().checkIsOne())
                {
                    // the denominator is the left side of pDenom
                    pFraction = new CNormalFraction(pDenom->getLeft());
                    //
                    //pFraction = new CNormalFraction(pDenom->getLeft());
                    //// now we set the numerator
                    //CNormalSum* pSum = new CNormalSum();
                    //pSum->add(**it);
                    //pFraction->setNumerator(*pSum);
                    //delete pSum;
                }
                else
                {
                    // the fraction has the found denominator as its denominator and the
                    // numerator is the product of all items
                    pFraction = new CNormalFraction();
                    CNormalSum* pSum = new CNormalSum();
                    pSum->add(*pTmpProduct);
                    pFraction->setNumerator(*pSum);
                    delete pSum;
                    // now we have to invert the general fraction that is the
                    // denominator
                    CNormalFraction* pTmpFraction = CNormalFraction::createUnitFraction();
                    CNormalSum* pTmpSum = new CNormalSum(pDenom->getLeft().getDenominator());
                    pTmpFraction->setNumerator(*pTmpSum);
                    delete pTmpSum;
                    pDenom->setLeft(*pTmpFraction);
                    delete pTmpFraction;
                    CNormalProduct* pTmpProduct = CNormalProduct::createUnitProduct();
                    CNormalItemPower* pTmpItemPower = new CNormalItemPower();
                    pTmpItemPower->setExp(1.0);
                    pTmpItemPower->setItem(*pDenom);
                    pTmpProduct->multiply(*pTmpItemPower);
                    delete pTmpItemPower;
                    pTmpSum = new CNormalSum();
                    pTmpSum->add(*pTmpProduct);
                    delete pTmpProduct;
                    pFraction->setDenominator(*pTmpSum);
                    delete pTmpSum;
                }

                delete pTmpProduct;
                newProducts.push_back(pFraction);
            }

            if (pDenom != NULL) delete pDenom;
        }

        ++it;
    }

    this->mProducts.clear();
    std::vector<CNormalBase*>::const_iterator it2 = newProducts.begin(), endit2 = newProducts.end();
    const CNormalFraction* pFrac = NULL;
    const CNormalSum* pSum = NULL;
    const CNormalProduct* pProd = NULL;
    std::set<CNormalSum*> multipliers;

    while (it2 != endit2)
    {
        pProd = dynamic_cast<const CNormalProduct*>(*it2);

        if (pProd != NULL)
        {
            this->add(*pProd);
        }
        else
        {
            pFrac = dynamic_cast<const CNormalFraction*>(*it2);

            if (pFrac != NULL)
            {
                this->add(*pFrac);
            }
            else
            {
                pSum = dynamic_cast<const CNormalSum*>(*it2);

                if (pSum != NULL)
                {
                    this->add(*pSum);
                    /*
                    // check if the sum contains more then one product
                    // we have to multiply the sum with that other sum in the end
                    if(pSum->getProducts().size()>1)
                    {
                      multipliers.insert(static_cast<CNormalSum*>(pSum->copy()));
                    }
                    else
                    {
                      if(pSum->getProducts().size()==1 && (*pSum->getProducts().begin())->getItemPowers.size()==1)
                      {
                          // check if the one item power is a general power with
                          // an exponent of one and a denominator of one.
                          const CNormalItemPower* pPower=(*(*pSum->getProducts().begin())->getItemPowers().begin());
                          if(fabs(pPow->getExp()-1.0/1.0)<1e-12 && pPower->getItemType()==CNormalItemPower::POWER)
                          {
                              // check if it is a power operator and not modulo,
                              // check if the exponent is one and the denominator
                              // is one
                              const CNormalGeneralPower* pGenPow=static_cast<const CNormalGeneralPower*>(pPower->getItem());
                              if(pGenPow->getType()==CNormalGeneralPower::POWER && pGenPower->getRight().checkIsOne() && pGenPower->getLeft().checkDenominatorOne())
                              {
                                  // check if there are more then one product in
                              }
                              else
                              {
                                  this->add(*pSum);
                              }
                          }
                          else
                          {
                              this->add(*pSum);
                          }
                      }
                      else
                      {
                        this->add(*pSum);
                      }
                    }*/
                }
                else
                {
                    // this can never happen
                    fatalError();
                }
            }
        }

        delete *it2;
        ++it2;
    }

    std::set<CNormalSum*>::iterator it4 = multipliers.begin(), endit4 = multipliers.end();

    while (it4 != endit4)
    {
        this->multiply(**it4);
        delete *it4;
        ++it4;
    }

    return result;
}
bool CNormalProduct::simplify()
{
  bool result = true;
  // don't work on the items in the set directly
  // make a copy, otherwise the set will be messed up
  std::set<CNormalItemPower*, compareItemPowers> itemPowersCopy(this->mItemPowers);
  std::set<CNormalItemPower*, compareItemPowers>::iterator it = itemPowersCopy.begin(), endit = itemPowersCopy.end();
  CNormalItemPower* pTmpItemPower = NULL;
  this->mItemPowers.clear();
  while (it != endit && result == true)
    {
      pTmpItemPower = *it;
      result = pTmpItemPower->simplify();
      if (result)
        {
          this->multiply(*pTmpItemPower);
        }
      delete pTmpItemPower;
      ++it;
    }
  // we should combine all general power items of type power into
  // one large general power item which is again simplified
  // this we only do if the CNormalItemPower parent has an exponent of 1
  it = this->mItemPowers.begin();
  endit = this->mItemPowers.end();
  std::vector<CNormalItemPower*> tmpV;
  // create a unit CNormalItemPower with one unit CNormalGeneralPower
  // and an exponent of 1
  CNormalGeneralPower* pGeneralPower = NULL; //CNormalGeneralPower::createUnitGeneralPower();
  while (it != endit)
    {
      if ((*it)->getExp() == 1.0 && (*it)->getItemType() == CNormalItemPower::POWER &&
          dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getType() == CNormalGeneralPower::POWER
          &&
          dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getRight().checkIsOne()
)
        {
          if (pGeneralPower)
            {
              pGeneralPower->multiply(*static_cast<CNormalGeneralPower*>(&(*it)->getItem()));
            }
          else
            {
              pGeneralPower = static_cast<CNormalGeneralPower*>(&(*it)->getItem());
              pGeneralPower = new CNormalGeneralPower(*pGeneralPower);
            }
          delete *it;
        }
      else
        {
          if ((*it)->getItemType() == CNormalItemPower::POWER &&
              dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getType() == CNormalGeneralPower::POWER &&
              dynamic_cast<CNormalGeneralPower*>(&(*it)->getItem())->getLeft().checkIsOne()
)
            {
              delete *it;
            }
          else
            {
              tmpV.push_back(*it);
            }
        }
      ++ it;
    }
  if (pGeneralPower && !pGeneralPower->checkIsOne())
    {
      CNormalItemPower* pTmpItemPower = new CNormalItemPower();
      pTmpItemPower->setExp(1.0);
      pTmpItemPower->setItem(*pGeneralPower);
      tmpV.push_back(pTmpItemPower);
    }
  delete pGeneralPower;
  // clear the current set of items and add all the item in tmpV
  this->mItemPowers.clear();
  std::vector<CNormalItemPower*>::iterator vIt = tmpV.begin();
  std::vector<CNormalItemPower*>::iterator vEndIt = tmpV.end();
  while (vIt != vEndIt)
    {
      this->multiply(**vIt);
      delete *vIt;
      ++vIt;
    }
  return result;
}