int factorial(const MultipleDeriv& ms) { Sundance::Map<Deriv, int> counts; for (MultipleDeriv::const_iterator i=ms.begin(); i!=ms.end(); i++) { if (counts.containsKey(*i)) counts[*i]++; else counts.put(*i, 1); } int rtn = 1; for (Sundance::Map<Deriv, int>::const_iterator i=counts.begin(); i!=counts.end(); i++) { int f = 1; for (int j=1; j<=i->second; j++) f *= j; rtn *= f; } return rtn; }
bool ReorderSum::doTransform(const RCP<ScalarExpr>& left, const RCP<ScalarExpr>& right, int sign, RCP<ScalarExpr>& rtn) const { TimeMonitor timer(reorderSumTimer()); /* first we check to see whether the terms are already in order. * The left and right trees are already ordered, so that if the * first term on the right is after the last term on the left, the * combination of both is already ordered. In that case, nothing more needs * to be done. */ Expr L = Expr::handle(left); Expr R = Expr::handle(right); Sundance::Map<Expr, int> tree = L.getSumTree(); Sundance::Map<Expr, int>::const_reverse_iterator iL = tree.rbegin(); Expr endOfLeft = iL->first; Sundance::Map<Expr, int> rightTree = R.getSumTree(); Sundance::Map<Expr, int>::const_iterator iR = rightTree.begin(); Expr startOfRight = iR->first; if (endOfLeft.lessThan(startOfRight)) { Tabs tab1; SUNDANCE_VERB_MEDIUM(tab1 << "Terms are already ordered, doing nothing"); return false; } else { Tabs tab1; for (Map<Expr, int>::const_iterator i=rightTree.begin(); i!=rightTree.end(); i++) { int leftCount = 0; if (tree.containsKey(i->first)) { leftCount = tree[i->first]; } int count = leftCount + sign * i->second; tree.put(i->first, count); } SUNDANCE_VERB_MEDIUM(tab1 << "Ordered terms are: " << tree); Expr sum = new ZeroExpr(); /* add up all terms. If no terms are left after cancellations, the result will * be zero. */ for (Map<Expr, int>::const_iterator i=tree.begin(); i!=tree.end(); i++) { const Expr& term = i->first; int count = i->second; if (count==0) continue; if (count==1) sum = sum + term; else if (count==-1) sum = sum - term; else sum = sum + count*term; } rtn = getScalar(sum); return true; } }