X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpreter/preprocessor/faust-0.9.47mr3/compiler/normalize/simplify.cpp diff --git a/interpreter/preprocessor/faust-0.9.47mr3/compiler/normalize/simplify.cpp b/interpreter/preprocessor/faust-0.9.47mr3/compiler/normalize/simplify.cpp new file mode 100644 index 0000000..0b47d35 --- /dev/null +++ b/interpreter/preprocessor/faust-0.9.47mr3/compiler/normalize/simplify.cpp @@ -0,0 +1,379 @@ +/************************************************************************ + ************************************************************************ + FAUST compiler + Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale + --------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************ + ************************************************************************/ + + + +#include +#include +#include "list.hh" +#include "signals.hh" +#include "sigtype.hh" +#include "recursivness.hh" +#include "sigtyperules.hh" +#include "sigorderrules.hh" +#include "sigprint.hh" +#include "ppsig.hh" +#include "simplify.hh" +#include "num.hh" +#include "xtended.hh" +#include +#include "compatibility.hh" + +#include "normalize.hh" + +#undef TRACE + +// declarations +Tree SIMPLIFIED = tree(symbol("sigSimplifiedProp")); +//static Tree binequiv (Tree sig, int opnum, Tree a, Tree b); +static Tree simplification (Tree sig); +static Tree sigMap (Tree key, tfun f, Tree t); + +static Tree traced_simplification(Tree sig) +{ + assert(sig); +#ifdef TRACE + cerr << ++TABBER << "Start simplification of : " << ppsig(sig) << endl; + /* + fprintf(stderr, "\nStart simplification of : "); + printSignal(sig, stderr); + fprintf(stderr, "\n"); + */ +#endif + Tree r = simplification(sig); + assert(r!=0); +#ifdef TRACE + cerr << --TABBER << "Simplification of : " << ppsig(sig) << " Returns : " << ppsig(r) << endl; + /* + fprintf(stderr, "Simplification of : "); + printSignal(sig, stderr); + fprintf(stderr, " -> "); + printSignal(r, stderr); + fprintf(stderr, "\n"); + */ +#endif + return r; +} + +Tree simplify (Tree sig) +{ + return sigMap(SIMPLIFIED, traced_simplification, sig); +} + + +// Implementation + +static Tree simplification (Tree sig) +{ + assert(sig); + int opnum; + Tree t1, t2, t3, t4; + + xtended* xt = (xtended*) getUserData(sig); + // primitive elements + if (xt) + { + //return 3; + vector args; + for (int i=0; iarity(); i++) { args.push_back( sig->branch(i) ); } + + // to avoid negative power to further normalization + if (xt != gPowPrim) { + return xt->computeSigOutput(args); + } else { + return normalizeAddTerm(xt->computeSigOutput(args)); + } + + } else if (isSigBinOp(sig, &opnum, t1, t2)) { + + BinOp* op = gBinOpTable[opnum]; + + Node n1 = t1->node(); + Node n2 = t2->node(); + + if (isNum(n1) && isNum(n2)) return tree(op->compute(n1,n2)); + + else if (op->isLeftNeutral(n1)) return t2; + + else if (op->isRightNeutral(n2)) return t1; + + else return normalizeAddTerm(sig); + + } else if (isSigDelay1(sig, t1)) { + + return normalizeDelay1Term (t1); + + } else if (isSigFixDelay(sig, t1, t2)) { + + return normalizeFixedDelayTerm (t1, t2); + + } else if (isSigIntCast(sig, t1)) { + + Tree tx; + int i; + double x; + Node n1 = t1->node(); + + if (isInt(n1, &i)) return t1; + if (isDouble(n1, &x)) return tree(int(x)); + if (isSigIntCast(t1, tx)) return t1; + + return sig; + + } else if (isSigFloatCast(sig, t1)) { + + Tree tx; + int i; + double x; + Node n1 = t1->node(); + + if (isInt(n1, &i)) return tree(double(i)); + if (isDouble(n1, &x)) return t1; + if (isSigFloatCast(t1, tx)) return t1; + + return sig; + + } else if (isSigSelect2(sig, t1, t2, t3)){ + + Node n1 = t1->node(); + + if (isZero(n1)) return t2; + if (isNum(n1)) return t3; + + if (t2==t3) return t2; + + return sig; + + } else if (isSigSelect3(sig, t1, t2, t3, t4)){ + + Node n1 = t1->node(); + + if (isZero(n1)) return t2; + if (isOne(n1)) return t3; + if (isNum(n1)) return t4; + + if (t3==t4) return simplification(sigSelect2(t1,t2,t3)); + + return sig; + + } else { + + return sig; + } +} + +/** + * Recursively transform a graph by applying a function f. + * map(f, foo[t1..tn]) = f(foo[map(f,t1)..map(f,tn)]) + */ +static Tree sigMap (Tree key, tfun f, Tree t) +{ + //printf("start sigMap\n"); + Tree p,id,body; + + if (getProperty(t, key, p)) { + + return (isNil(p)) ? t : p; // truc pour eviter les boucles + + } else if (isRec(t, id, body)) { + + setProperty(t, key, nil); // avoid infinite loop + return rec(id, sigMap(key, f, body)); + + } else { + + Tree r1=nil; + switch (t->arity()) { + + case 0 : + r1 = t; + break; + case 1 : + r1 = tree(t->node(), sigMap(key,f,t->branch(0))); + break; + case 2 : + r1 = tree(t->node(), sigMap(key,f,t->branch(0)), sigMap(key,f,t->branch(1))); + break; + case 3 : + r1 = tree(t->node(), sigMap(key,f,t->branch(0)), sigMap(key,f,t->branch(1)), + sigMap(key,f,t->branch(2))); + break; + case 4 : + r1 = tree(t->node(), sigMap(key,f,t->branch(0)), sigMap(key,f,t->branch(1)), + sigMap(key,f,t->branch(2)), sigMap(key,f,t->branch(3))); + break; + } + Tree r2 = f(r1); + if (r2 == t) { + setProperty(t, key, nil); + } else { + setProperty(t, key, r2); + } + return r2; + } +} + + + + + +/** + * Like SigMap, recursively transform a graph by applying a + * function f. But here recursive trees are also renamed. + * map(f, foo[t1..tn]) = f(foo[map(f,t1)..map(f,tn)]) + */ +static Tree sigMapRename (Tree key, Tree env, tfun f, Tree t) +{ + //printf("start sigMap\n"); + Tree p,id,body; + + if (getProperty(t, key, p)) { + + return (isNil(p)) ? t : p; // truc pour eviter les boucles + + } else if (isRec(t, id, body)) { + + assert(isRef(t,id)); // controle temporaire + + Tree id2; + if (searchEnv(id, id2, env)) { + // déjà en cours de visite de cette recursion + return ref(id2); + } else { + // premiere visite de cette recursion + id2 = tree(Node(unique("renamed"))); + Tree body2 = sigMapRename(key, pushEnv(id, id2, env), f, body); + return rec(id2,body2); + } + + } else { + + Tree r1=nil; + switch (t->arity()) { + + case 0 : + r1 = t; + break; + case 1 : + r1 = tree(t->node(), sigMapRename(key,env,f,t->branch(0))); + break; + case 2 : + r1 = tree(t->node(), sigMapRename(key,env,f,t->branch(0)), + sigMapRename(key,env,f,t->branch(1))); + break; + case 3 : + r1 = tree(t->node(), sigMapRename(key,env,f,t->branch(0)), + sigMapRename(key,env,f,t->branch(1)), + sigMapRename(key,env,f,t->branch(2))); + break; + case 4 : + r1 = tree(t->node(), sigMapRename(key,env,f,t->branch(0)), + sigMapRename(key,env,f,t->branch(1)), + sigMapRename(key,env,f,t->branch(2)), + sigMapRename(key,env,f,t->branch(3))); + break; + } + Tree r2 = f(r1); + if (r2 == t) { + setProperty(t, key, nil); + } else { + setProperty(t, key, r2); + } + return r2; + } +} + +#if 0 +static void eraseProperties (Tree key, Tree t) +{ + //printf("start sigMap\n"); + Tree p,id,body; + + if (getProperty(t, key, p)) { + // already erased, nothing to do + + } else if (isRec(t, id, body)) { + t->clearProperties(); + Tree r=rec(id, body); + assert(r==t); + setProperty(t, key, nil); // avoid infinite loop + eraseProperties(key, body); + + } else { + + for (int i=0; iarity(); i++) { + eraseProperties(key,t->branch(i)); + } + } +} + +void eraseAllProperties(Tree t) +{ + cerr << "begin eraseAllProperties" << endl; + eraseProperties(tree(Node(unique("erase_"))), t); + cerr << "end eraseAllProperties" << endl; +} +#endif + +/** + * Converts regular tables into doc tables in order to + * facilitate the mathematical documentation generation + */ + +Tree DOCTABLES = tree(symbol("DocTablesProp")); + +static Tree docTableConverter (Tree sig); + +static Tree NULLENV = tree(symbol("NullRenameEnv")); + +Tree docTableConvertion (Tree sig) +{ + Tree r = sigMapRename(DOCTABLES, NULLENV, docTableConverter, sig); + return r; +} + + +// Implementation + +static Tree docTableConverter (Tree sig) +{ + Tree tbl, tbl2, id, id2, size, igen, isig, ridx, widx, wsig; + + if (isSigRDTbl(sig, tbl, ridx)) { + // we are in a table to convert + if (isSigTable(tbl, id, size, igen)) { + // it's a read only table + assert(isSigGen(igen, isig)); + return sigDocAccessTbl(sigDocConstantTbl(size,isig),ridx); + } else { + // it's a read write table + assert(isSigWRTbl(tbl,id,tbl2,widx,wsig)); + assert(isSigTable(tbl2, id2, size, igen)); + assert(isSigGen(igen, isig)); + + return sigDocAccessTbl(sigDocWriteTbl(size,isig,widx,wsig),ridx); + } + + } else { + // nothing to convert + return sig; + } +}