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 /*****************************************************************************
23     HISTORY
24     22/01/05 : added int cast in select2 and select3 selection signal
25 *****************************************************************************/
26 
27 #include <float.h>
28 #include <vector>
29 
30 #include "global.hh"
31 #include "ppsig.hh"
32 #include "signals.hh"
33 #include "xtended.hh"
34 
sigWriteReadTable(Tree n,Tree init,Tree widx,Tree wsig,Tree ridx)35 EXPORT Tree sigWriteReadTable(Tree n, Tree init, Tree widx, Tree wsig, Tree ridx)
36 {
37     return sigRDTbl(sigWRTbl(gGlobal->nil, sigTable(gGlobal->nil, n, sigGen(init)), widx, wsig), ridx);
38 }
39 
sigReadOnlyTable(Tree n,Tree init,Tree ridx)40 EXPORT Tree sigReadOnlyTable(Tree n, Tree init, Tree ridx)
41 {
42     return sigRDTbl(sigTable(gGlobal->nil, n, sigGen(init)), ridx);
43 }
44 
45 ////////////////////////////////////////////////////////////////////////
46 /**
47  * Signals
48  */
49 ///////////////////////////////////////////////////////////////////////
50 
sigRem(Tree x,Tree y)51 Tree sigRem(Tree x, Tree y)
52 {
53     if (isZero(y)) {
54         stringstream error;
55         error << "ERROR : % by 0 in " << ppsig(x) << " % " << ppsig(y) << endl;
56         throw faustexception(error.str());
57     }
58     return sigBinOp(kRem, x, y);
59 }
60 
sigInt(int i)61 EXPORT Tree sigInt(int i)
62 {
63     return tree(i);
64 }
isSigInt(Tree t,int * i)65 bool isSigInt(Tree t, int* i)
66 {
67     return isInt(t->node(), i);
68 }
69 
sigReal(double r)70 EXPORT Tree sigReal(double r)
71 {
72     return tree(r);
73 }
isSigReal(Tree t,double * r)74 bool isSigReal(Tree t, double* r)
75 {
76     return isDouble(t->node(), r);
77 }
78 
sigInput(int i)79 EXPORT Tree sigInput(int i)
80 {
81     // Keep the max input number (used with the signal API)
82     gGlobal->gMaxInputs = std::max(gGlobal->gMaxInputs, i+1);
83     return tree(gGlobal->SIGINPUT, tree(i));
84 }
isSigInput(Tree t,int * i)85 bool isSigInput(Tree t, int* i)
86 {
87     Tree x;
88     return isTree(t, gGlobal->SIGINPUT, x) && isInt(x->node(), i);
89 }
90 
sigOutput(int i,Tree t0)91 Tree sigOutput(int i, Tree t0)
92 {
93     return tree(gGlobal->SIGOUTPUT, tree(i), t0);
94 }
isSigOutput(Tree t,int * i,Tree & t0)95 bool isSigOutput(Tree t, int* i, Tree& t0)
96 {
97     Tree x;
98     return isTree(t, gGlobal->SIGOUTPUT, x, t0) && isInt(x->node(), i);
99 }
100 
sigDelay0(Tree t0)101 Tree sigDelay0(Tree t0)
102 {
103     return sigDelay(t0, sigInt(0));
104 }
105 
sigDelay1(Tree t0)106 Tree sigDelay1(Tree t0)
107 {
108     return tree(gGlobal->SIGDELAY1, t0);
109 }
isSigDelay1(Tree t,Tree & t0)110 bool isSigDelay1(Tree t, Tree& t0)
111 {
112     return isTree(t, gGlobal->SIGDELAY1, t0);
113 }
114 
sigDelay(Tree t0,Tree t1)115 EXPORT Tree sigDelay(Tree t0, Tree t1)
116 {
117     return tree(gGlobal->SIGDELAY, t0, sigIntCast(t1));
118 }
isSigDelay(Tree t,Tree & t0,Tree & t1)119 bool isSigDelay(Tree t, Tree& t0, Tree& t1)
120 {
121     return isTree(t, gGlobal->SIGDELAY, t0, t1);
122 }
123 
sigPrefix(Tree t0,Tree t1)124 Tree sigPrefix(Tree t0, Tree t1)
125 {
126     return tree(gGlobal->SIGPREFIX, t0, t1);
127 }
isSigPrefix(Tree t,Tree & t0,Tree & t1)128 bool isSigPrefix(Tree t, Tree& t0, Tree& t1)
129 {
130     return isTree(t, gGlobal->SIGPREFIX, t0, t1);
131 }
132 
sigIota(Tree t0)133 Tree sigIota(Tree t0)
134 {
135     return tree(gGlobal->SIGIOTA, t0);
136 }
isSigIota(Tree t,Tree & t0)137 bool isSigIota(Tree t, Tree& t0)
138 {
139     return isTree(t, gGlobal->SIGIOTA, t0);
140 }
141 
142 // Read only and read write tables
143 
sigRDTbl(Tree t,Tree i)144 Tree sigRDTbl(Tree t, Tree i)
145 {
146     return tree(gGlobal->SIGRDTBL, t, i);
147 }
isSigRDTbl(Tree s,Tree & t,Tree & i)148 bool isSigRDTbl(Tree s, Tree& t, Tree& i)
149 {
150     return isTree(s, gGlobal->SIGRDTBL, t, i);
151 }
152 
sigWRTbl(Tree id,Tree t,Tree i,Tree s)153 Tree sigWRTbl(Tree id, Tree t, Tree i, Tree s)
154 {
155     return tree(gGlobal->SIGWRTBL, id, t, i, s);
156 }
isSigWRTbl(Tree u,Tree & id,Tree & t,Tree & i,Tree & s)157 bool isSigWRTbl(Tree u, Tree& id, Tree& t, Tree& i, Tree& s)
158 {
159     return isTree(u, gGlobal->SIGWRTBL, id, t, i, s);
160 }
161 
sigTable(Tree id,Tree n,Tree sig)162 Tree sigTable(Tree id, Tree n, Tree sig)
163 {
164     return tree(gGlobal->SIGTABLE, id, n, sig);
165 }
isSigTable(Tree t,Tree & id,Tree & n,Tree & sig)166 bool isSigTable(Tree t, Tree& id, Tree& n, Tree& sig)
167 {
168     return isTree(t, gGlobal->SIGTABLE, id, n, sig);
169 }
170 
171 // Signal used to generate the initial content of a table
172 
sigGen(Tree s)173 Tree sigGen(Tree s)
174 {
175     return tree(gGlobal->SIGGEN, s);
176 }
isSigGen(Tree t,Tree & x)177 bool isSigGen(Tree t, Tree& x)
178 {
179     return isTree(t, gGlobal->SIGGEN, x);
180 }
isSigGen(Tree t)181 bool isSigGen(Tree t)
182 {
183     return t->node() == Node(gGlobal->SIGGEN);
184 }
185 
186 // Documentator Tables : special version of tables only for documentation purposes
187 
sigDocConstantTbl(Tree n,Tree sig)188 Tree sigDocConstantTbl(Tree n, Tree sig)
189 {
190     return tree(gGlobal->SIGDOCONSTANTTBL, n, sig);
191 }
isSigDocConstantTbl(Tree t,Tree & n,Tree & sig)192 bool isSigDocConstantTbl(Tree t, Tree& n, Tree& sig)
193 {
194     return isTree(t, gGlobal->SIGDOCONSTANTTBL, n, sig);
195 }
196 
sigDocWriteTbl(Tree n,Tree sig,Tree widx,Tree wsig)197 Tree sigDocWriteTbl(Tree n, Tree sig, Tree widx, Tree wsig)
198 {
199     return tree(gGlobal->SIGDOCWRITETBL, n, sig, widx, wsig);
200 }
isSigDocWriteTbl(Tree t,Tree & n,Tree & sig,Tree & widx,Tree & wsig)201 bool isSigDocWriteTbl(Tree t, Tree& n, Tree& sig, Tree& widx, Tree& wsig)
202 {
203     return isTree(t, gGlobal->SIGDOCWRITETBL, n, sig, widx, wsig);
204 }
205 
sigDocAccessTbl(Tree tbl,Tree ridx)206 Tree sigDocAccessTbl(Tree tbl, Tree ridx)
207 {
208     return tree(gGlobal->SIGDOCACCESSTBL, tbl, ridx);
209 }
isSigDocAccessTbl(Tree t,Tree & tbl,Tree & ridx)210 bool isSigDocAccessTbl(Tree t, Tree& tbl, Tree& ridx)
211 {
212     return isTree(t, gGlobal->SIGDOCACCESSTBL, tbl, ridx);
213 }
214 
215 // Select on signal among severals
216 
sigSelect2(Tree selector,Tree s1,Tree s2)217 EXPORT Tree sigSelect2(Tree selector, Tree s1, Tree s2)
218 {
219     return tree(gGlobal->SIGSELECT2, sigIntCast(selector), s1, s2);
220 }
isSigSelect2(Tree t,Tree & selector,Tree & s1,Tree & s2)221 bool isSigSelect2(Tree t, Tree& selector, Tree& s1, Tree& s2)
222 {
223     return isTree(t, gGlobal->SIGSELECT2, selector, s1, s2);
224 }
225 
226 //  "select3" expressed with "select2"
sigSelect3(Tree selector,Tree s1,Tree s2,Tree s3)227 EXPORT Tree sigSelect3(Tree selector, Tree s1, Tree s2, Tree s3)
228 {
229     return sigSelect2(sigBinOp(kEQ, sigIntCast(selector), sigInt(0)),
230                       sigSelect2(sigBinOp(kEQ, sigIntCast(selector), sigInt(1)), s3, s2), s1);
231 }
232 
sigAssertBounds(Tree s1,Tree s2,Tree s3)233 Tree sigAssertBounds(Tree s1, Tree s2, Tree s3)
234 {
235     return tree(gGlobal->SIGASSERTBOUNDS, s1, s2, s3);
236 }
237 
isSigAssertBounds(Tree t,Tree & s1,Tree & s2,Tree & s3)238 bool isSigAssertBounds(Tree t, Tree& s1, Tree& s2, Tree& s3)
239 {
240     return isTree(t, gGlobal->SIGASSERTBOUNDS, s1, s2, s3);
241 }
242 
sigHighest(Tree s)243 Tree sigHighest(Tree s)
244 {
245     return tree(gGlobal->SIGHIGHEST, s);
246 }
247 
isSigHighest(Tree t,Tree & s)248 bool isSigHighest(Tree t, Tree& s)
249 {
250     return isTree(t, gGlobal->SIGHIGHEST, s);
251 }
252 
sigLowest(Tree s)253 Tree sigLowest(Tree s)
254 {
255     return tree(gGlobal->SIGLOWEST, s);
256 }
257 
isSigLowest(Tree t,Tree & s)258 bool isSigLowest(Tree t, Tree& s)
259 {
260     return isTree(t, gGlobal->SIGLOWEST, s);
261 }
262 
263 // Arithmetical operations
264 
sigBinOp(int op,Tree x,Tree y)265 EXPORT Tree sigBinOp(int op, Tree x, Tree y)
266 {
267     return tree(gGlobal->SIGBINOP, tree(op), x, y);
268 }
isSigBinOp(Tree s,int * op,Tree & x,Tree & y)269 bool isSigBinOp(Tree s, int* op, Tree& x, Tree& y)
270 {
271     Tree t;
272     return isTree(s, gGlobal->SIGBINOP, t, x, y) && isInt(t->node(), op);
273 }
274 
275 // Foreign Functions
276 
sigFFun(Tree ff,Tree largs)277 Tree sigFFun(Tree ff, Tree largs)
278 {
279     return tree(gGlobal->SIGFFUN, ff, largs);
280 }
isSigFFun(Tree s,Tree & ff,Tree & largs)281 bool isSigFFun(Tree s, Tree& ff, Tree& largs)
282 {
283     return isTree(s, gGlobal->SIGFFUN, ff, largs);
284 }
285 
sigFConst(Tree type,Tree name,Tree file)286 EXPORT Tree sigFConst(Tree type, Tree name, Tree file)
287 {
288     return tree(gGlobal->SIGFCONST, type, name, file);
289 }
isSigFConst(Tree s)290 bool isSigFConst(Tree s)
291 {
292     Tree t, n, f;
293     return isTree(s, gGlobal->SIGFCONST, t, n, f);
294 }
isSigFConst(Tree s,Tree & type,Tree & name,Tree & file)295 bool isSigFConst(Tree s, Tree& type, Tree& name, Tree& file)
296 {
297     return isTree(s, gGlobal->SIGFCONST, type, name, file);
298 }
299 
sigFVar(Tree type,Tree name,Tree file)300 EXPORT Tree sigFVar(Tree type, Tree name, Tree file)
301 {
302     return tree(gGlobal->SIGFVAR, type, name, file);
303 }
isSigFVar(Tree s)304 bool isSigFVar(Tree s)
305 {
306     Tree t, n, f;
307     return isTree(s, gGlobal->SIGFVAR, t, n, f);
308 }
isSigFVar(Tree s,Tree & type,Tree & name,Tree & file)309 bool isSigFVar(Tree s, Tree& type, Tree& name, Tree& file)
310 {
311     return isTree(s, gGlobal->SIGFVAR, type, name, file);
312 }
313 
314 // New version using rec and ref
315 
sigProj(int i,Tree rgroup)316 Tree sigProj(int i, Tree rgroup)
317 {
318     return tree(gGlobal->SIGPROJ, tree(i), rgroup);
319 }
isProj(Tree t,int * i,Tree & rgroup)320 bool isProj(Tree t, int* i, Tree& rgroup)
321 {
322     Tree x;
323     return isTree(t, gGlobal->SIGPROJ, x, rgroup) && isInt(x->node(), i);
324 }
325 
326 // Int and Float casting
327 
sigIntCast(Tree t)328 EXPORT Tree sigIntCast(Tree t)
329 {
330     Node n = t->node();
331 
332     int i;
333     if (isInt(n, &i)) return t;
334     double x;
335     if (isDouble(n, &x)) return tree(int(x));
336     if (isSigIntCast(t)) return t;
337 
338     return tree(gGlobal->SIGINTCAST, t);
339 }
340 
sigFloatCast(Tree t)341 EXPORT Tree sigFloatCast(Tree t)
342 {
343     // cerr << "sigFloatCast(" << ppsig(t) << ")" << endl;
344     Node n = t->node();
345 
346     int i;
347     if (isInt(n, &i)) return tree(double(i));
348     double x;
349     if (isDouble(n, &x)) return t;
350     if (isSigFloatCast(t)) return t;
351     if (isSigInput(t, &i)) return t;
352 
353     return tree(gGlobal->SIGFLOATCAST, t);
354 }
355 
356 // Tree sigFloatCast(Tree t) { return isSigFloatCast(t)? t : tree(gGlobal->SIGFLOATCAST, t); }
357 
isSigIntCast(Tree t)358 bool isSigIntCast(Tree t)
359 {
360     Tree x;
361     return isTree(t, gGlobal->SIGINTCAST, x);
362 }
isSigIntCast(Tree t,Tree & x)363 bool isSigIntCast(Tree t, Tree& x)
364 {
365     return isTree(t, gGlobal->SIGINTCAST, x);
366 }
367 
isSigFloatCast(Tree t)368 bool isSigFloatCast(Tree t)
369 {
370     Tree x;
371     return isTree(t, gGlobal->SIGFLOATCAST, x);
372 }
isSigFloatCast(Tree t,Tree & x)373 bool isSigFloatCast(Tree t, Tree& x)
374 {
375     return isTree(t, gGlobal->SIGFLOATCAST, x);
376 }
377 
378 // Emulation of all fonctions
sigAdd(Tree x,Tree y)379 EXPORT Tree sigAdd(Tree x, Tree y)
380 {
381     return sigBinOp(kAdd, x, y);
382 }
sigSub(Tree x,Tree y)383 EXPORT Tree sigSub(Tree x, Tree y)
384 {
385     return sigBinOp(kSub, x, y);
386 }
sigMul(Tree x,Tree y)387 EXPORT Tree sigMul(Tree x, Tree y)
388 {
389     return sigBinOp(kMul, x, y);
390 }
sigDiv(Tree x,Tree y)391 EXPORT Tree sigDiv(Tree x, Tree y)
392 {
393     return sigBinOp(kDiv, x, y);
394 }
395 Tree sigRem(Tree x, Tree y);
396 
sigAND(Tree x,Tree y)397 EXPORT Tree sigAND(Tree x, Tree y)
398 {
399     return sigBinOp(kAND, x, y);
400 }
sigOR(Tree x,Tree y)401 EXPORT Tree sigOR(Tree x, Tree y)
402 {
403     return sigBinOp(kOR, x, y);
404 }
sigXOR(Tree x,Tree y)405 EXPORT Tree sigXOR(Tree x, Tree y)
406 {
407     return sigBinOp(kXOR, x, y);
408 }
409 
sigLeftShift(Tree x,Tree y)410 EXPORT Tree sigLeftShift(Tree x, Tree y)
411 {
412     return sigBinOp(kLsh, x, y);
413 }
sigARightShift(Tree x,Tree y)414 EXPORT Tree sigARightShift(Tree x, Tree y)
415 {
416     return sigBinOp(kARsh, x, y);
417 }
sigLRightShift(Tree x,Tree y)418 EXPORT Tree sigLRightShift(Tree x, Tree y)
419 {
420     return sigBinOp(kLRsh, x, y);
421 }
422 
sigGT(Tree x,Tree y)423 EXPORT Tree sigGT(Tree x, Tree y)
424 {
425     return sigBinOp(kGT, x, y);
426 }
sigLT(Tree x,Tree y)427 EXPORT Tree sigLT(Tree x, Tree y)
428 {
429     return sigBinOp(kLT, x, y);
430 }
sigGE(Tree x,Tree y)431 EXPORT Tree sigGE(Tree x, Tree y)
432 {
433     return sigBinOp(kGE, x, y);
434 }
sigLE(Tree x,Tree y)435 EXPORT Tree sigLE(Tree x, Tree y)
436 {
437     return sigBinOp(kLE, x, y);
438 }
sigEQ(Tree x,Tree y)439 EXPORT Tree sigEQ(Tree x, Tree y)
440 {
441     return sigBinOp(kEQ, x, y);
442 }
sigNE(Tree x,Tree y)443 EXPORT Tree sigNE(Tree x, Tree y)
444 {
445     return sigBinOp(kNE, x, y);
446 }
447 
448 /*****************************************************************************
449                              User Interface Elements
450 *****************************************************************************/
451 
sigButton(Tree lbl)452 EXPORT Tree sigButton(Tree lbl)
453 {
454     return tree(gGlobal->SIGBUTTON, lbl);
455 }
isSigButton(Tree s)456 bool isSigButton(Tree s)
457 {
458     Tree lbl;
459     return isTree(s, gGlobal->SIGBUTTON, lbl);
460 }
isSigButton(Tree s,Tree & lbl)461 bool isSigButton(Tree s, Tree& lbl)
462 {
463     return isTree(s, gGlobal->SIGBUTTON, lbl);
464 }
465 
sigCheckbox(Tree lbl)466 EXPORT Tree sigCheckbox(Tree lbl)
467 {
468     return tree(gGlobal->SIGCHECKBOX, lbl);
469 }
isSigCheckbox(Tree s)470 bool isSigCheckbox(Tree s)
471 {
472     Tree lbl;
473     return isTree(s, gGlobal->SIGCHECKBOX, lbl);
474 }
isSigCheckbox(Tree s,Tree & lbl)475 bool isSigCheckbox(Tree s, Tree& lbl)
476 {
477     return isTree(s, gGlobal->SIGCHECKBOX, lbl);
478 }
479 
sigWaveform(const tvec & wf)480 EXPORT Tree sigWaveform(const tvec& wf)
481 {
482     return tree(gGlobal->SIGWAVEFORM, wf);
483 }
isSigWaveform(Tree s)484 bool isSigWaveform(Tree s)
485 {
486     return isTree(s, gGlobal->SIGWAVEFORM);
487 }
488 
sigHSlider(Tree lbl,Tree init,Tree min,Tree max,Tree step)489 EXPORT Tree sigHSlider(Tree lbl, Tree init, Tree min, Tree max, Tree step)
490 {
491     return tree(gGlobal->SIGHSLIDER, lbl, list4(init, min, max, step));
492 }
isSigHSlider(Tree s)493 bool isSigHSlider(Tree s)
494 {
495     Tree lbl, params;
496     return isTree(s, gGlobal->SIGHSLIDER, lbl, params);
497 }
498 
isSigHSlider(Tree s,Tree & lbl,Tree & init,Tree & min,Tree & max,Tree & step)499 bool isSigHSlider(Tree s, Tree& lbl, Tree& init, Tree& min, Tree& max, Tree& step)
500 {
501     Tree params;
502     if (isTree(s, gGlobal->SIGHSLIDER, lbl, params)) {
503         init  = nth(params, 0);
504         min  = nth(params, 1);
505         max  = nth(params, 2);
506         step = nth(params, 3);
507         return true;
508     } else {
509         return false;
510     }
511 }
512 
sigVSlider(Tree lbl,Tree init,Tree min,Tree max,Tree step)513 EXPORT Tree sigVSlider(Tree lbl, Tree init, Tree min, Tree max, Tree step)
514 {
515     return tree(gGlobal->SIGVSLIDER, lbl, list4(init, min, max, step));
516 }
isSigVSlider(Tree s)517 bool isSigVSlider(Tree s)
518 {
519     Tree lbl, params;
520     return isTree(s, gGlobal->SIGVSLIDER, lbl, params);
521 }
522 
isSigVSlider(Tree s,Tree & lbl,Tree & init,Tree & min,Tree & max,Tree & step)523 bool isSigVSlider(Tree s, Tree& lbl, Tree& init, Tree& min, Tree& max, Tree& step)
524 {
525     Tree params;
526     if (isTree(s, gGlobal->SIGVSLIDER, lbl, params)) {
527         init  = nth(params, 0);
528         min  = nth(params, 1);
529         max  = nth(params, 2);
530         step = nth(params, 3);
531         return true;
532     } else {
533         return false;
534     }
535 }
536 
sigNumEntry(Tree lbl,Tree init,Tree min,Tree max,Tree step)537 EXPORT Tree sigNumEntry(Tree lbl, Tree init, Tree min, Tree max, Tree step)
538 {
539     return tree(gGlobal->SIGNUMENTRY, lbl, list4(init, min, max, step));
540 }
isSigNumEntry(Tree s)541 bool isSigNumEntry(Tree s)
542 {
543     Tree lbl, params;
544     return isTree(s, gGlobal->SIGNUMENTRY, lbl, params);
545 }
546 
isSigNumEntry(Tree s,Tree & lbl,Tree & init,Tree & min,Tree & max,Tree & step)547 bool isSigNumEntry(Tree s, Tree& lbl, Tree& init, Tree& min, Tree& max, Tree& step)
548 {
549     Tree params;
550     if (isTree(s, gGlobal->SIGNUMENTRY, lbl, params)) {
551         init  = nth(params, 0);
552         min  = nth(params, 1);
553         max  = nth(params, 2);
554         step = nth(params, 3);
555         return true;
556     } else {
557         return false;
558     }
559 }
560 
561 // Output elements
562 
sigHBargraph(Tree lbl,Tree min,Tree max,Tree x)563 EXPORT Tree sigHBargraph(Tree lbl, Tree min, Tree max, Tree x)
564 {
565     return tree(gGlobal->SIGHBARGRAPH, lbl, min, max, x);
566 }
isSigHBargraph(Tree s)567 bool isSigHBargraph(Tree s)
568 {
569     Tree lbl, min, max, x;
570     return isTree(s, gGlobal->SIGHBARGRAPH, lbl, min, max, x);
571 }
isSigHBargraph(Tree s,Tree & lbl,Tree & min,Tree & max,Tree & x)572 bool isSigHBargraph(Tree s, Tree& lbl, Tree& min, Tree& max, Tree& x)
573 {
574     return isTree(s, gGlobal->SIGHBARGRAPH, lbl, min, max, x);
575 }
576 
sigVBargraph(Tree lbl,Tree min,Tree max,Tree x)577 EXPORT Tree sigVBargraph(Tree lbl, Tree min, Tree max, Tree x)
578 {
579     return tree(gGlobal->SIGVBARGRAPH, lbl, min, max, x);
580 }
isSigVBargraph(Tree s)581 bool isSigVBargraph(Tree s)
582 {
583     Tree lbl, min, max, x;
584     return isTree(s, gGlobal->SIGVBARGRAPH, lbl, min, max, x);
585 }
isSigVBargraph(Tree s,Tree & lbl,Tree & min,Tree & max,Tree & x)586 bool isSigVBargraph(Tree s, Tree& lbl, Tree& min, Tree& max, Tree& x)
587 {
588     return isTree(s, gGlobal->SIGVBARGRAPH, lbl, min, max, x);
589 }
590 
sigAttach(Tree t0,Tree t1)591 Tree sigAttach(Tree t0, Tree t1)
592 {
593     return tree(gGlobal->SIGATTACH, t0, t1);
594 }
isSigAttach(Tree t,Tree & t0,Tree & t1)595 bool isSigAttach(Tree t, Tree& t0, Tree& t1)
596 {
597     return isTree(t, gGlobal->SIGATTACH, t0, t1);
598 }
599 
sigEnable(Tree t0,Tree t1)600 Tree sigEnable(Tree t0, Tree t1)
601 {
602     return tree(gGlobal->SIGENABLE, t0, t1);
603 }
isSigEnable(Tree t,Tree & t0,Tree & t1)604 bool isSigEnable(Tree t, Tree& t0, Tree& t1)
605 {
606     return isTree(t, gGlobal->SIGENABLE, t0, t1);
607 }
608 
sigControl(Tree t0,Tree t1)609 Tree sigControl(Tree t0, Tree t1)
610 {
611     return tree(gGlobal->SIGCONTROL, t0, t1);
612 }
isSigControl(Tree t,Tree & t0,Tree & t1)613 bool isSigControl(Tree t, Tree& t0, Tree& t1)
614 {
615     return isTree(t, gGlobal->SIGCONTROL, t0, t1);
616 }
617 
618 // Extended math functions
sigExtended1(Tree sig,Tree x)619 static Tree sigExtended1(Tree sig, Tree x)
620 {
621     tvec args;
622     args.push_back(x);
623     return ((xtended*)getUserData(sig))->computeSigOutput(args);
624 }
625 
sigExtended2(Tree sig,Tree x,Tree y)626 static Tree sigExtended2(Tree sig, Tree x, Tree y)
627 {
628     tvec args;
629     args.push_back(x);
630     args.push_back(y);
631     return ((xtended*)getUserData(sig))->computeSigOutput(args);
632 }
633 
sigAbs(Tree x)634 EXPORT Tree sigAbs(Tree x)
635 {
636     return sigExtended1(gGlobal->gAbsPrim->box(), x);
637 }
638 
sigAcos(Tree x)639 EXPORT Tree sigAcos(Tree x)
640 {
641     return sigExtended1(gGlobal->gAcosPrim->box(), x);
642 }
643 
sigTan(Tree x)644 EXPORT Tree sigTan(Tree x)
645 {
646     return sigExtended1(gGlobal->gTanPrim->box(), x);
647 }
648 
sigSqrt(Tree x)649 EXPORT Tree sigSqrt(Tree x)
650 {
651     return sigExtended1(gGlobal->gSqrtPrim->box(), x);
652 }
653 
sigSin(Tree x)654 EXPORT Tree sigSin(Tree x)
655 {
656     return sigExtended1(gGlobal->gSinPrim->box(), x);
657 }
658 
sigRint(Tree x)659 EXPORT Tree sigRint(Tree x)
660 {
661     return sigExtended1(gGlobal->gRintPrim->box(), x);
662 }
663 
sigRemainder(Tree x,Tree y)664 EXPORT Tree sigRemainder(Tree x, Tree y)
665 {
666     return sigExtended2(gGlobal->gRemainderPrim->box(), x, y);
667 }
668 
sigPow(Tree x,Tree y)669 EXPORT Tree sigPow(Tree x, Tree y)
670 {
671     return sigExtended2(gGlobal->gPowPrim->box(), x, y);
672 }
673 
sigMin(Tree x,Tree y)674 EXPORT Tree sigMin(Tree x, Tree y)
675 {
676     return sigExtended2(gGlobal->gMinPrim->box(), x, y);
677 }
678 
sigMax(Tree x,Tree y)679 EXPORT Tree sigMax(Tree x, Tree y)
680 {
681     return sigExtended2(gGlobal->gMaxPrim->box(), x, y);
682 }
683 
sigLog(Tree x)684 EXPORT Tree sigLog(Tree x)
685 {
686     return sigExtended1(gGlobal->gLogPrim->box(), x);
687 }
688 
sigLog10(Tree x)689 EXPORT Tree sigLog10(Tree x)
690 {
691     return sigExtended1(gGlobal->gLog10Prim->box(), x);
692 }
693 
sigFmod(Tree x,Tree y)694 EXPORT Tree sigFmod(Tree x, Tree y)
695 {
696     return sigExtended2(gGlobal->gFmodPrim->box(), x, y);
697 }
698 
sigFloor(Tree x)699 EXPORT Tree sigFloor(Tree x)
700 {
701     return sigExtended1(gGlobal->gFloorPrim->box(), x);
702 }
703 
sigExp(Tree x)704 EXPORT Tree sigExp(Tree x)
705 {
706     return sigExtended1(gGlobal->gExpPrim->box(), x);
707 }
708 
sigExp10(Tree x)709 EXPORT Tree sigExp10(Tree x)
710 {
711     return sigExtended1(gGlobal->gExp10Prim->box(), x);
712 }
713 
sigCos(Tree x)714 EXPORT Tree sigCos(Tree x)
715 {
716     return sigExtended1(gGlobal->gCosPrim->box(), x);
717 }
718 
sigCeil(Tree x)719 EXPORT Tree sigCeil(Tree x)
720 {
721     return sigExtended1(gGlobal->gCeilPrim->box(), x);
722 }
723 
sigAtan(Tree x)724 EXPORT Tree sigAtan(Tree x)
725 {
726     return sigExtended1(gGlobal->gAtanPrim->box(), x);
727 }
728 
sigAtan2(Tree x,Tree y)729 EXPORT Tree sigAtan2(Tree x, Tree y)
730 {
731     return sigExtended2(gGlobal->gAtan2Prim->box(), x, y);
732 }
733 
sigAsin(Tree x)734 EXPORT Tree sigAsin(Tree x)
735 {
736     return sigExtended1(gGlobal->gAsinPrim->box(), x);
737 }
738 
sameMagnitude(Tree a,Tree b)739 bool sameMagnitude(Tree a, Tree b)
740 {
741     return sameMagnitude(a->node(), b->node());
742 }
743 
addNums(Tree a,Tree b)744 Tree addNums(Tree a, Tree b)
745 {
746     Tree r = tree(addNode(a->node(), b->node()));
747     // cerr.flags(ios::showpoint); cerr << "addNums " << *a << "+" << *b << " -> " << *r << endl;
748     return r;
749 }
750 
subNums(Tree a,Tree b)751 Tree subNums(Tree a, Tree b)
752 {
753     Tree r = tree(subNode(a->node(), b->node()));
754     // cerr.flags(ios::showpoint); cerr << "subNums " << *a << "-" << *b << " -> " << *r << endl;
755     return r;
756 }
757 
mulNums(Tree a,Tree b)758 Tree mulNums(Tree a, Tree b)
759 {
760     Tree r = tree(mulNode(a->node(), b->node()));
761     // cerr.flags(ios::showpoint); cerr << "mulNums " << *a << "*" << *b << " -> " << *r << endl;
762     return r;
763 }
764 
765 // Tree divNums(Tree a, Tree b)
766 //{
767 //	Tree r = tree(divNode(a->node(),b->node()));
768 //	//cerr.flags(ios::showpoint); cerr << "divNums " << *a << "/" << *b << " -> " << *r << endl;
769 //	return r;
770 //}
771 
divExtendedNums(Tree a,Tree b)772 Tree divExtendedNums(Tree a, Tree b)
773 {
774     // cerr.flags(ios::showpoint); cerr << "divExtendeNums " << *a << "/" << *b << " -> " << endl;
775     Tree r = tree(divExtendedNode(a->node(), b->node()));
776     // cerr.flags(ios::showpoint); cerr << "divExtendeNums " << *a << "/" << *b << " -> " << *r << endl;
777     return r;
778 }
779 
minusNum(Tree a)780 Tree minusNum(Tree a)
781 {
782     Tree r = tree(minusNode(a->node()));
783     // cerr.flags(ios::showpoint); cerr << "minusNum " << *a << " -> " << *r << endl;
784     return r;
785 }
786 
inverseNum(Tree a)787 Tree inverseNum(Tree a)
788 {
789     Tree r = tree(inverseNode(a->node()));
790     // cerr.flags(ios::showpoint); cerr << "inverseNum " << *a << " -> " << *r << endl;
791     return r;
792 }
793 
isSigAdd(Tree a,Tree & x,Tree & y)794 bool isSigAdd(Tree a, Tree& x, Tree& y)
795 {
796     int op;
797     return isSigBinOp(a, &op, x, y) && (op == kAdd);
798 }
799 
isSigMul(Tree a,Tree & x,Tree & y)800 bool isSigMul(Tree a, Tree& x, Tree& y)
801 {
802     int op;
803     return isSigBinOp(a, &op, x, y) && (op == kMul);
804 }
805 
isSigSub(Tree a,Tree & x,Tree & y)806 bool isSigSub(Tree a, Tree& x, Tree& y)
807 {
808     int op;
809     return isSigBinOp(a, &op, x, y) && (op == kSub);
810 }
811 
isSigDiv(Tree a,Tree & x,Tree & y)812 bool isSigDiv(Tree a, Tree& x, Tree& y)
813 {
814     int op;
815     return isSigBinOp(a, &op, x, y) && (op == kDiv);
816 }
817 
818 /*****************************************************************************
819                              Soundfiles
820 *****************************************************************************/
821 /*
822  A boxSoundfile(label,c) has 2 inputs and c+3 outputs:
823  0   sigSoundfileLength(label, part):  the number of frames of the soundfile part (NK)
824  1   sigSoundfileRate(label, part): the sampling rate encoded in the file (NK)
825  2   sigSoundfileBuffer(label, c, part, ridx): the cth channel content (RK ou RS)
826 */
sigSoundfile(Tree label)827 EXPORT Tree sigSoundfile(Tree label)
828 {
829     return tree(gGlobal->SIGSOUNDFILE, label);
830 }
sigSoundfileLength(Tree sf,Tree part)831 EXPORT Tree sigSoundfileLength(Tree sf, Tree part)
832 {
833     return tree(gGlobal->SIGSOUNDFILELENGTH, sf, part);
834 }
sigSoundfileRate(Tree sf,Tree part)835 EXPORT Tree sigSoundfileRate(Tree sf, Tree part)
836 {
837     return tree(gGlobal->SIGSOUNDFILERATE, sf, part);
838 }
sigSoundfileBuffer(Tree sf,Tree chan,Tree part,Tree ridx)839 EXPORT Tree sigSoundfileBuffer(Tree sf, Tree chan, Tree part, Tree ridx)
840 {
841     return tree(gGlobal->SIGSOUNDFILEBUFFER, sf, chan, part, ridx);
842 }
843 
isSigSoundfile(Tree s,Tree & label)844 bool isSigSoundfile(Tree s, Tree& label)
845 {
846     return isTree(s, gGlobal->SIGSOUNDFILE, label);
847 }
isSigSoundfileLength(Tree s,Tree & sf,Tree & part)848 bool isSigSoundfileLength(Tree s, Tree& sf, Tree& part)
849 {
850     return isTree(s, gGlobal->SIGSOUNDFILELENGTH, sf, part);
851 }
isSigSoundfileRate(Tree s,Tree & sf,Tree & part)852 bool isSigSoundfileRate(Tree s, Tree& sf, Tree& part)
853 {
854     return isTree(s, gGlobal->SIGSOUNDFILERATE, sf, part);
855 }
isSigSoundfileBuffer(Tree s,Tree & sf,Tree & chan,Tree & part,Tree & ridx)856 bool isSigSoundfileBuffer(Tree s, Tree& sf, Tree& chan, Tree& part, Tree& ridx)
857 {
858     return isTree(s, gGlobal->SIGSOUNDFILEBUFFER, sf, chan, part, ridx);
859 }
860 /*****************************************************************************
861                              matrix extension
862 *****************************************************************************/
863 
864 // a tuple of signals is basically a list of signals.
865 // mode = 0 means normal, mode = 1 means blocked
sigTuple(int mode,Tree ls)866 Tree sigTuple(int mode, Tree ls)
867 {
868     return tree(gGlobal->SIGTUPLE, tree(mode), ls);
869 }
isSigTuple(Tree s,int * mode,Tree & ls)870 bool isSigTuple(Tree s, int* mode, Tree& ls)
871 {
872     Tree m;
873     return isTree(s, gGlobal->SIGTUPLE, m, ls) && isInt(m->node(), mode);
874 }
875 
876 // Access the components of a tuple.
877 // ts is tuple of signals, idx is a scalar signal between 0..n
sigTupleAccess(Tree ts,Tree idx)878 Tree sigTupleAccess(Tree ts, Tree idx)
879 {
880     return tree(gGlobal->SIGTUPLEACCESS, ts, idx);
881 }
isSigTupleAccess(Tree s,Tree & ts,Tree & idx)882 bool isSigTupleAccess(Tree s, Tree& ts, Tree& idx)
883 {
884     return isTree(s, gGlobal->SIGTUPLEACCESS, ts, idx);
885 }
886 
887 // create a tuple of signals
sigCartesianProd(Tree s1,Tree s2)888 Tree sigCartesianProd(Tree s1, Tree s2)
889 {
890     Tree l1, l2;
891     int  m1, m2;
892 
893     if (isSigTuple(s1, &m1, l1) && (m1 == 0)) {
894         // nothing to do
895     } else {
896         l1 = list1(s1);
897     }
898 
899     if (isSigTuple(s2, &m2, l2) && (m2 == 0)) {
900         // nothing to do
901     } else {
902         l2 = list1(s2);
903     }
904 
905     return sigTuple(0, concat(l1, l2));
906 }
907 
908 /**
909  * Test if exp is very simple that is it
910  * can't be considered a real component
911  * @param exp the signal we want to test
912  * @return true if it a very simple signal
913  */
verySimple(Tree exp)914 bool verySimple(Tree exp)
915 {
916     int    i;
917     double r;
918     Tree   type, name, file;
919 
920     return isSigInt(exp, &i) || isSigReal(exp, &r) || isSigInput(exp, &i) || isSigFConst(exp, type, name, file);
921 }
922 
923 /*****************************************************************************
924                              FTZ wrapping
925     Add FTZ wrapping to a signal
926 *****************************************************************************/
927 
928 // \(x).(select2(abs(x)<mmm, x, 0))
929 
sigFTZ(Tree s)930 Tree sigFTZ(Tree s)
931 {
932     return tree(gGlobal->gFtzPrim->symbol(), s);
933 }
934 
935 /*****************************************************************************
936  *                          sigList2vectInt
937  *****************************************************************************/
938 // Convert a list of signals (representing numbers) into a vector of ints
939 // the result is true if the conversion was possible
940 
sigList2vecInt(Tree ls,vector<int> & v)941 bool sigList2vecInt(Tree ls, vector<int>& v)
942 {
943     int    i;
944     double x;
945 
946     while (!isNil(ls)) {
947         Tree s = hd(ls);
948         ls     = tl(ls);
949         if (isSigInt(s, &i)) {
950             v.push_back(i);
951         } else if (isSigReal(s, &x)) {
952             v.push_back(int(x));
953         } else {
954             return false;
955         }
956     }
957     return true;
958 }
959 
960 /**
961  * Convert an stl vector of signals into a tree list of signals
962  */
listConvert(const siglist & a)963 Tree listConvert(const siglist& a)
964 {
965     int  n = (int)a.size();
966     Tree t = gGlobal->nil;
967 
968     while (n--) t = cons(a[n], t);
969     return t;
970 }
971