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 CeilPrim : public xtended {
29    public:
CeilPrim()30     CeilPrim() : xtended("ceil") {}
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() == arity());
39         return floatCast(args[0]);
40     }
41 
infereSigOrder(const vector<int> & args)42     virtual int infereSigOrder(const vector<int>& args)
43     {
44         faustassert(args.size() == arity());
45         return args[0];
46     }
47 
computeSigOutput(const vector<Tree> & args)48     virtual Tree computeSigOutput(const vector<Tree>& args)
49     {
50         num n;
51         faustassert(args.size() == arity());
52         if (isNum(args[0], n)) {
53             return tree(ceil(double(n)));
54         } else {
55             if (gGlobal->gMathApprox) {
56                 // res = T(int(n)); return (r == n) ? n : (n >= 0 ? r + 1 : r);
57                 Tree r = sigFloatCast(sigIntCast(args[0]));
58                 return sigSelect2(sigBinOp(kEQ, args[0], r), sigSelect2(sigBinOp(kGE, args[0], sigInt(0)), r, sigBinOp(kAdd, r, sigInt(1))), args[0]);
59             } else {
60                 return tree(symbol(), args[0]);
61             }
62         }
63     }
64 
generateCode(CodeContainer * container,const list<ValueInst * > & args,::Type result,vector<::Type> const & types)65     virtual ValueInst* generateCode(CodeContainer* container, const list<ValueInst*>& args, ::Type result,
66                                     vector< ::Type> const& types)
67     {
68         faustassert(args.size() == arity());
69         faustassert(types.size() == arity());
70 
71         Typed::VarType         result_type;
72         vector<Typed::VarType> arg_types;
73         list<ValueInst*>       casted_args;
74         prepareTypeArgsResult(result, args, types, result_type, arg_types, casted_args);
75 
76         return container->pushFunction(subst("ceil$0", isuffix()), result_type, arg_types, casted_args);
77     }
78 
old_generateCode(Klass * klass,const vector<string> & args,const vector<::Type> & types)79     virtual string old_generateCode(Klass* klass, const vector<string>& args, const vector<::Type>& types)
80     {
81         faustassert(args.size() == arity());
82         faustassert(types.size() == arity());
83 
84         return subst("ceil$1($0)", args[0], isuffix());
85     }
86 
generateLateq(Lateq * lateq,const vector<string> & args,const vector<::Type> & types)87     virtual string generateLateq(Lateq* lateq, const vector<string>& args, const vector<::Type>& types)
88     {
89         faustassert(args.size() == arity());
90         faustassert(types.size() == arity());
91 
92         return subst("\\left\\lceil $0 \\right\\rceil", args[0]);
93     }
94 };
95