This atan2 optimisation is easy, done in https://github.com/grame-cncm/faust/commit/26537a42f0fe55c7d471cdbb968755bec92c1707
Stéphane > Le 29 avr. 2023 à 18:41, Oleg Nesterov <o...@redhat.com> a écrit : > > Stephane, Yann, > > Can I suggest another feature? The patch is not for inclusion yet, > but I'd like to discuss the idea / implementation. > > It adds the new keyword `meta` which returns the environment with > 2 primitives (so far): > > 1. serial(sig) - returns sig->serial() > 2. order(sig) - getSigOrder(sig) > > Note that they compute the returned value at compile time. > > Why the environment? Because this way it is very easy to add more > primitives (e.g. typeof(sig) which returns kBool / kInt / kReal) > using a single keyword. > > Why do we want this feature? Well, I certainly do ;) but I do not > have a simple and convincing example. > > ------------------------------------------------------------------------------- > But let me provide a basic example even if it is not convincing. > Consider: > > process(x,y) = atan2(x,x), atan2(x,y); > > it compiles to > > float fTemp0 = float(input0[i0]); > output0[i0] = FAUSTFLOAT(std::atan2(fTemp0, fTemp0)); > output1[i0] = FAUSTFLOAT(std::atan2(fTemp0, float(input1[i0]))); > > note that atan2(fTemp0, fTemp0) == %pi/4 (lets ignore the fTemp0 == 0 > case for the sake of simplicity), so this code is suboptimal. > > Let's try to improve this code: > > my_atan2(a,b) = select2(a == b, atan2(a,b), ma.PI/4); > process(x,y) = my_atan2(x,x), my_atan2(x,y); > > result: > > float fTemp0 = float(input0[i0]); > output0[i0] = FAUSTFLOAT(((fTemp0 == fTemp0) ? 0.7853982f : > std::atan2(fTemp0, fTemp0))); > float fTemp1 = float(input1[i0]); > output1[i0] = FAUSTFLOAT(((fTemp0 == fTemp1) ? 0.7853982f : > std::atan2(fTemp0, fTemp1))); > > doesn't look very good although the compiler will optimize out the 1st > `fTemp0 == fTemp0` check. > > Now let's use meta.serial: > > same_signal(a,b) = meta.serial(a) == meta.serial(b); > > my_atan2(a,b) = select2(same_signal(a,b), atan2(a,b), ma.PI/4); > process(x,y) = my_atan2(x,x), my_atan2(x,y); > > result: > > output0[i0] = FAUSTFLOAT(0.7853982f); > output1[i0] = FAUSTFLOAT(std::atan2(float(input0[i0]), > float(input1[i0]))); > > Oleg. > --- > compiler/extended/metaprim.hh | 94 +++++++++++++++++++++++++++++++++++ > compiler/global.cpp | 3 ++ > compiler/global.hh | 2 + > compiler/parser/faustlexer.l | 2 + > compiler/parser/faustparser.y | 3 ++ > 5 files changed, 104 insertions(+) > create mode 100644 compiler/extended/metaprim.hh > > diff --git a/compiler/extended/metaprim.hh b/compiler/extended/metaprim.hh > new file mode 100644 > index 000000000..20cc5982e > --- /dev/null > +++ b/compiler/extended/metaprim.hh > @@ -0,0 +1,94 @@ > +/************************************************************************ > + ************************************************************************ > + FAUST compiler > + Copyright (C) 2003-2018 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 Lesser General Public License as published > by > + the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + ************************************************************************ > + ************************************************************************/ > + > +#include "xtended.hh" > +#include "simplify.hh" > +#include "sigorderrules.hh" > + > +class MetaPrim : public xtended { > + private: > + int fOp; > + public: > + MetaPrim(int op, const char *name) : xtended(name), fOp(op) {} > + > + virtual unsigned int arity() { return 1; } > + > + virtual bool needCache() { return true; } > + > + virtual int infereSigOrder(const std::vector<int>& args) { return 0; } > + > + virtual Tree computeSigOutput(const std::vector<Tree>& args) > + { > + Tree sig = simplify(args[0]); > + int ret = -1; > + > + switch (fOp) { > + case 0: > + ret = sig->serial(); > + break; > + case 1: > + ret = getSigOrder(sig); > + break; > + default: > + faustassert(false); > + } > + > + return tree(ret); > + } > + > + virtual ::Type infereSigType(ConstTypes args) > + { > + faustassert(false); return 0; > + } > + > + virtual ValueInst* generateCode(CodeContainer* container, Values& args, > ::Type result, ConstTypes types) > + { > + faustassert(false); return 0; > + } > + > + virtual std::string generateCode(Klass* klass, const > std::vector<std::string>& args, ConstTypes types) > + { > + faustassert(false); return 0; > + } > + > + virtual std::string generateLateq(Lateq* lateq, const > std::vector<std::string>& args, ConstTypes types) > + { > + return "TODO"; > + } > +}; > + > +static Tree add_meta_def(Tree defs, int op, const char *d_n) > +{ > + Tree id = boxIdent(d_n); > + std::string x_n = std::string("meta_") + d_n; > + MetaPrim *meta = new MetaPrim(op, x_n.c_str()); > + return cons(cons(id, meta->box()), defs); > +} > + > +static Tree mkMetaEnv() > +{ > + Tree defs = gGlobal->nil; > + > + defs = add_meta_def(defs, 0, "serial"); > + defs = add_meta_def(defs, 1, "order"); > + > + return boxWithLocalDef(boxEnvironment(), defs); > +} > diff --git a/compiler/global.cpp b/compiler/global.cpp > index 29af5eb9d..6636eac92 100644 > --- a/compiler/global.cpp > +++ b/compiler/global.cpp > @@ -48,6 +48,7 @@ > #include "sourcereader.hh" > #include "sqrtprim.hh" > #include "tanprim.hh" > +#include "metaprim.hh" > #include "tree.hh" > #include "occur.hh" > #include "enrobage.hh" > @@ -592,6 +593,8 @@ void global::init() > // Predefined nil tree > nil = tree(NIL); > > + gMetaEnv = mkMetaEnv(); > + > PROCESS = symbol("process"); > > BOXTYPEPROP = tree(symbol("boxTypeProp")); > diff --git a/compiler/global.hh b/compiler/global.hh > index e8ced28c8..dbb001e7c 100644 > --- a/compiler/global.hh > +++ b/compiler/global.hh > @@ -322,6 +322,8 @@ struct global { > xtended* gAtan2Prim; > xtended* gAsinPrim; > > + Tree gMetaEnv; > + > // Signals > Sym BOXIDENT; > Sym BOXCUT; > diff --git a/compiler/parser/faustlexer.l b/compiler/parser/faustlexer.l > index c92210cb5..c9342848f 100644 > --- a/compiler/parser/faustlexer.l > +++ b/compiler/parser/faustlexer.l > @@ -198,6 +198,8 @@ NSID {ID}("::"{ID})* > "sum" return ISUM; > "prod" return IPROD; > > +"meta" return META; > + > "inputs" return INPUTS; > "outputs" return OUTPUTS; > > diff --git a/compiler/parser/faustparser.y b/compiler/parser/faustparser.y > index 0f29d3403..5c9d49379 100644 > --- a/compiler/parser/faustparser.y > +++ b/compiler/parser/faustparser.y > @@ -217,6 +217,8 @@ inline Tree unquote(char* str) > %token ISUM > %token IPROD > > +%token META > + > %token INPUTS > %token OUTPUTS > > @@ -587,6 +589,7 @@ primitive : INT { $$ = > boxInt(str2int(FAUSTtext) > | ffunction { $$ = boxFFun($1); } > | fconst { $$ = $1; } > | fvariable { $$ = $1; } > + | META { $$ = gGlobal->gMetaEnv; } > | COMPONENT LPAR uqstring RPAR { $$ = boxComponent($3); } > | LIBRARY LPAR uqstring RPAR { $$ = boxLibrary($3); } > | ENVIRONMENT LBRAQ stmtlist RBRAQ { $$ = > boxWithLocalDef(boxEnvironment(),formatDefinitions($3)); } > -- > 2.39.2 > > _______________________________________________ Faudiostream-devel mailing list Faudiostream-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/faudiostream-devel