SNode SNode::multiplyFactorSum(SNode factor, SNode sum) const {
  ENTERMETHOD2(factor,sum);
  CHECKNODETYPE(factor,NT_POWER);
  CHECKNODETYPE(sum   ,NT_SUM  );

  if((factor.base().getSymbol() == SUM) && factor.exponent().isOne()) {
    RETURNNODE(multiplySumSum(factor.base(),sum));
  } else {
    const AddentArray &sa = sum.getAddentArray();
    AddentArray        tmp(sa.getTree(),sa.size());
    for(size_t i = 0; i < sa.size(); i++) {
      SNode e = sa[i];
      tmp.add(addentExp(factor * e.left(),e.isPositive()));
    }
    RETURNNODE( sumExp(tmp) );
  }
}
SNode SNode::multiplyParenthesesInProduct() const {
  ENTERMETHOD();
  CHECKNODETYPE(*this,NT_PRODUCT);

  const FactorArray &a = getFactorArray();
  const size_t       n = a.size();
  FactorArray        newFactorArray(a.getTree(), n);
  for(size_t i = 0; i < n; i++) {
    SNode f = a[i];
    newFactorArray *= powerExp(f.base().multiplyParentheses(), f.exponent().multiplyParentheses());
  }

  BitSet done(newFactorArray.size() + 1);
  do {
    FactorArray tmp = newFactorArray;
    newFactorArray.clear();
    done.setCapacity(tmp.size() + 1);
    done.clear();
    for(size_t i1 = 1; i1 < tmp.size(); i1++) {
      if(done.contains(i1)) continue;
      SNode f1 = tmp[i1];
      if((f1.base().getSymbol() == SUM) && !f1.exponent().isOne()) {
        continue;
      }
      for(size_t i2 = 0; i2 < i1; i2++) {
        if(done.contains(i1)) break;
        if(done.contains(i2)) continue;
        SNode f2 = tmp[i2];
        if((f2.base().getSymbol() == SUM) && !f2.exponent().isOne()) {
          continue;
        }
        if(f1.base().getSymbol() == SUM) {
          newFactorArray *= multiplyFactorSum(f2, f1.base());
          done.add(i1);
          done.add(i2);
        } else if(f2.base().getSymbol() == SUM) {
          newFactorArray *= multiplyFactorSum(f1, f2.base());
          done.add(i1);
          done.add(i2);
        }
      }
    }
    for(size_t i = 0; i < tmp.size(); i++) {
      if(!done.contains(i)) {
        newFactorArray *= tmp[i];
      }
    }
  } while(!done.isEmpty());
  SNode result = productExp(newFactorArray);
  RETURNNODE( result );
}