X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpretor/preprocessor/faust-0.9.47mr3/compiler/normalize/mterm.cpp diff --git a/interpretor/preprocessor/faust-0.9.47mr3/compiler/normalize/mterm.cpp b/interpretor/preprocessor/faust-0.9.47mr3/compiler/normalize/mterm.cpp deleted file mode 100644 index 1f8bd2d..0000000 --- a/interpretor/preprocessor/faust-0.9.47mr3/compiler/normalize/mterm.cpp +++ /dev/null @@ -1,485 +0,0 @@ -#include "mterm.hh" -#include "signals.hh" -#include "ppsig.hh" -#include "xtended.hh" -#include -//static void collectMulTerms (Tree& coef, map& M, Tree t, bool invflag=false); - -#undef TRACE - -using namespace std; - -typedef map MP; - -mterm::mterm () : fCoef(sigInt(0)) {} -mterm::mterm (int k) : fCoef(sigInt(k)) {} -mterm::mterm (double k) : fCoef(sigReal(k)) {} // cerr << "DOUBLE " << endl; } -mterm::mterm (const mterm& m) : fCoef(m.fCoef), fFactors(m.fFactors) {} - -/** - * create a mterm from a tree sexpression - */ -mterm::mterm (Tree t) : fCoef(sigInt(1)) -{ - //cerr << "mterm::mterm (Tree t) : " << ppsig(t) << endl; - *this *= t; - //cerr << "MTERM(" << ppsig(t) << ") -> " << *this << endl; -} - -/** - * true if mterm doesn't represent number 0 - */ -bool mterm::isNotZero() const -{ - return !isZero(fCoef); -} - -/** - * true if mterm doesn't represent number 0 - */ -bool mterm::isNegative() const -{ - return !isGEZero(fCoef); -} - -/** - * print a mterm in a human readable format - */ -ostream& mterm::print(ostream& dst) const -{ - const char* sep = ""; - if (!isOne(fCoef) || fFactors.empty()) { dst << ppsig(fCoef); sep = " * "; } - //if (true) { dst << ppsig(fCoef); sep = " * "; } - for (MP::const_iterator p = fFactors.begin(); p != fFactors.end(); p++) { - dst << sep << ppsig(p->first); - if (p->second != 1) dst << "**" << p->second; - sep = " * "; - } - return dst; -} - -/** - * Compute the "complexity" of a mterm, that is the number of - * factors it contains (weighted by the importance of these factors) - */ -int mterm::complexity() const -{ - int c = isOne(fCoef) ? 0 : 1; - for (MP::const_iterator p = fFactors.begin(); p != fFactors.end(); ++p) { - c += (1+getSigOrder(p->first))*abs(p->second); - } - return c; -} - -/** - * match x^p with p:int - */ -static bool isSigPow(Tree sig, Tree& x, int& n) -{ - //cerr << "isSigPow("<< *sig << ')' << endl; - xtended* p = (xtended*) getUserData(sig); - if (p == gPowPrim) { - if (isSigInt(sig->branch(1), &n)) { - x = sig->branch(0); - //cerr << "factor of isSigPow " << *x << endl; - return true; - } - } - return false; -} - -/** - * produce x^p with p:int - */ -static Tree sigPow(Tree x, int p) -{ - return tree(gPowPrim->symbol(), x, sigInt(p)); -} - -/** - * Multiple a mterm by an expression tree t. Go down recursively looking - * for multiplications and divisions - */ -const mterm& mterm::operator *= (Tree t) -{ - int op, n; - Tree x,y; - - assert(t!=0); - - if (isNum(t)) { - fCoef = mulNums(fCoef,t); - - } else if (isSigBinOp(t, &op, x, y) && (op == kMul)) { - *this *= x; - *this *= y; - - } else if (isSigBinOp(t, &op, x, y) && (op == kDiv)) { - *this *= x; - *this /= y; - - } else { - if (isSigPow(t,x,n)) { - fFactors[x] += n; - } else { - fFactors[t] += 1; - } - } - return *this; -} - -/** - * Divide a mterm by an expression tree t. Go down recursively looking - * for multiplications and divisions - */ -const mterm& mterm::operator /= (Tree t) -{ - //cerr << "division en place : " << *this << " / " << ppsig(t) << endl; - int op,n; - Tree x,y; - - assert(t!=0); - - if (isNum(t)) { - fCoef = divExtendedNums(fCoef,t); - - } else if (isSigBinOp(t, &op, x, y) && (op == kMul)) { - *this /= x; - *this /= y; - - } else if (isSigBinOp(t, &op, x, y) && (op == kDiv)) { - *this /= x; - *this *= y; - - } else { - if (isSigPow(t,x,n)) { - fFactors[x] -= n; - } else { - fFactors[t] -= 1; - } - } - return *this; -} - -/** - * replace the content with a copy of m - */ -const mterm& mterm::operator = (const mterm& m) -{ - fCoef = m.fCoef; - fFactors = m.fFactors; - return *this; -} - -/** - * Clean a mterm by removing x**0 factors - */ -void mterm::cleanup() -{ - if (isZero(fCoef)) { - fFactors.clear(); - } else { - for (MP::iterator p = fFactors.begin(); p != fFactors.end(); ) { - if (p->second == 0) { - fFactors.erase(p++); - } else { - p++; - } - } - } -} - -/** - * Add in place an mterm. As we want the result to be - * a mterm therefore essentially mterms of same signature can be added - */ -const mterm& mterm::operator += (const mterm& m) -{ - if (isZero(m.fCoef)) { - // nothing to do - } else if (isZero(fCoef)) { - // copy of m - fCoef = m.fCoef; - fFactors = m.fFactors; - } else { - // only add mterms of same signature - assert(signatureTree() == m.signatureTree()); - fCoef = addNums(fCoef, m.fCoef); - } - cleanup(); - return *this; -} - -/** - * Substract in place an mterm. As we want the result to be - * a mterm therefore essentially mterms of same signature can be substracted - */ -const mterm& mterm::operator -= (const mterm& m) -{ - if (isZero(m.fCoef)) { - // nothing to do - } else if (isZero(fCoef)) { - // minus of m - fCoef = minusNum(m.fCoef); - fFactors = m.fFactors; - } else { - // only add mterms of same signature - assert(signatureTree() == m.signatureTree()); - fCoef = subNums(fCoef, m.fCoef); - } - cleanup(); - return *this; -} - -/** - * Multiply a mterm by the content of another mterm - */ -const mterm& mterm::operator *= (const mterm& m) -{ - fCoef = mulNums(fCoef,m.fCoef); - for (MP::const_iterator p = m.fFactors.begin(); p != m.fFactors.end(); p++) { - fFactors[p->first] += p->second; - } - cleanup(); - return *this; -} - -/** - * Divide a mterm by the content of another mterm - */ -const mterm& mterm::operator /= (const mterm& m) -{ - //cerr << "division en place : " << *this << " / " << m << endl; - fCoef = divExtendedNums(fCoef,m.fCoef); - for (MP::const_iterator p = m.fFactors.begin(); p != m.fFactors.end(); p++) { - fFactors[p->first] -= p->second; - } - cleanup(); - return *this; -} - -/** - * Multiply two mterms - */ -mterm mterm::operator * (const mterm& m) const -{ - mterm r(*this); - r *= m; - return r; -} - -/** - * Divide two mterms - */ -mterm mterm::operator / (const mterm& m) const -{ - mterm r(*this); - r /= m; - return r; -} - -/** - * return the "common quantity" of two numbers - */ -static int common(int a, int b) -{ - if (a > 0 & b > 0) { - return min(a,b); - } else if (a < 0 & b < 0) { - return max(a,b); - } else { - return 0; - } -} - - -/** - * return a mterm that is the greatest common divisor of two mterms - */ -mterm gcd (const mterm& m1, const mterm& m2) -{ - //cerr << "GCD of " << m1 << " and " << m2 << endl; - - Tree c = (m1.fCoef == m2.fCoef) ? m1.fCoef : tree(1); // common coefficient (real gcd not needed) - mterm R(c); - for (MP::const_iterator p1 = m1.fFactors.begin(); p1 != m1.fFactors.end(); p1++) { - Tree t = p1->first; - MP::const_iterator p2 = m2.fFactors.find(t); - if (p2 != m2.fFactors.end()) { - int v1 = p1->second; - int v2 = p2->second; - int c = common(v1,v2); - if (c != 0) { - R.fFactors[t] = c; - } - } - } - //cerr << "GCD of " << m1 << " and " << m2 << " is : " << R << endl; - return R; -} - -/** - * We say that a "contains" b if a/b > 0. For example 3 contains 2 and - * -4 contains -2, but 3 doesn't contains -2 and -3 doesn't contains 1 - */ -static bool contains(int a, int b) -{ - return (b == 0) || (a/b > 0); -} - -/** - * Check if M accept N has a divisor. We can say that N is - * a divisor of M if M = N*Q and the complexity is preserved : - * complexity(M) = complexity(N)+complexity(Q) - * x**u has divisor x**v if u >= v - * x**-u has divisor x**-v if -u <= -v - */ -bool mterm::hasDivisor (const mterm& n) const -{ - for (MP::const_iterator p1 = n.fFactors.begin(); p1 != n.fFactors.end(); p1++) { - // for each factor f**q of m - Tree f = p1->first; - int v = p1->second; - - // check that f is also a factor of *this - MP::const_iterator p2 = fFactors.find(f); - if (p2 == fFactors.end()) return false; - - // analyze quantities - int u = p2->second; - if (! contains(u,v) ) return false; - } - return true; -} - -/** - * produce the canonical tree correspoding to a mterm - */ - -/** - * Build a power term of type f**q -> (((f.f).f)..f) with q>0 - */ -static Tree buildPowTerm(Tree f, int q) -{ - assert(f); - assert(q>0); - if (q>1) { - return sigPow(f, q); - } else { - return f; - } -} - -/** - * Combine R and A doing R = R*A or R = A - */ -static void combineMulLeft(Tree& R, Tree A) -{ - if (R && A) R = sigMul(R,A); - else if (A) R = A; - else exit(1); -} - -/** - * Combine R and A doing R = R*A or R = A - */ -static void combineDivLeft(Tree& R, Tree A) -{ - if (R && A) R = sigDiv(R,A); - else if (A) R = sigDiv(tree(1.0f),A); - else exit(1); -} - -/** - * Do M = M * f**q or D = D * f**-q - */ -static void combineMulDiv(Tree& M, Tree& D, Tree f, int q) -{ - #ifdef TRACE - cerr << "combineMulDiv (" << M << "/" << D << "*" << ppsig(f)<< "**" << q << endl; - #endif - if (f) { - assert(q != 0); - if (q > 0) { - combineMulLeft(M, buildPowTerm(f,q)); - } else if (q < 0) { - combineMulLeft(D, buildPowTerm(f,-q)); - } - } -} - - -/** - * returns a normalized (canonical) tree expression of structure : - * ((v1/v2)*(c1/c2))*(s1/s2) - */ -Tree mterm::signatureTree() const -{ - return normalizedTree(true); -} - -/** - * returns a normalized (canonical) tree expression of structure : - * ((k*(v1/v2))*(c1/c2))*(s1/s2) - * In signature mode the fCoef factor is ommited - * In negativeMode the sign of the fCoef factor is inverted - */ -Tree mterm::normalizedTree(bool signatureMode, bool negativeMode) const -{ - if (fFactors.empty() || isZero(fCoef)) { - // it's a pure number - if (signatureMode) return tree(1); - if (negativeMode) return minusNum(fCoef); - else return fCoef; - } else { - // it's not a pure number, it has factors - Tree A[4], B[4]; - - // group by order - for (int order = 0; order < 4; order++) { - A[order] = 0; B[order] = 0; - for (MP::const_iterator p = fFactors.begin(); p != fFactors.end(); p++) { - Tree f = p->first; // f = factor - int q = p->second; // q = power of f - if (f && q && getSigOrder(f)==order) { - - combineMulDiv (A[order], B[order], f, q); - } - } - } - if (A[0] != 0) cerr << "A[0] == " << *A[0] << endl; - if (B[0] != 0) cerr << "B[0] == " << *B[0] << endl; - // en principe ici l'order zero est vide car il correspond au coef numerique - assert(A[0] == 0); - assert(B[0] == 0); - - // we only use a coeficient if it differes from 1 and if we are not in signature mode - if (! (signatureMode | isOne(fCoef))) { - A[0] = (negativeMode) ? minusNum(fCoef) : fCoef; - } - - if (signatureMode) { - A[0] = 0; - } else if (negativeMode) { - if (isMinusOne(fCoef)) { A[0] = 0; } else { A[0] = minusNum(fCoef); } - } else if (isOne(fCoef)) { - A[0] = 0; - } else { - A[0] = fCoef; - } - - // combine each order separately : R[i] = A[i]/B[i] - Tree RR = 0; - for (int order = 0; order < 4; order++) { - if (A[order] && B[order]) combineMulLeft(RR,sigDiv(A[order],B[order])); - else if (A[order]) combineMulLeft(RR,A[order]); - else if (B[order]) combineDivLeft(RR,B[order]); - } - if (RR == 0) RR = tree(1); // a verifier ******************* - - assert(RR); - //cerr << "Normalized Tree of " << *this << " is " << ppsig(RR) << endl; - return RR; - } -} -