Esempio n. 1
0
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;
}
Esempio n. 2
0
CNormalProduct * CNormalProduct::createProduct(const CEvaluationNode* node)
{
  CNormalProduct * product = new CNormalProduct();

  switch (node->mainType())
    {
      case CEvaluationNode::T_OPERATOR:  // PLUS(->createSum), MINUS(translated as +(-..)) and DIVIDE(->createFraction) do not occur.
      {
        if (node->getData() == "^")
          {
            if (CEvaluationNode::type(static_cast<const CEvaluationNode*>(node->getChild()->getSibling())->getType()) == CEvaluationNode::T_NUMBER)
              {
                CNormalItemPower* power = CNormalItemPower::createItemPower(node);
                product->multiply(*power);
                delete power;
                return product;
              }
            else
              {
                CNormalItem* item = CNormalItem::createItem(node);
                product->multiply(*item);
                delete item;
                return product;
              }
          }

        if (node->getData() == "*")
          {
            CNormalProduct* product1 = createProduct(static_cast<const CEvaluationNode*>(node->getChild()));
            CNormalProduct* product2 = createProduct(static_cast<const CEvaluationNode*>(node->getChild()->getSibling()));
            product->multiply(*product1);
            product->multiply(*product2);
            delete product1;
            delete product2;
            return product;
          }

        //default (case MODULUS):
        CNormalItem* item = CNormalItem::createItem(node);
        product->multiply(*item);
        delete item;
        return product;
      }

      case CEvaluationNode::T_NUMBER:
      {
        product->multiply(node->value());
        return product;
      }

      case CEvaluationNode::T_FUNCTION:
      {
        if (node->getData() == "-")
          {
            product->multiply(-1.0);
            CNormalProduct * product2 = createProduct(dynamic_cast<const CEvaluationNode*>(node->getChild()));
            product->multiply(*product2);
            delete product2;
            return product;
          }

        CNormalItem * item = CNormalItem::createItem(node);
        product->multiply(*item);
        delete item;
        return product;
      }

      default:   //cases VARIABLE, CONSTANT, CALL, CHOICE, LOGICAL, OBJECT, VECTOR
      {
        CNormalItem * item = CNormalItem::createItem(node);
        product->multiply(*item);
        delete item;
        return product;
      }
    }
}