1 /************************************************************************
2  ************************************************************************
3     FAUST compiler
4     Copyright (C) 2003-2018 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.
10 
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.
15 
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  ************************************************************************/
21 
22 #include <math.h>
23 
24 #include "Text.hh"
25 #include "floats.hh"
26 #include "xtended.hh"
27 
28 class SqrtPrim : public xtended {
29    public:
SqrtPrim()30     SqrtPrim() : xtended("sqrt") {}
31 
arity()32     virtual unsigned int arity() { return 1; }
33 
needCache()34     virtual bool needCache() { return true; }
35 
infereSigType(const vector<::Type> & args)36     virtual ::Type infereSigType(const vector<::Type>& args)
37     {
38         faustassert(args.size() == 1);
39         Type     t = args[0];
40         interval i = t->getInterval();
41         if (i.valid) {
42             if (i.lo >= 0) {
43                 return castInterval(floatCast(t), interval(sqrt(i.lo), sqrt(i.hi)));
44             } else if (gGlobal->gMathExceptions) {
45                 cerr << "WARNING : potential out of domain in sqrt(" << i << ")" << endl;
46             }
47         }
48         return castInterval(floatCast(t), interval());
49     }
50 
infereSigOrder(const vector<int> & args)51     virtual int infereSigOrder(const vector<int>& args) { return args[0]; }
52 
computeSigOutput(const vector<Tree> & args)53     virtual Tree computeSigOutput(const vector<Tree>& args)
54     {
55         // check simplifications
56         num n;
57         if (isNum(args[0], n)) {
58             if (double(n) < 0) {
59                 stringstream error;
60                 error << "ERROR : out of domain sqrt(" << ppsig(args[0]) << ")" << endl;
61                 throw faustexception(error.str());
62             } else {
63                 return tree(sqrt(double(n)));
64             }
65         } else {
66             return tree(symbol(), args[0]);
67         }
68     }
69 
generateCode(CodeContainer * container,const list<ValueInst * > & args,::Type result,vector<::Type> const & types)70     virtual ValueInst* generateCode(CodeContainer* container, const list<ValueInst*>& args, ::Type result,
71                                     vector< ::Type> const& types)
72     {
73         faustassert(args.size() == arity());
74         faustassert(types.size() == arity());
75 
76         Typed::VarType         result_type;
77         vector<Typed::VarType> arg_types;
78         list<ValueInst*>       casted_args;
79         prepareTypeArgsResult(result, args, types, result_type, arg_types, casted_args);
80 
81         return container->pushFunction(subst("sqrt$0", isuffix()), result_type, arg_types, casted_args);
82     }
83 
old_generateCode(Klass * klass,const vector<string> & args,const vector<::Type> & types)84     virtual string old_generateCode(Klass* klass, const vector<string>& args, const vector<::Type>& types)
85     {
86         faustassert(args.size() == arity());
87         faustassert(types.size() == arity());
88 
89         return subst("sqrt$1($0)", args[0], isuffix());
90     }
91 
generateLateq(Lateq * lateq,const vector<string> & args,const vector<::Type> & types)92     virtual string generateLateq(Lateq* lateq, const vector<string>& args, const vector<::Type>& types)
93     {
94         faustassert(args.size() == arity());
95         faustassert(types.size() == arity());
96 
97         return subst("\\sqrt{$0}", args[0]);
98     }
99 };
100