Logo Search packages:      
Sourcecode: faust version File versions  Download package

simplify.cpp

/************************************************************************
 ************************************************************************
    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 <stdio.h>
#include <assert.h>
#include "list.hh"
#include "signals.hh"
#include "sigtype.hh"
#include "recursivness.hh"
#include "sigtyperules.hh"
#include "sigorderrules.hh"
#include "sigprint.hh"
#include "simplify.hh"
#include "num.hh"
#include "xtended.hh"
#include <map>
#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 : " << *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 : " << *sig << " Returns : " << *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;

      xtended* xt = (xtended*) getUserData(sig);
      // primitive elements
      if (xt)
      {
            //return 3;
            vector<Tree> args;
            for (int i=0; i<sig->arity(); i++) { args.push_back( sig->branch(i) ); }
            return 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 {

            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; i<t->arity(); 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);

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;
    }
}

Generated by  Doxygen 1.6.0   Back to index