|
FAUST compiler
0.9.9.6b8
|
00001 #include "mterm.hh" 00002 #include "signals.hh" 00003 #include "ppsig.hh" 00004 #include "xtended.hh" 00005 #include <assert.h> 00006 //static void collectMulTerms (Tree& coef, map<Tree,int>& M, Tree t, bool invflag=false); 00007 00008 #undef TRACE 00009 00010 using namespace std; 00011 00012 typedef map<Tree,int> MP; 00013 00014 mterm::mterm () : fCoef(sigInt(0)) {} 00015 mterm::mterm (int k) : fCoef(sigInt(k)) {} 00016 mterm::mterm (double k) : fCoef(sigReal(k)) {} // cerr << "DOUBLE " << endl; } 00017 mterm::mterm (const mterm& m) : fCoef(m.fCoef), fFactors(m.fFactors) {} 00018 00022 mterm::mterm (Tree t) : fCoef(sigInt(1)) 00023 { 00024 //cerr << "mterm::mterm (Tree t) : " << ppsig(t) << endl; 00025 *this *= t; 00026 //cerr << "MTERM(" << ppsig(t) << ") -> " << *this << endl; 00027 } 00028 00032 bool mterm::isNotZero() const 00033 { 00034 return !isZero(fCoef); 00035 } 00036 00040 bool mterm::isNegative() const 00041 { 00042 return !isGEZero(fCoef); 00043 } 00044 00048 ostream& mterm::print(ostream& dst) const 00049 { 00050 const char* sep = ""; 00051 if (!isOne(fCoef) || fFactors.empty()) { dst << ppsig(fCoef); sep = " * "; } 00052 //if (true) { dst << ppsig(fCoef); sep = " * "; } 00053 for (MP::const_iterator p = fFactors.begin(); p != fFactors.end(); p++) { 00054 dst << sep << ppsig(p->first); 00055 if (p->second != 1) dst << "**" << p->second; 00056 sep = " * "; 00057 } 00058 return dst; 00059 } 00060 00065 int mterm::complexity() const 00066 { 00067 int c = isOne(fCoef) ? 0 : 1; 00068 for (MP::const_iterator p = fFactors.begin(); p != fFactors.end(); ++p) { 00069 c += (1+getSigOrder(p->first))*abs(p->second); 00070 } 00071 return c; 00072 } 00073 00077 static bool isSigPow(Tree sig, Tree& x, int& n) 00078 { 00079 //cerr << "isSigPow("<< *sig << ')' << endl; 00080 xtended* p = (xtended*) getUserData(sig); 00081 if (p == gPowPrim) { 00082 if (isSigInt(sig->branch(1), &n)) { 00083 x = sig->branch(0); 00084 //cerr << "factor of isSigPow " << *x << endl; 00085 return true; 00086 } 00087 } 00088 return false; 00089 } 00090 00094 static Tree sigPow(Tree x, int p) 00095 { 00096 return tree(gPowPrim->symbol(), x, sigInt(p)); 00097 } 00098 00103 const mterm& mterm::operator *= (Tree t) 00104 { 00105 int op, n; 00106 Tree x,y; 00107 00108 assert(t!=0); 00109 00110 if (isNum(t)) { 00111 fCoef = mulNums(fCoef,t); 00112 00113 } else if (isSigBinOp(t, &op, x, y) && (op == kMul)) { 00114 *this *= x; 00115 *this *= y; 00116 00117 } else if (isSigBinOp(t, &op, x, y) && (op == kDiv)) { 00118 *this *= x; 00119 *this /= y; 00120 00121 } else { 00122 if (isSigPow(t,x,n)) { 00123 fFactors[x] += n; 00124 } else { 00125 fFactors[t] += 1; 00126 } 00127 } 00128 return *this; 00129 } 00130 00135 const mterm& mterm::operator /= (Tree t) 00136 { 00137 //cerr << "division en place : " << *this << " / " << ppsig(t) << endl; 00138 int op,n; 00139 Tree x,y; 00140 00141 assert(t!=0); 00142 00143 if (isNum(t)) { 00144 fCoef = divExtendedNums(fCoef,t); 00145 00146 } else if (isSigBinOp(t, &op, x, y) && (op == kMul)) { 00147 *this /= x; 00148 *this /= y; 00149 00150 } else if (isSigBinOp(t, &op, x, y) && (op == kDiv)) { 00151 *this /= x; 00152 *this *= y; 00153 00154 } else { 00155 if (isSigPow(t,x,n)) { 00156 fFactors[x] -= n; 00157 } else { 00158 fFactors[t] -= 1; 00159 } 00160 } 00161 return *this; 00162 } 00163 00167 const mterm& mterm::operator = (const mterm& m) 00168 { 00169 fCoef = m.fCoef; 00170 fFactors = m.fFactors; 00171 return *this; 00172 } 00173 00177 void mterm::cleanup() 00178 { 00179 if (isZero(fCoef)) { 00180 fFactors.clear(); 00181 } else { 00182 for (MP::iterator p = fFactors.begin(); p != fFactors.end(); ) { 00183 if (p->second == 0) { 00184 fFactors.erase(p++); 00185 } else { 00186 p++; 00187 } 00188 } 00189 } 00190 } 00191 00196 const mterm& mterm::operator += (const mterm& m) 00197 { 00198 if (isZero(m.fCoef)) { 00199 // nothing to do 00200 } else if (isZero(fCoef)) { 00201 // copy of m 00202 fCoef = m.fCoef; 00203 fFactors = m.fFactors; 00204 } else { 00205 // only add mterms of same signature 00206 assert(signatureTree() == m.signatureTree()); 00207 fCoef = addNums(fCoef, m.fCoef); 00208 } 00209 cleanup(); 00210 return *this; 00211 } 00212 00217 const mterm& mterm::operator -= (const mterm& m) 00218 { 00219 if (isZero(m.fCoef)) { 00220 // nothing to do 00221 } else if (isZero(fCoef)) { 00222 // minus of m 00223 fCoef = minusNum(m.fCoef); 00224 fFactors = m.fFactors; 00225 } else { 00226 // only add mterms of same signature 00227 assert(signatureTree() == m.signatureTree()); 00228 fCoef = subNums(fCoef, m.fCoef); 00229 } 00230 cleanup(); 00231 return *this; 00232 } 00233 00237 const mterm& mterm::operator *= (const mterm& m) 00238 { 00239 fCoef = mulNums(fCoef,m.fCoef); 00240 for (MP::const_iterator p = m.fFactors.begin(); p != m.fFactors.end(); p++) { 00241 fFactors[p->first] += p->second; 00242 } 00243 cleanup(); 00244 return *this; 00245 } 00246 00250 const mterm& mterm::operator /= (const mterm& m) 00251 { 00252 //cerr << "division en place : " << *this << " / " << m << endl; 00253 fCoef = divExtendedNums(fCoef,m.fCoef); 00254 for (MP::const_iterator p = m.fFactors.begin(); p != m.fFactors.end(); p++) { 00255 fFactors[p->first] -= p->second; 00256 } 00257 cleanup(); 00258 return *this; 00259 } 00260 00264 mterm mterm::operator * (const mterm& m) const 00265 { 00266 mterm r(*this); 00267 r *= m; 00268 return r; 00269 } 00270 00274 mterm mterm::operator / (const mterm& m) const 00275 { 00276 mterm r(*this); 00277 r /= m; 00278 return r; 00279 } 00280 00284 static int common(int a, int b) 00285 { 00286 if (a > 0 & b > 0) { 00287 return min(a,b); 00288 } else if (a < 0 & b < 0) { 00289 return max(a,b); 00290 } else { 00291 return 0; 00292 } 00293 } 00294 00295 00299 mterm gcd (const mterm& m1, const mterm& m2) 00300 { 00301 //cerr << "GCD of " << m1 << " and " << m2 << endl; 00302 00303 Tree c = (m1.fCoef == m2.fCoef) ? m1.fCoef : tree(1); // common coefficient (real gcd not needed) 00304 mterm R(c); 00305 for (MP::const_iterator p1 = m1.fFactors.begin(); p1 != m1.fFactors.end(); p1++) { 00306 Tree t = p1->first; 00307 MP::const_iterator p2 = m2.fFactors.find(t); 00308 if (p2 != m2.fFactors.end()) { 00309 int v1 = p1->second; 00310 int v2 = p2->second; 00311 int c = common(v1,v2); 00312 if (c != 0) { 00313 R.fFactors[t] = c; 00314 } 00315 } 00316 } 00317 //cerr << "GCD of " << m1 << " and " << m2 << " is : " << R << endl; 00318 return R; 00319 } 00320 00325 static bool contains(int a, int b) 00326 { 00327 return (b == 0) || (a/b > 0); 00328 } 00329 00337 bool mterm::hasDivisor (const mterm& n) const 00338 { 00339 for (MP::const_iterator p1 = n.fFactors.begin(); p1 != n.fFactors.end(); p1++) { 00340 // for each factor f**q of m 00341 Tree f = p1->first; 00342 int v = p1->second; 00343 00344 // check that f is also a factor of *this 00345 MP::const_iterator p2 = fFactors.find(f); 00346 if (p2 == fFactors.end()) return false; 00347 00348 // analyze quantities 00349 int u = p2->second; 00350 if (! contains(u,v) ) return false; 00351 } 00352 return true; 00353 } 00354 00362 static Tree buildPowTerm(Tree f, int q) 00363 { 00364 assert(f); 00365 assert(q>0); 00366 if (q>1) { 00367 return sigPow(f, q); 00368 } else { 00369 return f; 00370 } 00371 } 00372 00376 static void combineMulLeft(Tree& R, Tree A) 00377 { 00378 if (R && A) R = sigMul(R,A); 00379 else if (A) R = A; 00380 else exit(1); 00381 } 00382 00386 static void combineDivLeft(Tree& R, Tree A) 00387 { 00388 if (R && A) R = sigDiv(R,A); 00389 else if (A) R = sigDiv(tree(1.0f),A); 00390 else exit(1); 00391 } 00392 00396 static void combineMulDiv(Tree& M, Tree& D, Tree f, int q) 00397 { 00398 #ifdef TRACE 00399 cerr << "combineMulDiv (" << M << "/" << D << "*" << ppsig(f)<< "**" << q << endl; 00400 #endif 00401 if (f) { 00402 assert(q != 0); 00403 if (q > 0) { 00404 combineMulLeft(M, buildPowTerm(f,q)); 00405 } else if (q < 0) { 00406 combineMulLeft(D, buildPowTerm(f,-q)); 00407 } 00408 } 00409 } 00410 00411 00416 Tree mterm::signatureTree() const 00417 { 00418 return normalizedTree(true); 00419 } 00420 00427 Tree mterm::normalizedTree(bool signatureMode, bool negativeMode) const 00428 { 00429 if (fFactors.empty() || isZero(fCoef)) { 00430 // it's a pure number 00431 if (signatureMode) return tree(1); 00432 if (negativeMode) return minusNum(fCoef); 00433 else return fCoef; 00434 } else { 00435 // it's not a pure number, it has factors 00436 Tree A[4], B[4]; 00437 00438 // group by order 00439 for (int order = 0; order < 4; order++) { 00440 A[order] = 0; B[order] = 0; 00441 for (MP::const_iterator p = fFactors.begin(); p != fFactors.end(); p++) { 00442 Tree f = p->first; // f = factor 00443 int q = p->second; // q = power of f 00444 if (f && q && getSigOrder(f)==order) { 00445 00446 combineMulDiv (A[order], B[order], f, q); 00447 } 00448 } 00449 } 00450 if (A[0] != 0) cerr << "A[0] == " << *A[0] << endl; 00451 if (B[0] != 0) cerr << "B[0] == " << *B[0] << endl; 00452 // en principe ici l'order zero est vide car il correspond au coef numerique 00453 assert(A[0] == 0); 00454 assert(B[0] == 0); 00455 00456 // we only use a coeficient if it differes from 1 and if we are not in signature mode 00457 if (! (signatureMode | isOne(fCoef))) { 00458 A[0] = (negativeMode) ? minusNum(fCoef) : fCoef; 00459 } 00460 00461 if (signatureMode) { 00462 A[0] = 0; 00463 } else if (negativeMode) { 00464 if (isMinusOne(fCoef)) { A[0] = 0; } else { A[0] = minusNum(fCoef); } 00465 } else if (isOne(fCoef)) { 00466 A[0] = 0; 00467 } else { 00468 A[0] = fCoef; 00469 } 00470 00471 // combine each order separately : R[i] = A[i]/B[i] 00472 Tree RR = 0; 00473 for (int order = 0; order < 4; order++) { 00474 if (A[order] && B[order]) combineMulLeft(RR,sigDiv(A[order],B[order])); 00475 else if (A[order]) combineMulLeft(RR,A[order]); 00476 else if (B[order]) combineDivLeft(RR,B[order]); 00477 } 00478 if (RR == 0) RR = tree(1); // a verifier ******************* 00479 00480 assert(RR); 00481 //cerr << "Normalized Tree of " << *this << " is " << ppsig(RR) << endl; 00482 return RR; 00483 } 00484 } 00485
1.8.0