1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
31 #include "sigprint.hh"
36 #include "recursivness.hh"
38 #include "sigtyperules.hh"
39 #include "sigraterules.hh"
43 //--------------------------------------------------------------------------
44 // Uncomment to activate type inference tracing
55 ========================================== RATE INFERENCE =========================================
61 /**************************************************************************************************
65 **************************************************************************************************/
67 static Tree
inferreMultiRates(Tree lsig1
, bool& success
);
68 static ostream
& printRateEnvironment(ostream
& fout
, Tree E
);
69 static ostream
& printRateEnvironmentList(ostream
& fout
, Tree LE
);
70 static void doInferreRate(Tree sig
, int* rate
, Tree
& renv
);
71 static void inferreRate(Tree sig
, int* rate
, Tree
& E
);
72 static Tree
addToMultiRates(Tree E1
, Tree LE
, bool& success
);
73 static Tree
addRecursiveSignals(Tree lsig
);
74 static Tree
doAddRecursiveSignals(Tree sig
, Tree accSig
);
75 static Tree
flatRateEnvironmentList(Tree lre
);
77 static int computeRate(Tree sig
, Tree renv
, property
<int>& rateProperty
);
81 /**************************************************************************************************
82 **************************************************************************************************
83 **************************************************************************************************
87 **************************************************************************************************
88 **************************************************************************************************
89 **************************************************************************************************/
92 * Inferre the rate of a list of signals.
94 Tree
inferreMultiRates(Tree lsig1
, bool& success
)
100 Tree lsig2
= addRecursiveSignals(lsig1
);
101 TRACE(cerr
<< "lsig2 = " << *lsig2
<< endl
);
103 while (isList(lsig2
)) {
104 Tree s
= hd(lsig2
); lsig2
= tl(lsig2
);
105 Tree E
; int r
; inferreRate(s
, &r
, E
);
108 cerr
<< "ERROR inferreMultiRates failed 1" << endl
;
116 // combines all the rate environements
119 for (unsigned int i
=0; success
&& i
<envs
.size(); i
++) {
120 LE
= addToMultiRates(envs
[i
], LE
, success
);
122 TRACE(cerr
<< "***multirates :"; printRateEnvironmentList(cerr
, LE
); cerr
<< endl
);
123 Tree RE
= flatRateEnvironmentList(LE
);
124 TRACE(cerr
<< "***flat rate :"; printRateEnvironment(cerr
, RE
); cerr
<< endl
);
131 * Print a rate environment
133 ostream
& printRateEnvironment(ostream
& fout
, Tree E
)
138 fout
<< sep
<< ppsig(hd(hd(E
))) << ":" << tree2int(tl(hd(E
)));
148 * Print a list of rate environments
150 ostream
& printRateEnvironmentList(ostream
& fout
, Tree LE
)
155 fout
<< sep
; printRateEnvironment(fout
, hd(LE
));
165 /**************************************************************************************************
166 **************************************************************************************************
167 **************************************************************************************************
171 **************************************************************************************************
172 **************************************************************************************************
173 **************************************************************************************************/
177 * Greatest common divisor
179 static int TRACED_gcd(int a
, int b
);
181 static int gcd(int a
, int b
)
183 int r
= TRACED_gcd(a
,b
);
184 //cerr << TABBER << "gcd(" << a << ',' << b <<") = " << r << endl;
189 static int TRACED_gcd(int a
, int b
)
191 return (b
==0) ? a
: gcd (b
, a
%b
);
195 * Least common multiple
197 static int lcm(int a
, int b
)
199 int r
= (a
*b
)/gcd(a
,b
);
200 //cerr << TABBER << "lcm(" << a << ',' << b <<") = " << r << endl;
206 * Add to a list of existing signals lsig the list of recursive signals apprearing in lsig
209 static Tree
addRecursiveSignals(Tree lsig
)
211 CTree::startNewVisit();
214 while (isList(lsig
)) {
215 lsig2
= doAddRecursiveSignals(hd(lsig
), lsig2
);
222 static Tree
doAddRecursiveSignals(Tree sig
, Tree accSig
)
224 TRACE(cerr
<< ++TABBER
<< "doAddRecursiveSignals(" << *sig
<< ',' << *accSig
<< ')' << endl
);
225 if ( ! sig
->isAlreadyVisited() ) {
229 if (isProj(sig
,&i
,rsig
) && isRec(rsig
, id
, body
)) {
230 Tree p
= nth(body
,i
);
231 accSig
= doAddRecursiveSignals(p
, cons(p
,accSig
));
233 assert(!isProj(sig
,&i
,rsig
));
235 vector
<Tree
> subsigs
;
236 getSubSignals(sig
,subsigs
,false);
237 for (unsigned int i
=0; i
<subsigs
.size(); i
++) {
238 accSig
= doAddRecursiveSignals(subsigs
[i
], accSig
);
242 TRACE(cerr
<< --TABBER
<< "doAddRecursiveSignals(" << *sig
<< ',' << *accSig
<< ") -> " << *accSig
<< endl
);
246 /** *********************************** RATE ENVIRONMENTS ************************************************
248 A rate environement E = {(s1,r1), (s2,r2), ...} is a set of pairs associating a signal and a rate. The
249 signals are unique : if (s1,r1) and (s2,r2) are in E then s1=s2 => r1=r2.
251 The environment is kept ordered
254 **********************************************************************************************************/
260 * Add a pair signal s1 x rate r1 to rate environment E
262 static Tree
addRateEnv(Tree s1
, int r1
, Tree E
)
267 return cons(cons(s1
,tree(r1
)),E
);
268 } else if (s1
== s2
) {
269 return cons(cons(s1
,tree(r1
)),tl(E
));
271 return cons(hd(E
), addRateEnv(s1
,r1
,tl(E
)));
274 return cons(cons(s1
,tree(r1
)),nil
);
280 * multiply by n all the rates of rate environment E
281 * E={(s1,r1),...} -> E'={(s1,n.r1),...}
283 static Tree
TRACED_multRateEnv(int n
, Tree E
);
285 static Tree
multRateEnv(int n
, Tree E
)
287 TRACE(cerr
<< ++TABBER
<< "multRateEnv(" << n
<< ", " << *E
<< ")" << endl
);
288 Tree result
= TRACED_multRateEnv(n
, E
);
289 TRACE(cerr
<< --TABBER
<< "multRateEnv(" << n
<< ", " << *E
<< ") -> " << *result
<< endl
);
295 static Tree
TRACED_multRateEnv(int n
, Tree E
)
300 int r
= tree2int(tl(p
));
301 Tree q
= cons(k
, tree(r
*n
));
302 return cons(q
, multRateEnv(n
, tl(E
)));
310 * Get value associated to key k in "function" l
311 * returns true if a value was found.
314 static bool getRateEnv(Tree k
, int* i
, Tree l
)
322 return false; // not found
324 *i
= tree2int(tl(hd(l
)));
327 return getRateEnv(k
,i
,tl(l
));
335 * two rate environments are compatible if common rates
336 * are linked by the same ratio
339 static bool checkRatesCompatible(Tree R1
, Tree R2
, int n1
, int n2
)
341 if (isNil(R1
) || isNil(R2
)) {
351 return checkRatesCompatible(tl(R1
), R2
, n1
, n2
);
352 } else if (k1
> k2
) {
353 return checkRatesCompatible(R1
, tl(R2
), n1
, n2
);
358 if (tree2int(v1
)*n1
== tree2int(v2
)*n2
) {
359 return checkRatesCompatible(tl(R1
), tl(R2
), n1
, n2
);
370 * Two rate environments are independent if they don't have any
374 static bool areRatesIndependent(Tree R1
, Tree R2
)
376 if (isNil(R1
) || isNil(R2
)) {
386 return areRatesIndependent(tl(R1
), R2
);
387 } else if (s2
< s1
) {
388 return areRatesIndependent(R1
, tl(R2
));
390 return false; // s1 and s2 are in common
399 * Two rate environments are compatible if common rates
400 * are linked by the same ratio
403 static bool areRatesCompatible(Tree R1
, Tree R2
, int& n1
, int& n2
)
405 if (isNil(R1
) || isNil(R2
)) {
420 return areRatesCompatible(tl(R1
), R2
, n1
, n2
);
422 } else if (k1
> k2
) {
424 return areRatesCompatible(R1
, tl(R2
), n1
, n2
);
428 // we have a common expression
432 int r1
= tree2int(v1
);
433 int r2
= tree2int(v2
);
437 // we update the n1 and n2 coefficients
441 // and we check that the rest of the environments are compatible
442 return checkRatesCompatible(tl(R1
), tl(R2
), n1
, n2
);
449 * Merge two compatible rate environments. Rate environments are
450 * compatible if common expressions have same rate.
451 * Returns the merge environment and success flag
453 static Tree
TRACED_mergeRateEnvironment(Tree R1
, Tree R2
, bool& success
);
455 static Tree
mergeRateEnvironment(Tree R1
, Tree R2
, bool& success
)
457 TRACE(cerr
<< ++TABBER
<< "mergeRateEnvironment(" << *R1
<< ", " << *R2
<< ")" << endl
);
458 Tree result
= TRACED_mergeRateEnvironment(R1
, R2
, success
);
460 TRACE(cerr
<< --TABBER
<< "mergeRateEnvironment(" << *R1
<< ", " << *R2
<< ") -> " << *result
<< endl
);
462 TRACE(cerr
<< --TABBER
<< "mergeRateEnvironment(" << *R1
<< ", " << *R2
<< ") -> FAILED" << endl
);
470 static Tree
TRACED_mergeRateEnvironment(Tree R1
, Tree R2
, bool& success
)
477 } else if (isNil(R2
)) {
492 return cons(p1
, mergeRateEnvironment(tl(R1
), R2
, success
));
494 } else if (k2
< k1
) {
496 return cons(p2
, mergeRateEnvironment(R1
, tl(R2
), success
));
500 // we have a common expression
506 return cons(p2
, mergeRateEnvironment(tl(R1
), tl(R2
), success
));
516 * Merge a list of independent rate environments into a single rate environment
518 static Tree
flatRateEnvironmentList(Tree lre
)
522 while (isList(lre
)) {
523 e
= mergeRateEnvironment(hd(lre
),e
, success
);
524 assert(success
); // can't failed if environments are independant
532 ========================================== RATE INFERENCE =========================================
538 property
<Tree
> gInferreRateProperty
;
540 static void setInferreRateProperty(Tree sig
, int rate
, Tree renv
)
542 gInferreRateProperty
.set(sig
, cons(tree(rate
),renv
));
545 static bool getInferreRateProperty(Tree sig
, int* rate
, Tree
& renv
)
548 if (gInferreRateProperty
.get(sig
, p
)) {
549 *rate
= tree2int(hd(p
));
559 * Inferre rate (and rate environment) of a single signal.
560 * Use a property to cache previous results
562 static void inferreRate(Tree sig
, int* rate
, Tree
& E
)
564 TRACE(cerr
<< ++TABBER
<< "inferreRate(" << ppsig(sig
) << ")" << endl
);
565 if (! getInferreRateProperty(sig
, rate
, E
)) {
566 doInferreRate(sig
, rate
, E
);
567 setInferreRateProperty(sig
, *rate
, E
);
569 TRACE(cerr
<< --TABBER
<< "inferreRate(" << ppsig(sig
) << ") = " << *rate
<< " with " << *E
<< endl
);
574 * Checks that w denotes a positive constant integer signal n
577 static int checkSignalDenotesSize(Tree w
, Tree sig
)
579 // checks that w denotes a positive constant integer signal n
580 SimpleType
* st
= isSimpleType(getCertifiedSigType(w
));
582 if (st
&& st
->nature()==kInt
) {
583 interval i
= st
->getInterval();
584 if (i
.valid
&& i
.lo
>= 0 && i
.lo
== i
.hi
) {
588 cerr
<< "ERROR in expression : " << ppsig(sig
) << endl
;
589 cerr
<< *w
<< " is not a positive constant integer" << endl
;
594 * Inferre the rate (and the rate environment) of a signal.
595 * A zero rate indicates an impossibility
597 static void doInferreRate(Tree sig
, int* rate
, Tree
& E
)
599 Tree w
, x
, rsig
, id
, body
;
602 if ( isSigVectorize(sig
, w
, x
) ) {
604 // -- rate(vectorize(n,x)) = rate(x)/n
606 VectorType
* vt
= isVectorType(getCertifiedSigType(sig
)); assert(vt
);
607 int n
= vt
->size(); assert(n
>0);
609 int r
; inferreRate(x
, &r
, E
);
611 // fine, the rate of x can be divided by n
612 // (note: this is compatible with r==0 indicating that x has no rate)
615 // we need to scale the rates involved in x
618 E
= multRateEnv(m
/r
, E
);
621 } else if ( isSigDownSample(sig
, w
, x
) ) {
623 // -- rate(down(n,x) = rate(x)/n
625 int n
= checkSignalDenotesSize(w
, sig
);
627 int r
; inferreRate(x
, &r
, E
);
630 // fine, the rate of x can be divided by n
631 // (note: this is compatible with r==0 indicating that x has no rate)
634 // we need to scale the rates involved in x
637 E
= multRateEnv(m
/r
, E
);
640 } else if ( isSigUpSample(sig
, w
, x
) ) {
642 // -- rate(up(n,x) = rate(x)*n
644 int n
= checkSignalDenotesSize(w
, sig
);
645 int r
; inferreRate(x
, &r
, E
);
648 } else if ( isSigSerialize(sig
, x
)) {
650 // -- rate(serialize(x) = rate(x)*n [with Type(x) = vector(n,T)]
652 VectorType
* vt
= isVectorType(getCertifiedSigType(x
)); assert(vt
);
654 int r
; inferreRate(x
, &r
, E
);
655 *rate
= vt
->size() * r
;
657 } else if ( isSigInput(sig
, &in
)) {
659 // -- rate(input(x)) = 1
662 E
= addRateEnv(sig
,1,nil
);
664 } else if (isProj(sig
,&i
,rsig
) && isRec(rsig
, id
, body
)) {
666 // -- rate(proj(i, x=(E0,E1,...))) = 1
669 E
= addRateEnv(sig
,1,nil
);
674 // -- rate(op(s1, s2)) = lcm(rate(s1), rate(s2))
676 vector
<Tree
> subsigs
;
677 unsigned int n
= getSubSignals(sig
, subsigs
, false);
685 // -- rate(op(s1, s2)) = lcm(rate(s1), rate(s2))
687 vector
<int> subrates(n
);
688 vector
<Tree
> subenvs(n
);
691 for (unsigned int i
=0; i
<n
; i
++) {
692 inferreRate(subsigs
[i
], &subrates
[i
], subenvs
[i
]);
693 lcmrate
= lcm(subrates
[i
], lcmrate
);
696 // Try to merge all (scaled) rate environments
698 bool success
= false;
700 for (unsigned int i
=0; i
<n
; i
++) {
701 M
= mergeRateEnvironment(M
, multRateEnv(lcmrate
/subrates
[i
], subenvs
[i
]), success
);
709 *rate
= lcmrate
; E
= M
;
716 * Try to add a rate environment E1 to a list of independent rate environments LE
717 * Returns a list of independent rate environments
719 static Tree
addToMultiRates(Tree E1
, Tree LE
, bool& success
);
720 static Tree
TRACED_addToMultiRates(Tree E1
, Tree LE
, bool& success
);
722 static Tree
addToMultiRates(Tree E1
, Tree LE
, bool& success
)
724 TRACE(cerr
<< ++TABBER
<< "addToMultiRates(" << *E1
<< ", " << *LE
<< ")" << endl
);
725 Tree result
= TRACED_addToMultiRates(E1
, LE
, success
);
727 TRACE(cerr
<< --TABBER
<< "addToMultiRates(" << *E1
<< ", " << *LE
<< ") -> " << *result
<< endl
);
729 TRACE(cerr
<< --TABBER
<< "addToMultiRates(" << *E1
<< ", " << *LE
<< ") -> FAILED" << endl
);
735 static Tree
TRACED_addToMultiRates(Tree E1
, Tree LE
, bool& success
)
742 if (areRatesIndependent(E1
,E2
)) {
743 return cons(E2
, addToMultiRates(E1
, tl(LE
), success
));
746 if (areRatesCompatible(E1
, E2
, n1
, n2
)) {
747 Tree M
= mergeRateEnvironment(multRateEnv(n1
,E1
), multRateEnv(n2
,E2
), success
);
749 return addToMultiRates(M
, tl(LE
), success
);
762 RateInferrer::RateInferrer(Tree lsig
)
764 TRACE(cerr
<< "ENTRE RateInferrer constructor of " << *lsig
<< endl
);
765 if (! (isList(lsig
) | isNil(lsig
))) {
766 lsig
= cons(lsig
,nil
);
768 fFullList
= addRecursiveSignals(lsig
);
769 fRateEnv
= inferreMultiRates(lsig
, fSuccess
);
771 // nit the rate properties for the expressions in the environment
772 for (Tree L
=fRateEnv
; isList(L
); L
= tl(L
)) {
774 fRateProperty
.set(hd(p
),tree2int(tl(p
)));
777 TRACE(cerr
<< "EXIT RateInferrer constructor" << *lsig
<< endl
);
780 // returns the rate of sig assuming that sig is a subexpression of lsig
781 int RateInferrer::rate(Tree sig
)
787 } else if (fRateProperty
.get(sig
, r
)) {
790 r
= computeRate(sig
);
791 fRateProperty
.set(sig
, r
);
796 int RateInferrer::computeRate(Tree sig
)
798 Tree n
, x
, rsig
, id
, body
;
801 if ( isSigInput(sig
, &i
)) {
803 TRACE(cerr
<< "ERROR: Input " << i
<< " should have a rate" << endl
);
806 } else if ( isProj(sig
,&i
,rsig
) && isRec(rsig
, id
, body
) ) {
808 TRACE(cerr
<< "ERROR: Recursive signal " << *sig
<< " should have a rate" << endl
);
811 } else if ( isSigVectorize(sig
, n
, x
) ) {
813 VectorType
* vt
= isVectorType(getCertifiedSigType(sig
));
815 return rate(x
) / vt
->size();
817 } else if ( isSigSerialize(sig
, x
)) {
819 VectorType
* vt
= isVectorType(getCertifiedSigType(x
));
821 return vt
->size() * rate(x
);
823 } else if ( isSigUpSample(sig
, n
, x
) ) {
825 int i
= checkSignalDenotesSize(n
,sig
);
828 } else if ( isSigDownSample(sig
, n
, x
) ) {
830 int i
= checkSignalDenotesSize(n
,sig
);
837 vector
<Tree
> subsigs
;
838 vector
<int> subrates
;
839 int n
= getSubSignals(sig
, subsigs
, false);
841 // we don't depend of any subsignals, then the rate is 1
844 // we depend on subsignals, the rate is the highest one
845 // moreover the highest one is a multiple of all other
849 for (unsigned int i
=0; i
<subsigs
.size(); i
++) {
850 int r
= rate(subsigs
[i
]);
851 maxrate
= max(r
, maxrate
);
852 lcmrate
= lcm(r
, lcmrate
);
853 if (lcmrate
!= maxrate
) {
854 return 0; // rates of arguments are incompatible