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 <stdlib.h>
23 #include <iostream>
24 #include <sstream>
25 
26 #include "floats.hh"
27 #include "global.hh"
28 
29 using namespace std;
30 
31 //-----------------------------------------------
32 // float size coding :
33 //-----------------------------------------------
34 //          0: external float (macro name)
35 //          1: single precision float
36 //          2: double precision float
37 //          3: long double precision float
38 //          4: fixed-point
39 
40 static const char* mathsuffix[5];       // suffix for math functions
41 static const char* numsuffix[5];        // suffix for numeric constants
42 static const char* floatname[5];        // float types
43 static const char* floatptrname[5];     // float ptr types
44 static const char* floatptrptrname[5];  // float ptr ptr types
45 static const char* castname[5];         // float castings
46 static double      floatmin[5];         // minimum float values before denormals
47 
initFaustFloat()48 void initFaustFloat()
49 {
50     // Using in FIR code generation to code math functions type (float/double/quad), same for Rust and C/C++ backends
51     mathsuffix[0] = "";
52     mathsuffix[1] = "f";
53     mathsuffix[2] = "";
54     mathsuffix[3] = "l";
55     mathsuffix[4] = "";
56 
57     // Specific for Rust backend
58     if (gGlobal->gOutputLang == "rust") {
59         numsuffix[0] = "";
60         numsuffix[1] = "";
61         numsuffix[2] = "";
62         numsuffix[3] = "";
63         numsuffix[4] = "";
64 
65         floatname[0] = FLOATMACRO;
66         floatname[1] = "F32";
67         floatname[2] = "F64";
68         floatname[3] = "dummy";
69         floatname[4] = "dummy";
70 
71         floatptrname[0] = FLOATMACROPTR;
72         floatptrname[1] = "F32*";
73         floatptrname[2] = "F64*";
74         floatptrname[3] = "dummy*";
75         floatptrname[4] = "dummy*";
76 
77         floatptrptrname[0] = FLOATMACROPTRPTR;
78         floatptrptrname[1] = "F32**";
79         floatptrptrname[2] = "F64**";
80         floatptrptrname[3] = "dummy**";
81         floatptrptrname[4] = "dummy**";
82 
83         castname[0] = FLOATCASTER;
84         castname[1] = "as F32";
85         castname[2] = "as F64";
86         castname[3] = "(dummy)";
87         castname[4] = "(dummy)";
88 
89         floatmin[0] = 0;
90         floatmin[1] = FLT_MIN;
91         floatmin[2] = DBL_MIN;
92         floatmin[3] = LDBL_MIN;
93         floatmin[4] = FLT_MIN;
94 
95     // Specific for Julia backend
96     } else  if (gGlobal->gOutputLang == "julia") {
97         numsuffix[0] = "";
98         numsuffix[1] = "f0";
99         numsuffix[2] = "";
100         numsuffix[3] = "";
101         numsuffix[4] = "";
102 
103         floatname[0] = FLOATMACRO;
104         floatname[1] = "Float32";
105         floatname[2] = "Float64";
106         floatname[3] = "dummy";
107         floatname[4] = "dummy";
108 
109         floatptrname[0] = FLOATMACROPTR;
110         floatptrname[1] = "Float32*";
111         floatptrname[2] = "Float64*";
112         floatptrname[3] = "dummy*";
113         floatptrname[4] = "dummy*";
114 
115         floatptrptrname[0] = FLOATMACROPTRPTR;
116         floatptrptrname[1] = "Float32**";
117         floatptrptrname[2] = "Float64**";
118         floatptrptrname[3] = "dummy**";
119         floatptrptrname[4] = "dummy**";
120 
121         castname[0] = FLOATCASTER;
122         castname[1] = "(Float32)";
123         castname[2] = "(Float64)";
124         castname[3] = "(dummy)";
125         castname[4] = "(dummy)";
126 
127         floatmin[0] = 0;
128         floatmin[1] = FLT_MIN;
129         floatmin[2] = DBL_MIN;
130         floatmin[3] = LDBL_MIN;
131         floatmin[4] = FLT_MIN;
132 
133     // Specific for D backend
134     } else if (gGlobal->gOutputLang == "dlang") {
135         numsuffix[0] = "";
136         numsuffix[1] = "";
137         numsuffix[2] = "";
138         numsuffix[3] = "";
139         numsuffix[4] = "";
140 
141         floatname[0] = FLOATMACRO;
142         floatname[1] = "float";
143         floatname[2] = "double";
144         floatname[3] = "real";
145         floatname[4] = "dummy";
146 
147         floatptrname[0] = FLOATMACROPTR;
148         floatptrname[1] = "float*";
149         floatptrname[2] = "double*";
150         floatptrname[3] = "real*";
151         floatptrname[4] = "dummy*";
152 
153         floatptrptrname[0] = FLOATMACROPTRPTR;
154         floatptrptrname[1] = "float**";
155         floatptrptrname[2] = "double**";
156         floatptrptrname[3] = "real**";
157         floatptrptrname[4] = "dummy**";
158 
159         castname[0] = FLOATCASTER;
160         castname[1] = "cast(float)";
161         castname[2] = "cast(double)";
162         castname[3] = "cast(real)";
163         castname[4] = "cast(dummy)";
164 
165         floatmin[0] = 0;
166         floatmin[1] = FLT_MIN;
167         floatmin[2] = DBL_MIN;
168         floatmin[3] = LDBL_MIN;
169         floatmin[4] = FLT_MIN;
170 
171     // Specific for C/C++ backends
172     } else {
173         numsuffix[0] = "";
174         numsuffix[1] = "f";
175         numsuffix[2] = "";
176         numsuffix[3] = "L";
177         numsuffix[4] = "";
178 
179         floatname[0] = FLOATMACRO;
180         floatname[1] = "float";
181         floatname[2] = "double";
182         floatname[3] = "quad";
183         floatname[4] = "fixpoint_t";
184 
185         floatptrname[0] = FLOATMACROPTR;
186         floatptrname[1] = "float*";
187         floatptrname[2] = "double*";
188         floatptrname[3] = "quad*";
189         floatptrname[4] = "fixpoint_t*";
190 
191         floatptrptrname[0] = FLOATMACROPTRPTR;
192         floatptrptrname[1] = "float**";
193         floatptrptrname[2] = "double**";
194         floatptrptrname[3] = "quad**";
195         floatptrptrname[4] = "fixpoint_t**";
196 
197         castname[0] = FLOATCASTER;
198         castname[1] = "(float)";
199         castname[2] = "(double)";
200         castname[3] = "(quad)";
201         castname[4] = "(fixpoint_t)";
202 
203         floatmin[0] = 0;
204         floatmin[1] = FLT_MIN;
205         floatmin[2] = DBL_MIN;
206         floatmin[3] = LDBL_MIN;
207         floatmin[4] = FLT_MIN;
208     }
209 }
210 
211 ///< suffix for math functions
isuffix()212 const char* isuffix()
213 {
214     return mathsuffix[gGlobal->gFloatSize];
215 }
216 
217 ///< suffix for numeric constants
inumix()218 const char* inumix()
219 {
220     return numsuffix[gGlobal->gFloatSize];
221 }
222 
ifloat()223 const char* ifloat()
224 {
225     return floatname[gGlobal->gFloatSize];
226 }
227 
ifloatptr()228 const char* ifloatptr()
229 {
230     return floatptrname[gGlobal->gFloatSize];
231 }
232 
ifloatptrptr()233 const char* ifloatptrptr()
234 {
235     return floatptrptrname[gGlobal->gFloatSize];
236 }
237 
icast()238 const char* icast()
239 {
240     return castname[gGlobal->gFloatSize];
241 }
242 
inummin()243 double inummin()
244 {
245     return floatmin[gGlobal->gFloatSize];
246 }
247 
xfloat()248 const char* xfloat()
249 {
250     return floatname[0];
251 }
252 
xcast()253 const char* xcast()
254 {
255     return castname[0];
256 }
257 
ifloatsize()258 int ifloatsize()
259 {
260     switch (gGlobal->gFloatSize) {
261         case 1:
262             return 4;
263         case 2:
264             return 8;
265         case 3:
266             return 16;
267         case 4:
268             return 4;
269         default:
270             faustassert(false);
271             return 0;
272     }
273 }
274 
itfloat()275 Typed::VarType itfloat()
276 {
277     switch (gGlobal->gFloatSize) {
278         case 1:
279             return Typed::kFloat;
280         case 2:
281             return Typed::kDouble;
282         case 3:
283             return Typed::kQuad;
284         case 4:
285             return Typed::kFixedPoint;
286         default:
287             faustassert(false);
288             return Typed::kNoType;
289     }
290 }
291 
itfloatptr()292 Typed::VarType itfloatptr()
293 {
294     switch (gGlobal->gFloatSize) {
295         case 1:
296             return Typed::kFloat_ptr;
297         case 2:
298             return Typed::kDouble_ptr;
299         case 3:
300             return Typed::kQuad_ptr;
301         case 4:
302             return Typed::kFixedPoint_ptr;
303         default:
304             faustassert(false);
305             return Typed::kNoType;
306     }
307 }
308 
itfloatptrptr()309 Typed::VarType itfloatptrptr()
310 {
311     switch (gGlobal->gFloatSize) {
312         case 1:
313             return Typed::kFloat_ptr_ptr;
314         case 2:
315             return Typed::kDouble_ptr_ptr;
316         case 3:
317             return Typed::kQuad_ptr_ptr;
318         case 4:
319             return Typed::kFixedPoint_ptr_ptr;
320         default:
321             faustassert(false);
322             return Typed::kNoType;
323     }
324 }
325 
printfloatdef(std::ostream & fout)326 void printfloatdef(std::ostream& fout)
327 {
328     fout << "#ifndef " << FLOATMACRO << std::endl;
329     fout << "#define " << FLOATMACRO << " float" << std::endl;
330     fout << "#endif " << std::endl;
331     fout << std::endl;
332     if (gGlobal->gFloatSize == 3) {
333         fout << "typedef long double quad;" << std::endl;
334     }
335 }
336