6 //static void collectMulTerms (Tree& coef, map<Tree,int>& M, Tree t, bool invflag=false);
12 typedef map
<Tree
,int> MP
;
14 mterm::mterm () : fCoef(sigInt(0)) {}
15 mterm::mterm (int k
) : fCoef(sigInt(k
)) {}
16 mterm::mterm (double k
) : fCoef(sigReal(k
)) {} // cerr << "DOUBLE " << endl; }
17 mterm::mterm (const mterm
& m
) : fCoef(m
.fCoef
), fFactors(m
.fFactors
) {}
20 * create a mterm from a tree sexpression
22 mterm::mterm (Tree t
) : fCoef(sigInt(1))
24 //cerr << "mterm::mterm (Tree t) : " << ppsig(t) << endl;
26 //cerr << "MTERM(" << ppsig(t) << ") -> " << *this << endl;
30 * true if mterm doesn't represent number 0
32 bool mterm::isNotZero() const
34 return !isZero(fCoef
);
38 * true if mterm doesn't represent number 0
40 bool mterm::isNegative() const
42 return !isGEZero(fCoef
);
46 * print a mterm in a human readable format
48 ostream
& mterm::print(ostream
& dst
) const
51 if (!isOne(fCoef
) || fFactors
.empty()) { dst
<< ppsig(fCoef
); sep
= " * "; }
52 //if (true) { dst << ppsig(fCoef); sep = " * "; }
53 for (MP::const_iterator p
= fFactors
.begin(); p
!= fFactors
.end(); p
++) {
54 dst
<< sep
<< ppsig(p
->first
);
55 if (p
->second
!= 1) dst
<< "**" << p
->second
;
62 * Compute the "complexity" of a mterm, that is the number of
63 * factors it contains (weighted by the importance of these factors)
65 int mterm::complexity() const
67 int c
= isOne(fCoef
) ? 0 : 1;
68 for (MP::const_iterator p
= fFactors
.begin(); p
!= fFactors
.end(); ++p
) {
69 c
+= (1+getSigOrder(p
->first
))*abs(p
->second
);
75 * match x^p with p:int
77 static bool isSigPow(Tree sig
, Tree
& x
, int& n
)
79 //cerr << "isSigPow("<< *sig << ')' << endl;
80 xtended
* p
= (xtended
*) getUserData(sig
);
82 if (isSigInt(sig
->branch(1), &n
)) {
84 //cerr << "factor of isSigPow " << *x << endl;
92 * produce x^p with p:int
94 static Tree
sigPow(Tree x
, int p
)
96 return tree(gPowPrim
->symbol(), x
, sigInt(p
));
100 * Multiple a mterm by an expression tree t. Go down recursively looking
101 * for multiplications and divisions
103 const mterm
& mterm::operator *= (Tree t
)
111 fCoef
= mulNums(fCoef
,t
);
113 } else if (isSigBinOp(t
, &op
, x
, y
) && (op
== kMul
)) {
117 } else if (isSigBinOp(t
, &op
, x
, y
) && (op
== kDiv
)) {
122 if (isSigPow(t
,x
,n
)) {
132 * Divide a mterm by an expression tree t. Go down recursively looking
133 * for multiplications and divisions
135 const mterm
& mterm::operator /= (Tree t
)
137 //cerr << "division en place : " << *this << " / " << ppsig(t) << endl;
144 fCoef
= divExtendedNums(fCoef
,t
);
146 } else if (isSigBinOp(t
, &op
, x
, y
) && (op
== kMul
)) {
150 } else if (isSigBinOp(t
, &op
, x
, y
) && (op
== kDiv
)) {
155 if (isSigPow(t
,x
,n
)) {
165 * replace the content with a copy of m
167 const mterm
& mterm::operator = (const mterm
& m
)
170 fFactors
= m
.fFactors
;
175 * Clean a mterm by removing x**0 factors
177 void mterm::cleanup()
182 for (MP::iterator p
= fFactors
.begin(); p
!= fFactors
.end(); ) {
183 if (p
->second
== 0) {
193 * Add in place an mterm. As we want the result to be
194 * a mterm therefore essentially mterms of same signature can be added
196 const mterm
& mterm::operator += (const mterm
& m
)
198 if (isZero(m
.fCoef
)) {
200 } else if (isZero(fCoef
)) {
203 fFactors
= m
.fFactors
;
205 // only add mterms of same signature
206 assert(signatureTree() == m
.signatureTree());
207 fCoef
= addNums(fCoef
, m
.fCoef
);
214 * Substract in place an mterm. As we want the result to be
215 * a mterm therefore essentially mterms of same signature can be substracted
217 const mterm
& mterm::operator -= (const mterm
& m
)
219 if (isZero(m
.fCoef
)) {
221 } else if (isZero(fCoef
)) {
223 fCoef
= minusNum(m
.fCoef
);
224 fFactors
= m
.fFactors
;
226 // only add mterms of same signature
227 assert(signatureTree() == m
.signatureTree());
228 fCoef
= subNums(fCoef
, m
.fCoef
);
235 * Multiply a mterm by the content of another mterm
237 const mterm
& mterm::operator *= (const mterm
& m
)
239 fCoef
= mulNums(fCoef
,m
.fCoef
);
240 for (MP::const_iterator p
= m
.fFactors
.begin(); p
!= m
.fFactors
.end(); p
++) {
241 fFactors
[p
->first
] += p
->second
;
248 * Divide a mterm by the content of another mterm
250 const mterm
& mterm::operator /= (const mterm
& m
)
252 //cerr << "division en place : " << *this << " / " << m << endl;
253 fCoef
= divExtendedNums(fCoef
,m
.fCoef
);
254 for (MP::const_iterator p
= m
.fFactors
.begin(); p
!= m
.fFactors
.end(); p
++) {
255 fFactors
[p
->first
] -= p
->second
;
262 * Multiply two mterms
264 mterm
mterm::operator * (const mterm
& m
) const
274 mterm
mterm::operator / (const mterm
& m
) const
282 * return the "common quantity" of two numbers
284 static int common(int a
, int b
)
288 } else if (a
< 0 & b
< 0) {
297 * return a mterm that is the greatest common divisor of two mterms
299 mterm
gcd (const mterm
& m1
, const mterm
& m2
)
301 //cerr << "GCD of " << m1 << " and " << m2 << endl;
303 Tree c
= (m1
.fCoef
== m2
.fCoef
) ? m1
.fCoef
: tree(1); // common coefficient (real gcd not needed)
305 for (MP::const_iterator p1
= m1
.fFactors
.begin(); p1
!= m1
.fFactors
.end(); p1
++) {
307 MP::const_iterator p2
= m2
.fFactors
.find(t
);
308 if (p2
!= m2
.fFactors
.end()) {
311 int c
= common(v1
,v2
);
317 //cerr << "GCD of " << m1 << " and " << m2 << " is : " << R << endl;
322 * We say that a "contains" b if a/b > 0. For example 3 contains 2 and
323 * -4 contains -2, but 3 doesn't contains -2 and -3 doesn't contains 1
325 static bool contains(int a
, int b
)
327 return (b
== 0) || (a
/b
> 0);
331 * Check if M accept N has a divisor. We can say that N is
332 * a divisor of M if M = N*Q and the complexity is preserved :
333 * complexity(M) = complexity(N)+complexity(Q)
334 * x**u has divisor x**v if u >= v
335 * x**-u has divisor x**-v if -u <= -v
337 bool mterm::hasDivisor (const mterm
& n
) const
339 for (MP::const_iterator p1
= n
.fFactors
.begin(); p1
!= n
.fFactors
.end(); p1
++) {
340 // for each factor f**q of m
344 // check that f is also a factor of *this
345 MP::const_iterator p2
= fFactors
.find(f
);
346 if (p2
== fFactors
.end()) return false;
348 // analyze quantities
350 if (! contains(u
,v
) ) return false;
356 * produce the canonical tree correspoding to a mterm
360 * Build a power term of type f**q -> (((f.f).f)..f) with q>0
362 static Tree
buildPowTerm(Tree f
, int q
)
374 * Combine R and A doing R = R*A or R = A
376 static void combineMulLeft(Tree
& R
, Tree A
)
378 if (R
&& A
) R
= sigMul(R
,A
);
384 * Combine R and A doing R = R*A or R = A
386 static void combineDivLeft(Tree
& R
, Tree A
)
388 if (R
&& A
) R
= sigDiv(R
,A
);
389 else if (A
) R
= sigDiv(tree(1.0f
),A
);
394 * Do M = M * f**q or D = D * f**-q
396 static void combineMulDiv(Tree
& M
, Tree
& D
, Tree f
, int q
)
399 cerr
<< "combineMulDiv (" << M
<< "/" << D
<< "*" << ppsig(f
)<< "**" << q
<< endl
;
404 combineMulLeft(M
, buildPowTerm(f
,q
));
406 combineMulLeft(D
, buildPowTerm(f
,-q
));
413 * returns a normalized (canonical) tree expression of structure :
414 * ((v1/v2)*(c1/c2))*(s1/s2)
416 Tree
mterm::signatureTree() const
418 return normalizedTree(true);
422 * returns a normalized (canonical) tree expression of structure :
423 * ((k*(v1/v2))*(c1/c2))*(s1/s2)
424 * In signature mode the fCoef factor is ommited
425 * In negativeMode the sign of the fCoef factor is inverted
427 Tree
mterm::normalizedTree(bool signatureMode
, bool negativeMode
) const
429 if (fFactors
.empty() || isZero(fCoef
)) {
430 // it's a pure number
431 if (signatureMode
) return tree(1);
432 if (negativeMode
) return minusNum(fCoef
);
435 // it's not a pure number, it has factors
439 for (int order
= 0; order
< 4; order
++) {
440 A
[order
] = 0; B
[order
] = 0;
441 for (MP::const_iterator p
= fFactors
.begin(); p
!= fFactors
.end(); p
++) {
442 Tree f
= p
->first
; // f = factor
443 int q
= p
->second
; // q = power of f
444 if (f
&& q
&& getSigOrder(f
)==order
) {
446 combineMulDiv (A
[order
], B
[order
], f
, q
);
450 if (A
[0] != 0) cerr
<< "A[0] == " << *A
[0] << endl
;
451 if (B
[0] != 0) cerr
<< "B[0] == " << *B
[0] << endl
;
452 // en principe ici l'order zero est vide car il correspond au coef numerique
456 // we only use a coeficient if it differes from 1 and if we are not in signature mode
457 if (! (signatureMode
| isOne(fCoef
))) {
458 A
[0] = (negativeMode
) ? minusNum(fCoef
) : fCoef
;
463 } else if (negativeMode
) {
464 if (isMinusOne(fCoef
)) { A
[0] = 0; } else { A
[0] = minusNum(fCoef
); }
465 } else if (isOne(fCoef
)) {
471 // combine each order separately : R[i] = A[i]/B[i]
473 for (int order
= 0; order
< 4; order
++) {
474 if (A
[order
] && B
[order
]) combineMulLeft(RR
,sigDiv(A
[order
],B
[order
]));
475 else if (A
[order
]) combineMulLeft(RR
,A
[order
]);
476 else if (B
[order
]) combineDivLeft(RR
,B
[order
]);
478 if (RR
== 0) RR
= tree(1); // a verifier *******************
481 //cerr << "Normalized Tree of " << *this << " is " << ppsig(RR) << endl;