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 ************************************************************************/
29 #include "recursivness.hh"
30 #include "sigtyperules.hh"
31 #include "sigorderrules.hh"
32 #include "sigprint.hh"
34 #include "simplify.hh"
38 #include "compatibility.hh"
40 #include "normalize.hh"
45 Tree SIMPLIFIED
= tree(symbol("sigSimplifiedProp"));
46 //static Tree binequiv (Tree sig, int opnum, Tree a, Tree b);
47 static Tree
simplification (Tree sig
);
48 static Tree
sigMap (Tree key
, tfun f
, Tree t
);
50 static Tree
traced_simplification(Tree sig
)
54 cerr
<< ++TABBER
<< "Start simplification of : " << ppsig(sig
) << endl
;
56 fprintf(stderr, "\nStart simplification of : ");
57 printSignal(sig, stderr);
58 fprintf(stderr, "\n");
61 Tree r
= simplification(sig
);
64 cerr
<< --TABBER
<< "Simplification of : " << ppsig(sig
) << " Returns : " << ppsig(r
) << endl
;
66 fprintf(stderr, "Simplification of : ");
67 printSignal(sig, stderr);
68 fprintf(stderr, " -> ");
69 printSignal(r, stderr);
70 fprintf(stderr, "\n");
76 Tree
simplify (Tree sig
)
78 return sigMap(SIMPLIFIED
, traced_simplification
, sig
);
84 static Tree
simplification (Tree sig
)
90 xtended
* xt
= (xtended
*) getUserData(sig
);
96 for (int i
=0; i
<sig
->arity(); i
++) { args
.push_back( sig
->branch(i
) ); }
98 // to avoid negative power to further normalization
100 return xt
->computeSigOutput(args
);
102 return normalizeAddTerm(xt
->computeSigOutput(args
));
105 } else if (isSigBinOp(sig
, &opnum
, t1
, t2
)) {
107 BinOp
* op
= gBinOpTable
[opnum
];
109 Node n1
= t1
->node();
110 Node n2
= t2
->node();
112 if (isNum(n1
) && isNum(n2
)) return tree(op
->compute(n1
,n2
));
114 else if (op
->isLeftNeutral(n1
)) return t2
;
116 else if (op
->isRightNeutral(n2
)) return t1
;
118 else return normalizeAddTerm(sig
);
120 } else if (isSigDelay1(sig
, t1
)) {
122 return normalizeDelay1Term (t1
);
124 } else if (isSigFixDelay(sig
, t1
, t2
)) {
126 return normalizeFixedDelayTerm (t1
, t2
);
128 } else if (isSigIntCast(sig
, t1
)) {
133 Node n1
= t1
->node();
135 if (isInt(n1
, &i
)) return t1
;
136 if (isDouble(n1
, &x
)) return tree(int(x
));
137 if (isSigIntCast(t1
, tx
)) return t1
;
141 } else if (isSigFloatCast(sig
, t1
)) {
146 Node n1
= t1
->node();
148 if (isInt(n1
, &i
)) return tree(double(i
));
149 if (isDouble(n1
, &x
)) return t1
;
150 if (isSigFloatCast(t1
, tx
)) return t1
;
154 } else if (isSigSelect2(sig
, t1
, t2
, t3
)){
156 Node n1
= t1
->node();
158 if (isZero(n1
)) return t2
;
159 if (isNum(n1
)) return t3
;
161 if (t2
==t3
) return t2
;
165 } else if (isSigSelect3(sig
, t1
, t2
, t3
, t4
)){
167 Node n1
= t1
->node();
169 if (isZero(n1
)) return t2
;
170 if (isOne(n1
)) return t3
;
171 if (isNum(n1
)) return t4
;
173 if (t3
==t4
) return simplification(sigSelect2(t1
,t2
,t3
));
184 * Recursively transform a graph by applying a function f.
185 * map(f, foo[t1..tn]) = f(foo[map(f,t1)..map(f,tn)])
187 static Tree
sigMap (Tree key
, tfun f
, Tree t
)
189 //printf("start sigMap\n");
192 if (getProperty(t
, key
, p
)) {
194 return (isNil(p
)) ? t
: p
; // truc pour eviter les boucles
196 } else if (isRec(t
, id
, body
)) {
198 setProperty(t
, key
, nil
); // avoid infinite loop
199 return rec(id
, sigMap(key
, f
, body
));
204 switch (t
->arity()) {
210 r1
= tree(t
->node(), sigMap(key
,f
,t
->branch(0)));
213 r1
= tree(t
->node(), sigMap(key
,f
,t
->branch(0)), sigMap(key
,f
,t
->branch(1)));
216 r1
= tree(t
->node(), sigMap(key
,f
,t
->branch(0)), sigMap(key
,f
,t
->branch(1)),
217 sigMap(key
,f
,t
->branch(2)));
220 r1
= tree(t
->node(), sigMap(key
,f
,t
->branch(0)), sigMap(key
,f
,t
->branch(1)),
221 sigMap(key
,f
,t
->branch(2)), sigMap(key
,f
,t
->branch(3)));
226 setProperty(t
, key
, nil
);
228 setProperty(t
, key
, r2
);
239 * Like SigMap, recursively transform a graph by applying a
240 * function f. But here recursive trees are also renamed.
241 * map(f, foo[t1..tn]) = f(foo[map(f,t1)..map(f,tn)])
243 static Tree
sigMapRename (Tree key
, Tree env
, tfun f
, Tree t
)
245 //printf("start sigMap\n");
248 if (getProperty(t
, key
, p
)) {
250 return (isNil(p
)) ? t
: p
; // truc pour eviter les boucles
252 } else if (isRec(t
, id
, body
)) {
254 assert(isRef(t
,id
)); // controle temporaire
257 if (searchEnv(id
, id2
, env
)) {
258 // déjà en cours de visite de cette recursion
261 // premiere visite de cette recursion
262 id2
= tree(Node(unique("renamed")));
263 Tree body2
= sigMapRename(key
, pushEnv(id
, id2
, env
), f
, body
);
264 return rec(id2
,body2
);
270 switch (t
->arity()) {
276 r1
= tree(t
->node(), sigMapRename(key
,env
,f
,t
->branch(0)));
279 r1
= tree(t
->node(), sigMapRename(key
,env
,f
,t
->branch(0)),
280 sigMapRename(key
,env
,f
,t
->branch(1)));
283 r1
= tree(t
->node(), sigMapRename(key
,env
,f
,t
->branch(0)),
284 sigMapRename(key
,env
,f
,t
->branch(1)),
285 sigMapRename(key
,env
,f
,t
->branch(2)));
288 r1
= tree(t
->node(), sigMapRename(key
,env
,f
,t
->branch(0)),
289 sigMapRename(key
,env
,f
,t
->branch(1)),
290 sigMapRename(key
,env
,f
,t
->branch(2)),
291 sigMapRename(key
,env
,f
,t
->branch(3)));
296 setProperty(t
, key
, nil
);
298 setProperty(t
, key
, r2
);
305 static void eraseProperties (Tree key
, Tree t
)
307 //printf("start sigMap\n");
310 if (getProperty(t
, key
, p
)) {
311 // already erased, nothing to do
313 } else if (isRec(t
, id
, body
)) {
314 t
->clearProperties();
315 Tree r
=rec(id
, body
);
317 setProperty(t
, key
, nil
); // avoid infinite loop
318 eraseProperties(key
, body
);
322 for (int i
=0; i
<t
->arity(); i
++) {
323 eraseProperties(key
,t
->branch(i
));
328 void eraseAllProperties(Tree t
)
330 cerr
<< "begin eraseAllProperties" << endl
;
331 eraseProperties(tree(Node(unique("erase_"))), t
);
332 cerr
<< "end eraseAllProperties" << endl
;
337 * Converts regular tables into doc tables in order to
338 * facilitate the mathematical documentation generation
341 Tree DOCTABLES
= tree(symbol("DocTablesProp"));
343 static Tree
docTableConverter (Tree sig
);
345 static Tree NULLENV
= tree(symbol("NullRenameEnv"));
347 Tree
docTableConvertion (Tree sig
)
349 Tree r
= sigMapRename(DOCTABLES
, NULLENV
, docTableConverter
, sig
);
356 static Tree
docTableConverter (Tree sig
)
358 Tree tbl
, tbl2
, id
, id2
, size
, igen
, isig
, ridx
, widx
, wsig
;
360 if (isSigRDTbl(sig
, tbl
, ridx
)) {
361 // we are in a table to convert
362 if (isSigTable(tbl
, id
, size
, igen
)) {
363 // it's a read only table
364 assert(isSigGen(igen
, isig
));
365 return sigDocAccessTbl(sigDocConstantTbl(size
,isig
),ridx
);
367 // it's a read write table
368 assert(isSigWRTbl(tbl
,id
,tbl2
,widx
,wsig
));
369 assert(isSigTable(tbl2
, id2
, size
, igen
));
370 assert(isSigGen(igen
, isig
));
372 return sigDocAccessTbl(sigDocWriteTbl(size
,isig
,widx
,wsig
),ridx
);
376 // nothing to convert