--- /dev/null
+#include "aterm.hh"
+#include "ppsig.hh"
+//static void collectMulTerms (Tree& coef, map<Tree,int>& M, Tree t, bool invflag=false);
+
+#undef TRACE
+
+using namespace std;
+
+typedef map<Tree,mterm> SM;
+
+aterm::aterm ()
+{}
+
+
+/**
+ * create a aterm from a tree expression
+ */
+aterm::aterm (Tree t)
+{
+ #ifdef TRACE
+ cerr << "aterm::aterm (" << ppsig(t)<< ")" << endl;
+ #endif
+ *this += t;
+ #ifdef TRACE
+ cerr << "aterm::aterm (" << ppsig(t)<< ") : -> " << *this << endl;
+ #endif
+}
+
+
+/**
+ * Add two terms trying to simplify the result
+ */
+static Tree simplifyingAdd(Tree t1, Tree t2)
+{
+ assert(t1!=0);
+ assert(t2!=0);
+
+ if (isNum(t1) && isNum(t2)) {
+ return addNums(t1,t2);
+
+ } else if (isZero(t1)) {
+ return t2;
+
+ } else if (isZero(t2)) {
+ return t1;
+
+ } else if (t1 <= t2) {
+ return sigAdd(t1, t2);
+
+ } else {
+ return sigAdd(t2, t1);
+ }
+}
+
+/**
+ * return the corresponding normalized expression tree
+ */
+
+Tree aterm::normalizedTree() const
+{
+ // store positive and negative tems by order and sign
+ // positive terms are stored in P[]
+ // negative terms are inverted (made positive) and stored in N[]
+ Tree P[4], N[4];
+
+ // prepare
+ for (int order = 0; order < 4; order++) P[order] = N[order] = tree(0);
+
+ // sum by order and sign
+ for (SM::const_iterator p = fSig2MTerms.begin(); p != fSig2MTerms.end(); p++) {
+ const mterm& m = p->second;
+ if (m.isNegative()) {
+ Tree t = m.normalizedTree(false, true);
+ int order = getSigOrder(t);
+ N[order] = simplifyingAdd(N[order],t);
+ } else {
+ Tree t = m.normalizedTree();
+ int order = getSigOrder(t);
+ P[order] = simplifyingAdd(P[order],t);
+ }
+ }
+
+ // combine sums
+ Tree SUM = tree(0);
+ for (int order = 0; order < 4; order++) {
+ if (!isZero(P[order])) {
+ SUM = simplifyingAdd(SUM,P[order]);
+ }
+ if (!isZero(N[order])) { // we have to substract
+ if (isZero(SUM) && (order < 3)) {
+ // we postpone substraction
+ N[order+1] = simplifyingAdd(N[order], N[order+1]);
+ } else {
+ SUM = sigSub(SUM, N[order]);
+ }
+ }
+ }
+
+ assert(SUM);
+ return SUM;
+}
+
+
+/**
+ * print an aterm in a human readable format
+ */
+ostream& aterm::print(ostream& dst) const
+{
+ if (fSig2MTerms.empty()) {
+ dst << "AZERO";
+ } else {
+ const char* sep = "";
+ for (SM::const_iterator p = fSig2MTerms.begin(); p != fSig2MTerms.end(); p++) {
+ dst << sep << p->second;
+ sep = " + ";
+ }
+ }
+
+ return dst;
+}
+
+
+/**
+ * Add in place an additive expression tree Go down t recursively looking
+ * for additions and substractions
+ */
+const aterm& aterm::operator += (Tree t)
+{
+ int op;
+ Tree x,y;
+
+ assert(t!=0);
+
+ if (isSigBinOp(t, &op, x, y) && (op == kAdd)) {
+ *this += x;
+ *this += y;
+
+ } else if (isSigBinOp(t, &op, x, y) && (op == kSub)) {
+ *this += x;
+ *this -= y;
+
+ } else {
+ mterm m(t);
+ *this += m;
+ }
+ return *this;
+}
+
+
+/**
+ * Substract in place an additive expression tree Go down t recursively looking
+ * for additions and substractions
+ */
+const aterm& aterm::operator -= (Tree t)
+{
+ int op;
+ Tree x,y;
+
+ assert(t!=0);
+
+ if (isSigBinOp(t, &op, x, y) && (op == kAdd)) {
+ *this -= x;
+ *this -= y;
+
+ } else if (isSigBinOp(t, &op, x, y) && (op == kSub)) {
+ *this -= x;
+ *this += y;
+
+ } else {
+ mterm m(t);
+ *this -= m;
+ }
+ return *this;
+}
+
+
+/**
+ * Add in place an mterm
+ */
+const aterm& aterm::operator += (const mterm& m)
+{
+ #ifdef TRACE
+ cerr << *this << " aterm::+= " << m << endl;
+ #endif
+ Tree sig = m.signatureTree();
+ #ifdef TRACE
+ cerr << "signature " << *sig << endl;
+ #endif
+ SM::const_iterator p = fSig2MTerms.find(sig);
+ if (p == fSig2MTerms.end()) {
+ // its a new mterm
+ fSig2MTerms.insert(make_pair(sig,m));
+ } else {
+ fSig2MTerms[sig] += m;
+ }
+ return *this;
+}
+
+
+/**
+ * Substract in place an mterm
+ */
+const aterm& aterm::operator -= (const mterm& m)
+{
+ //cerr << *this << " aterm::-= " << m << endl;
+ Tree sig = m.signatureTree();
+ //cerr << "signature " << *sig << endl;
+ SM::const_iterator p = fSig2MTerms.find(sig);
+ if (p == fSig2MTerms.end()) {
+ // its a new mterm
+ fSig2MTerms.insert(make_pair(sig,m*mterm(-1)));
+ } else {
+ fSig2MTerms[sig] -= m;
+ }
+ return *this;
+}
+
+mterm aterm::greatestDivisor() const
+{
+ int maxComplexity = 0;
+ mterm maxGCD(1);
+
+ for (SM::const_iterator p1 = fSig2MTerms.begin(); p1 != fSig2MTerms.end(); p1++) {
+ for (SM::const_iterator p2 = p1; p2 != fSig2MTerms.end(); p2++) {
+ if (p2 != p1) {
+ mterm g = gcd(p1->second,p2->second);
+ if (g.complexity()>maxComplexity) {
+ maxComplexity = g.complexity();
+ maxGCD = g;
+ }
+ }
+ }
+ }
+ //cerr << "greatestDivisor of " << *this << " is " << maxGCD << endl;
+ return maxGCD;
+}
+
+/**
+ * reorganize the aterm by factorizing d
+ */
+aterm aterm::factorize(const mterm& d)
+{
+ //cerr << "factorize : " << *this << " with " << d << endl;
+ aterm A;
+ aterm Q;
+
+ // separate the multiple of m from the others
+ for (SM::const_iterator p1 = fSig2MTerms.begin(); p1 != fSig2MTerms.end(); p1++) {
+ mterm t = p1->second;
+ if (t.hasDivisor(d)) {
+ mterm q = t/d;
+ //cerr << "q = " << q << endl;
+ Q += q;
+ //cerr << "step Q = " << Q << endl;
+ } else {
+ A += t;
+ //cerr << "step A = " << A << endl;
+ }
+ }
+
+ // combines the two parts
+ //cerr << "d.normalizedTree() " << ppsig(d.normalizedTree()) << endl;
+ //cerr << "Q.normalizedTree() " << ppsig(Q.normalizedTree()) << endl;
+ //Tree tt = sigMul(d.normalizedTree(), Q.normalizedTree());
+ //cerr << "tt " << *tt << endl;
+
+ //Tree ttt = sigAdd(
+ A += sigMul(d.normalizedTree(), Q.normalizedTree());
+ //cerr << "Final A = " << A << endl;
+ //cerr << "Final Tree " << *(A.normalizedTree()) << endl;
+ return A;
+}
+
+
+