> note that atan2(fTemp0, fTemp0) == %pi/4

That's only true if fTemp0 is positive.
For negative fTemp0, it's 5 * %pi / 4, or - 3 * %pi / 4, depending on your
choice of domain.

On Sat, Apr 29, 2023 at 9:42 AM Oleg Nesterov <o...@redhat.com> wrote:

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


-- 
"Anything that can be automated should optionally be"
_______________________________________________
Faudiostream-devel mailing list
Faudiostream-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/faudiostream-devel

Reply via email to