/[svn]/linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/scriptvm/CoreVMFunctions.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3747 - (hide annotations) (download)
Sun Feb 16 11:31:46 2020 UTC (3 months, 1 week ago) by schoenebeck
File size: 61950 byte(s)
* NKSP: Fixed re-entrant issue with function calls which caused wrong
  result values if the same function was called multiple times in a term
  (specifically if metric prefixes were used).

* Tests: Added NKSP core language test cases to guard this fixed issue.

* Bumped version (2.1.1.svn50).

1 schoenebeck 2581 /*
2 schoenebeck 3707 * Copyright (c) 2014-2020 Christian Schoenebeck
3 schoenebeck 2581 *
4     * http://www.linuxsampler.org
5     *
6     * This file is part of LinuxSampler and released under the same terms.
7     * See README file for details.
8     */
9    
10     #include "CoreVMFunctions.h"
11    
12     #include <iostream>
13 schoenebeck 3221 #include <algorithm> // for std::sort()
14 schoenebeck 2619 #include <math.h>
15     #include <stdlib.h>
16 schoenebeck 2581 #include "tree.h"
17     #include "ScriptVM.h"
18 schoenebeck 3285 #include "../common/RTMath.h"
19 schoenebeck 2581
20     namespace LinuxSampler {
21    
22 schoenebeck 3581 inline bool _fEqualX(vmfloat a, vmfloat b) {
23     if (sizeof(vmfloat) == sizeof(float))
24     return RTMath::fEqual32(a, b);
25     else
26     return RTMath::fEqual64(a, b);
27     }
28    
29 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
30 schoenebeck 3744 // class VMIntResult
31    
32     VMIntResult::VMIntResult() :
33     flags(STMT_SUCCESS), value(0), unitPrefixFactor(VM_NO_FACTOR),
34     unitBaseType(VM_NO_UNIT)
35     {
36     }
37    
38     ///////////////////////////////////////////////////////////////////////////
39     // class VMRealResult
40    
41     VMRealResult::VMRealResult() :
42     flags(STMT_SUCCESS), value(0), unitPrefixFactor(VM_NO_FACTOR),
43     unitBaseType(VM_NO_UNIT)
44     {
45    
46     }
47    
48     ///////////////////////////////////////////////////////////////////////////
49 schoenebeck 2727 // class VMEmptyResultFunction
50    
51 schoenebeck 3747 void VMEmptyResultFunction::bindResult(VMFnResult* res) {
52     result = dynamic_cast<VMEmptyResult*>(res);
53     }
54    
55     VMFnResult* VMEmptyResultFunction::boundResult() const {
56     return result;
57     }
58    
59 schoenebeck 2581 VMFnResult* VMEmptyResultFunction::errorResult() {
60 schoenebeck 3747 result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
61     return result;
62 schoenebeck 2581 }
63    
64 schoenebeck 2598 VMFnResult* VMEmptyResultFunction::successResult() {
65 schoenebeck 3747 result->flags = STMT_SUCCESS;
66     return result;
67 schoenebeck 2596 }
68    
69 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
70     // class VMIntResultFunction
71    
72 schoenebeck 3747 void VMIntResultFunction::bindResult(VMFnResult* res) {
73     result = dynamic_cast<VMIntResult*>(res);
74     }
75    
76     VMFnResult* VMIntResultFunction::boundResult() const {
77     return result;
78     }
79    
80 schoenebeck 3557 VMFnResult* VMIntResultFunction::errorResult(vmint i) {
81 schoenebeck 3747 result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
82     result->value = i;
83     result->unitPrefixFactor = VM_NO_FACTOR;
84     result->unitBaseType = VM_NO_UNIT;
85     return result;
86 schoenebeck 2596 }
87    
88 schoenebeck 3557 VMFnResult* VMIntResultFunction::successResult(vmint i) {
89 schoenebeck 3747 result->flags = STMT_SUCCESS;
90     result->value = i;
91     result->unitPrefixFactor = VM_NO_FACTOR;
92     result->unitBaseType = VM_NO_UNIT;
93     return result;
94 schoenebeck 2581 }
95    
96 schoenebeck 3581 VMFnResult* VMIntResultFunction::errorResult(VMIntFnResDef res) {
97 schoenebeck 3747 result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
98     result->value = res.value;
99     result->unitPrefixFactor = res.unitFactor;
100     result->unitBaseType = VM_NO_UNIT;
101     return result;
102 schoenebeck 3581 }
103    
104     VMFnResult* VMIntResultFunction::successResult(VMIntFnResDef res) {
105 schoenebeck 3747 result->flags = STMT_SUCCESS;
106     result->value = res.value;
107     result->unitPrefixFactor = res.unitFactor;
108     result->unitBaseType = VM_NO_UNIT;
109     return result;
110 schoenebeck 3581 }
111    
112 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
113 schoenebeck 3573 // class VMRealResultFunction
114    
115 schoenebeck 3747 void VMRealResultFunction::bindResult(VMFnResult* res) {
116     result = dynamic_cast<VMRealResult*>(res);
117     }
118    
119     VMFnResult* VMRealResultFunction::boundResult() const {
120     return result;
121     }
122    
123 schoenebeck 3573 VMFnResult* VMRealResultFunction::errorResult(vmfloat f) {
124 schoenebeck 3747 result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
125     result->value = f;
126     result->unitPrefixFactor = VM_NO_FACTOR;
127     result->unitBaseType = VM_NO_UNIT;
128     return result;
129 schoenebeck 3573 }
130    
131 schoenebeck 3581 VMFnResult* VMRealResultFunction::errorResult(VMRealFnResDef res) {
132 schoenebeck 3747 result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
133     result->value = res.value;
134     result->unitPrefixFactor = res.unitFactor;
135     result->unitBaseType = VM_NO_UNIT;
136     return result;
137 schoenebeck 3581 }
138    
139 schoenebeck 3573 VMFnResult* VMRealResultFunction::successResult(vmfloat f) {
140 schoenebeck 3747 result->flags = STMT_SUCCESS;
141     result->value = f;
142     result->unitPrefixFactor = VM_NO_FACTOR;
143     result->unitBaseType = VM_NO_UNIT;
144     return result;
145 schoenebeck 3573 }
146    
147 schoenebeck 3581 VMFnResult* VMRealResultFunction::successResult(VMRealFnResDef res) {
148 schoenebeck 3747 result->flags = STMT_SUCCESS;
149     result->value = res.value;
150     result->unitPrefixFactor = res.unitFactor;
151     result->unitBaseType = VM_NO_UNIT;
152     return result;
153 schoenebeck 3581 }
154    
155 schoenebeck 3573 ///////////////////////////////////////////////////////////////////////////
156 schoenebeck 2727 // class VMStringResultFunction
157    
158 schoenebeck 3747 void VMStringResultFunction::bindResult(VMFnResult* res) {
159     result = dynamic_cast<VMStringResult*>(res);
160     }
161    
162     VMFnResult* VMStringResultFunction::boundResult() const {
163     return result;
164     }
165    
166 schoenebeck 2581 VMFnResult* VMStringResultFunction::errorResult(const String& s) {
167 schoenebeck 3747 result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
168     result->value = s;
169     return result;
170 schoenebeck 2581 }
171    
172     VMFnResult* VMStringResultFunction::successResult(const String& s) {
173 schoenebeck 3747 result->flags = STMT_SUCCESS;
174     result->value = s;
175     return result;
176 schoenebeck 2581 }
177    
178 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
179 schoenebeck 3582 // class VMNumberResultFunction
180 schoenebeck 3577
181 schoenebeck 3747 VMFnResult* VMNumberResultFunction::allocResult(VMFnArgs* args) {
182     ExprType_t type = returnType(args);
183     if (type == INT_EXPR)
184     return new VMIntResult();
185     if (type == REAL_EXPR)
186     return new VMRealResult();
187     assert(false);
188     return NULL; // just to avoid compiler error, we actually never get here
189     }
190    
191     VMFnResult* VMNumberResultFunction::boundResult() const {
192     if (intResult) return intResult;
193     return realResult;
194     }
195    
196     void VMNumberResultFunction::bindResult(VMFnResult* res) {
197     intResult = dynamic_cast<VMIntResult*>(res);
198     if (intResult) {
199     realResult = NULL;
200     return;
201     }
202     realResult = dynamic_cast<VMRealResult*>(res);
203     }
204    
205 schoenebeck 3582 VMFnResult* VMNumberResultFunction::errorResult(vmint i) {
206 schoenebeck 3747 intResult->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
207     intResult->value = i;
208     intResult->unitPrefixFactor = VM_NO_FACTOR;
209     intResult->unitBaseType = VM_NO_UNIT;
210     return intResult;
211 schoenebeck 3577 }
212    
213 schoenebeck 3582 VMFnResult* VMNumberResultFunction::errorResult(vmfloat f) {
214 schoenebeck 3747 realResult->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
215     realResult->value = f;
216     realResult->unitPrefixFactor = VM_NO_FACTOR;
217     intResult->unitBaseType = VM_NO_UNIT;
218     return realResult;
219 schoenebeck 3577 }
220    
221 schoenebeck 3582 VMFnResult* VMNumberResultFunction::successResult(vmint i) {
222 schoenebeck 3747 intResult->flags = STMT_SUCCESS;
223     intResult->value = i;
224     intResult->unitPrefixFactor = VM_NO_FACTOR;
225     intResult->unitBaseType = VM_NO_UNIT;
226     return intResult;
227 schoenebeck 3577 }
228    
229 schoenebeck 3582 VMFnResult* VMNumberResultFunction::successResult(vmfloat f) {
230 schoenebeck 3747 realResult->flags = STMT_SUCCESS;
231     realResult->value = f;
232     realResult->unitPrefixFactor = VM_NO_FACTOR;
233     realResult->unitBaseType = VM_NO_UNIT;
234     return realResult;
235 schoenebeck 3577 }
236    
237 schoenebeck 3582 VMFnResult* VMNumberResultFunction::errorIntResult(VMIntFnResDef res) {
238 schoenebeck 3747 intResult->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
239     intResult->value = res.value;
240     intResult->unitPrefixFactor = res.unitFactor;
241     intResult->unitBaseType = VM_NO_UNIT;
242     return intResult;
243 schoenebeck 3581 }
244    
245 schoenebeck 3582 VMFnResult* VMNumberResultFunction::errorRealResult(VMRealFnResDef res) {
246 schoenebeck 3747 realResult->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
247     realResult->value = res.value;
248     realResult->unitPrefixFactor = res.unitFactor;
249     realResult->unitBaseType = VM_NO_UNIT;
250     return realResult;
251 schoenebeck 3581 }
252    
253 schoenebeck 3582 VMFnResult* VMNumberResultFunction::successIntResult(VMIntFnResDef res) {
254 schoenebeck 3747 intResult->flags = STMT_SUCCESS;
255     intResult->value = res.value;
256     intResult->unitPrefixFactor = res.unitFactor;
257     intResult->unitBaseType = VM_NO_UNIT;
258     return intResult;
259 schoenebeck 3581 }
260    
261 schoenebeck 3582 VMFnResult* VMNumberResultFunction::successRealResult(VMRealFnResDef res) {
262 schoenebeck 3747 realResult->flags = STMT_SUCCESS;
263     realResult->value = res.value;
264     realResult->unitPrefixFactor = res.unitFactor;
265     realResult->unitBaseType = VM_NO_UNIT;
266     return realResult;
267 schoenebeck 3581 }
268    
269 schoenebeck 3577 ///////////////////////////////////////////////////////////////////////////
270 schoenebeck 2727 // built-in script function: message()
271    
272 schoenebeck 3557 bool CoreVMFunction_message::acceptsArgType(vmint iArg, ExprType_t type) const {
273 schoenebeck 3573 return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
274 schoenebeck 2581 }
275    
276     VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {
277     if (!args->argsCount()) return errorResult();
278    
279 schoenebeck 3285 uint64_t usecs = RTMath::unsafeMicroSeconds(RTMath::real_clock);
280    
281 schoenebeck 2581 VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(args->arg(0));
282     if (strExpr) {
283 schoenebeck 3285 printf("[ScriptVM %.3f] %s\n", usecs/1000000.f, strExpr->evalStr().c_str());
284 schoenebeck 2581 return successResult();
285     }
286    
287 schoenebeck 3573 VMRealExpr* realExpr = dynamic_cast<VMRealExpr*>(args->arg(0));
288     if (realExpr) {
289     printf("[ScriptVM %.3f] %f\n", usecs/1000000.f, realExpr->evalReal());
290     return successResult();
291     }
292    
293 schoenebeck 2581 VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
294     if (intExpr) {
295 schoenebeck 3707 printf("[ScriptVM %.3f] %" PRId64 "\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
296 schoenebeck 2581 return successResult();
297     }
298    
299     return errorResult();
300     }
301    
302 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
303     // built-in script function: exit()
304    
305 schoenebeck 3557 vmint CoreVMFunction_exit::maxAllowedArgs() const {
306 schoenebeck 3551 return (vm->isExitResultEnabled()) ? 1 : 0;
307     }
308    
309 schoenebeck 3557 bool CoreVMFunction_exit::acceptsArgType(vmint iArg, ExprType_t type) const {
310 schoenebeck 3551 if (!vm->isExitResultEnabled()) return false;
311 schoenebeck 3575 return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
312 schoenebeck 3551 }
313    
314 schoenebeck 3581 bool CoreVMFunction_exit::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
315     if (!vm->isExitResultEnabled()) return false;
316     return true;
317     }
318    
319     bool CoreVMFunction_exit::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
320     if (!vm->isExitResultEnabled()) return false;
321     return true;
322     }
323     bool CoreVMFunction_exit::acceptsArgFinal(vmint iArg) const {
324     if (!vm->isExitResultEnabled()) return false;
325     return true;
326     }
327    
328 schoenebeck 2581 VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
329 schoenebeck 3747 this->result->flags = STMT_ABORT_SIGNALLED;
330 schoenebeck 3551 if (vm->isExitResultEnabled() && args->argsCount()) {
331     ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
332     switch (args->arg(0)->exprType()) {
333 schoenebeck 3581 case INT_EXPR: {
334     VMIntExpr* expr = args->arg(0)->asInt();
335     ctx->exitRes.intLiteral = IntLiteral({
336     .value = expr->evalInt(),
337     .unitFactor = expr->unitFactor(),
338     .unitType = expr->unitType(),
339     .isFinal = expr->isFinal()
340     });
341 schoenebeck 3551 ctx->exitRes.value = &ctx->exitRes.intLiteral;
342     break;
343 schoenebeck 3581 }
344     case REAL_EXPR: {
345     VMRealExpr* expr = args->arg(0)->asReal();
346     ctx->exitRes.realLiteral = RealLiteral({
347     .value = expr->evalReal(),
348     .unitFactor = expr->unitFactor(),
349     .unitType = expr->unitType(),
350     .isFinal = expr->isFinal()
351     });
352 schoenebeck 3575 ctx->exitRes.value = &ctx->exitRes.realLiteral;
353     break;
354 schoenebeck 3581 }
355 schoenebeck 3551 case STRING_EXPR:
356 schoenebeck 3581 ctx->exitRes.stringLiteral = StringLiteral(
357     args->arg(0)->asString()->evalStr()
358     );
359 schoenebeck 3551 ctx->exitRes.value = &ctx->exitRes.stringLiteral;
360     break;
361     default:
362     ; // noop - just to shut up the compiler
363     }
364     }
365 schoenebeck 3747 return result;
366 schoenebeck 2581 }
367    
368 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
369     // built-in script function: wait()
370    
371 schoenebeck 3584 bool CoreVMFunction_wait::acceptsArgType(vmint iArg, ExprType_t type) const {
372     return type == INT_EXPR || type == REAL_EXPR;
373     }
374    
375 schoenebeck 3561 bool CoreVMFunction_wait::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
376 schoenebeck 3584 return type == VM_NO_UNIT || type == VM_SECOND;
377 schoenebeck 3561 }
378    
379 schoenebeck 3564 bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
380 schoenebeck 3584 return type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
381 schoenebeck 3561 }
382    
383 schoenebeck 2581 VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
384     ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
385 schoenebeck 3584 VMNumberExpr* expr = args->arg(0)->asNumber();
386 schoenebeck 3564 StdUnit_t unit = expr->unitType();
387 schoenebeck 3584 vmint us = (unit) ? expr->evalCastInt(VM_MICRO) : expr->evalCastInt();
388 schoenebeck 2972 if (us < 0) {
389 schoenebeck 3747 wrnMsg("wait(): argument may not be negative! Aborting handler!");
390     this->result->flags = STMT_ABORT_SIGNALLED;
391 schoenebeck 2972 } else if (us == 0) {
392 schoenebeck 3747 wrnMsg("wait(): argument may not be zero! Aborting handler!");
393     this->result->flags = STMT_ABORT_SIGNALLED;
394 schoenebeck 2972 } else {
395     ctx->suspendMicroseconds = us;
396 schoenebeck 3747 this->result->flags = STMT_SUSPEND_SIGNALLED;
397 schoenebeck 2972 }
398 schoenebeck 3747 return result;
399 schoenebeck 2581 }
400    
401 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
402     // built-in script function: abs()
403    
404 schoenebeck 3577 ExprType_t CoreVMFunction_abs::returnType(VMFnArgs* args) {
405     return args->arg(0)->exprType();
406     }
407    
408 schoenebeck 3581 StdUnit_t CoreVMFunction_abs::returnUnitType(VMFnArgs* args) {
409 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
410 schoenebeck 3581 }
411    
412     bool CoreVMFunction_abs::returnsFinal(VMFnArgs* args) {
413 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
414 schoenebeck 3581 }
415    
416 schoenebeck 3557 bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
417 schoenebeck 3577 return type == INT_EXPR || type == REAL_EXPR;
418 schoenebeck 2619 }
419    
420     VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
421 schoenebeck 3577 VMExpr* arg = args->arg(0);
422 schoenebeck 3581 if (arg->exprType() == REAL_EXPR) {
423     VMRealExpr* expr = arg->asReal();
424     return successRealResult({
425 persson 3596 .value = static_cast<vmfloat>(::fabs(expr->evalReal())),
426 schoenebeck 3581 .unitFactor = expr->unitFactor()
427     });
428     } else {
429     VMIntExpr* expr = arg->asInt();
430     return successIntResult({
431 persson 3596 .value = std::abs(expr->evalInt()),
432 schoenebeck 3581 .unitFactor = expr->unitFactor()
433     });
434     }
435 schoenebeck 2619 }
436    
437 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
438     // built-in script function: random()
439    
440 schoenebeck 3581 ExprType_t CoreVMFunction_random::returnType(VMFnArgs* args) {
441     return (args->arg(0)->exprType() == INT_EXPR &&
442     args->arg(1)->exprType() == INT_EXPR) ? INT_EXPR : REAL_EXPR;
443     }
444    
445     StdUnit_t CoreVMFunction_random::returnUnitType(VMFnArgs* args) {
446     // we ensure in checkArgs() below (which is called before this method here)
447     // that both arguments must be of same unit type, so either one is fine here
448 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
449 schoenebeck 3581 }
450    
451     bool CoreVMFunction_random::returnsFinal(VMFnArgs* args) {
452 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal() ||
453     args->arg(1)->asNumber()->isFinal();
454 schoenebeck 3581 }
455    
456 schoenebeck 3557 bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
457 schoenebeck 3581 return type == INT_EXPR || type == REAL_EXPR;
458 schoenebeck 2619 }
459    
460 schoenebeck 3581 void CoreVMFunction_random::checkArgs(VMFnArgs* args,
461     std::function<void(String)> err,
462     std::function<void(String)> wrn)
463     {
464     // super class checks
465     Super::checkArgs(args, err, wrn);
466    
467     // own checks ...
468 schoenebeck 3582 if (args->arg(0)->asNumber()->unitType() !=
469     args->arg(1)->asNumber()->unitType())
470 schoenebeck 3581 {
471 schoenebeck 3582 String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
472     String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
473 schoenebeck 3581 err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
474     return;
475     }
476 schoenebeck 3582 if (args->arg(0)->asNumber()->isFinal() !=
477     args->arg(1)->asNumber()->isFinal())
478 schoenebeck 3581 {
479 schoenebeck 3582 String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
480     String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
481 schoenebeck 3581 wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
482     }
483     }
484    
485 schoenebeck 2619 VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
486 schoenebeck 2620 float f = float(::rand()) / float(RAND_MAX);
487 schoenebeck 3581
488 schoenebeck 3582 VMNumberExpr* arg0 = args->arg(0)->asNumber();
489     VMNumberExpr* arg1 = args->arg(1)->asNumber();
490 schoenebeck 3581
491     if (arg0->exprType() == INT_EXPR && arg1->exprType() == INT_EXPR) {
492     vmint iMin = args->arg(0)->asInt()->evalInt();
493     vmint iMax = args->arg(1)->asInt()->evalInt();
494     if (arg0->unitFactor() == arg1->unitFactor()) {
495     return successIntResult({
496     .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
497     .unitFactor = arg0->unitFactor()
498     });
499     } else if (arg0->unitFactor() < arg1->unitFactor()) {
500     iMax = Unit::convIntToUnitFactor(iMax, arg1, arg0);
501     return successIntResult({
502     .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
503     .unitFactor = arg0->unitFactor()
504     });
505     } else { // arg0->unitFactor() > arg1->unitFactor() ...
506     iMin = Unit::convIntToUnitFactor(iMin, arg0, arg1);
507     return successIntResult({
508     .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
509     .unitFactor = arg1->unitFactor()
510     });
511     }
512     } else {
513     vmfloat fMin = arg0->evalCastReal();
514     vmfloat fMax = arg1->evalCastReal();
515     if (arg0->unitFactor() == arg1->unitFactor()) {
516     return successRealResult({
517     .value = fMin + f * (fMax - fMin),
518     .unitFactor = arg0->unitFactor()
519     });
520     } else if (arg0->unitFactor() < arg1->unitFactor()) {
521     fMax = Unit::convRealToUnitFactor(fMax, arg1, arg0);
522     return successRealResult({
523     .value = fMin + f * (fMax - fMin),
524     .unitFactor = arg0->unitFactor()
525     });
526     } else { // arg0->unitFactor() > arg1->unitFactor() ...
527     fMin = Unit::convRealToUnitFactor(fMin, arg0, arg1);
528     return successRealResult({
529     .value = fMin + f * (fMax - fMin),
530     .unitFactor = arg1->unitFactor()
531     });
532     }
533     }
534 schoenebeck 2619 }
535    
536 schoenebeck 2727 ///////////////////////////////////////////////////////////////////////////
537     // built-in script function: num_elements()
538    
539 schoenebeck 3557 bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
540 schoenebeck 3581 return isArray(type);
541 schoenebeck 2619 }
542    
543     VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
544 schoenebeck 3581 return successResult( args->arg(0)->asArray()->arraySize() );
545 schoenebeck 2619 }
546    
547 schoenebeck 2945 ///////////////////////////////////////////////////////////////////////////
548     // built-in script function: inc()
549    
550 schoenebeck 3581 StdUnit_t CoreVMFunction_inc::returnUnitType(VMFnArgs* args) {
551 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
552 schoenebeck 3581 }
553    
554     bool CoreVMFunction_inc::returnsFinal(VMFnArgs* args) {
555 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
556 schoenebeck 3581 }
557    
558     void CoreVMFunction_inc::checkArgs(VMFnArgs* args,
559     std::function<void(String)> err,
560     std::function<void(String)> wrn)
561     {
562     // super class checks
563     Super::checkArgs(args, err, wrn);
564    
565     // own checks ...
566 schoenebeck 3582 if (args->arg(0)->asNumber()->unitType()) {
567     String unitType = unitTypeStr(args->arg(0)->asNumber()->unitType());
568 schoenebeck 3581 wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be incremented by one.");
569     }
570     }
571    
572 schoenebeck 2945 VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
573     VMExpr* arg = args->arg(0);
574     VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
575     VMVariable* out = dynamic_cast<VMVariable*>(arg);
576 schoenebeck 3557 vmint i = in->evalInt() + 1;
577 schoenebeck 3581 IntLiteral tmp({
578     .value = i,
579     .unitFactor = in->unitFactor()
580     });
581 schoenebeck 2945 out->assignExpr(&tmp);
582 schoenebeck 3581 return successResult({
583     .value = i,
584     .unitFactor = in->unitFactor()
585     });
586 schoenebeck 2945 }
587    
588     ///////////////////////////////////////////////////////////////////////////
589     // built-in script function: dec()
590    
591 schoenebeck 3581 StdUnit_t CoreVMFunction_dec::returnUnitType(VMFnArgs* args) {
592 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
593 schoenebeck 3581 }
594    
595     bool CoreVMFunction_dec::returnsFinal(VMFnArgs* args) {
596 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
597 schoenebeck 3581 }
598    
599     void CoreVMFunction_dec::checkArgs(VMFnArgs* args,
600     std::function<void(String)> err,
601     std::function<void(String)> wrn)
602     {
603     // super class checks
604     Super::checkArgs(args, err, wrn);
605    
606     // own checks ...
607 schoenebeck 3582 if (args->arg(0)->asNumber()->unitType()) {
608     String unitType = unitTypeStr(args->arg(0)->asNumber()->unitType());
609 schoenebeck 3581 wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be decremented by one.");
610     }
611     }
612    
613 schoenebeck 2945 VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
614     VMExpr* arg = args->arg(0);
615     VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
616     VMVariable* out = dynamic_cast<VMVariable*>(arg);
617 schoenebeck 3557 vmint i = in->evalInt() - 1;
618 schoenebeck 3581 IntLiteral tmp({
619     .value = i,
620     .unitFactor = in->unitFactor()
621     });
622 schoenebeck 2945 out->assignExpr(&tmp);
623 schoenebeck 3581 return successResult({
624     .value = i,
625     .unitFactor = in->unitFactor()
626     });
627 schoenebeck 2945 }
628    
629 schoenebeck 2965 ///////////////////////////////////////////////////////////////////////////
630 schoenebeck 3076 // built-in script function: in_range()
631    
632 schoenebeck 3581 bool CoreVMFunction_in_range::acceptsArgType(vmint iArg, ExprType_t type) const {
633     return type == INT_EXPR || type == REAL_EXPR;
634     }
635    
636     void CoreVMFunction_in_range::checkArgs(VMFnArgs* args,
637     std::function<void(String)> err,
638     std::function<void(String)> wrn)
639     {
640     // super class checks
641     Super::checkArgs(args, err, wrn);
642    
643     // own checks ...
644 schoenebeck 3582 if (args->arg(0)->asNumber()->unitType() !=
645     args->arg(1)->asNumber()->unitType() ||
646     args->arg(1)->asNumber()->unitType() !=
647     args->arg(2)->asNumber()->unitType())
648 schoenebeck 3581 {
649 schoenebeck 3582 String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
650     String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
651     String c = unitTypeStr(args->arg(2)->asNumber()->unitType());
652 schoenebeck 3581 err("Arguments must all have same unit, however argument 1 is " + a +
653     ", argument 2 is " + b + ", argument 3 is " + c + ".");
654     return;
655 schoenebeck 3076 }
656 schoenebeck 3581 if (args->arg(0)->exprType() != args->arg(1)->exprType() ||
657     args->arg(1)->exprType() != args->arg(2)->exprType())
658     {
659     String a = typeStr(args->arg(0)->exprType());
660     String b = typeStr(args->arg(1)->exprType());
661     String c = typeStr(args->arg(2)->exprType());
662     String r = typeStr(REAL_EXPR);
663     wrn("Argument 1 is " + a + ", argument 2 is " + b +
664     ", argument 3 is " + c + ", function result will be " + r + ".");
665     }
666 schoenebeck 3076 }
667    
668 schoenebeck 3581 template<class T>
669     inline void _swapByValue(T& a, T& b) {
670     T tmp = a;
671     a = b;
672     b = tmp;
673     }
674    
675     VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
676 schoenebeck 3582 VMNumberExpr* argNeedle = args->arg(0)->asNumber();
677     VMNumberExpr* argLo = args->arg(1)->asNumber();
678     VMNumberExpr* argHi = args->arg(2)->asNumber();
679 schoenebeck 3581
680     vmfloat needle = argNeedle->evalCastReal();
681     vmfloat lo = argLo->evalCastReal();
682     vmfloat hi = argHi->evalCastReal();
683    
684     needle *= argNeedle->unitFactor();
685     lo *= argLo->unitFactor();
686     hi *= argHi->unitFactor();
687    
688     if (lo > hi) _swapByValue(lo, hi);
689    
690     return successResult(needle >= lo && needle <= hi);
691     }
692    
693 schoenebeck 3076 ///////////////////////////////////////////////////////////////////////////
694 schoenebeck 2965 // built-in script function: sh_left()
695    
696 schoenebeck 3581 bool CoreVMFunction_sh_left::returnsFinal(VMFnArgs* args) {
697 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
698 schoenebeck 3581 }
699    
700 schoenebeck 2965 VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
701 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
702     vmint n = args->arg(1)->asInt()->evalInt();
703 schoenebeck 2965 return successResult(i << n);
704     }
705    
706     ///////////////////////////////////////////////////////////////////////////
707     // built-in script function: sh_right()
708    
709 schoenebeck 3581 bool CoreVMFunction_sh_right::returnsFinal(VMFnArgs* args) {
710 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
711 schoenebeck 3581 }
712    
713 schoenebeck 2965 VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
714 schoenebeck 3557 vmint i = args->arg(0)->asInt()->evalInt();
715     vmint n = args->arg(1)->asInt()->evalInt();
716 schoenebeck 2965 return successResult(i >> n);
717     }
718    
719 schoenebeck 2970 ///////////////////////////////////////////////////////////////////////////
720 schoenebeck 3678 // built-in script function: msb()
721    
722     VMFnResult* CoreVMFunction_msb::exec(VMFnArgs* args) {
723     vmint i = args->arg(0)->asInt()->evalInt();
724     return successResult((i >> 7) & 127);
725     }
726    
727     ///////////////////////////////////////////////////////////////////////////
728     // built-in script function: lsb()
729    
730     VMFnResult* CoreVMFunction_lsb::exec(VMFnArgs* args) {
731     vmint i = args->arg(0)->asInt()->evalInt();
732     return successResult(i & 127);
733     }
734    
735     ///////////////////////////////////////////////////////////////////////////
736 schoenebeck 2970 // built-in script function: min()
737    
738 schoenebeck 3577 ExprType_t CoreVMFunction_min::returnType(VMFnArgs* args) {
739     return (args->arg(0)->exprType() == REAL_EXPR ||
740     args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
741     }
742    
743 schoenebeck 3581 StdUnit_t CoreVMFunction_min::returnUnitType(VMFnArgs* args) {
744 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
745 schoenebeck 3581 }
746    
747     bool CoreVMFunction_min::returnsFinal(VMFnArgs* args) {
748 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal() ||
749     args->arg(1)->asNumber()->isFinal();
750 schoenebeck 3581 }
751    
752 schoenebeck 3577 bool CoreVMFunction_min::acceptsArgType(vmint iArg, ExprType_t type) const {
753     return type == INT_EXPR || type == REAL_EXPR;
754     }
755    
756 schoenebeck 3581 void CoreVMFunction_min::checkArgs(VMFnArgs* args,
757     std::function<void(String)> err,
758     std::function<void(String)> wrn)
759     {
760     // super class checks
761     Super::checkArgs(args, err, wrn);
762    
763     // own checks ...
764 schoenebeck 3582 if (args->arg(0)->asNumber()->unitType() !=
765     args->arg(1)->asNumber()->unitType())
766 schoenebeck 3581 {
767 schoenebeck 3582 String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
768     String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
769 schoenebeck 3581 err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
770     return;
771     }
772     if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
773     String a = typeStr(args->arg(0)->exprType());
774     String b = typeStr(args->arg(1)->exprType());
775     String c = typeStr(REAL_EXPR);
776     wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be " + c + ".");
777     return;
778     }
779 schoenebeck 3582 if (args->arg(0)->asNumber()->isFinal() !=
780     args->arg(1)->asNumber()->isFinal())
781 schoenebeck 3581 {
782 schoenebeck 3582 String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
783     String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
784 schoenebeck 3581 wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
785     }
786     }
787    
788 schoenebeck 2970 VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
789 schoenebeck 3582 VMNumberExpr* lhs = args->arg(0)->asNumber();
790     VMNumberExpr* rhs = args->arg(1)->asNumber();
791 schoenebeck 3581 if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
792     vmfloat lm = lhs->asReal()->evalReal();
793     vmfloat rm = rhs->asReal()->evalReal();
794     vmfloat lprod = lm * lhs->unitFactor();
795     vmfloat rprod = rm * rhs->unitFactor();
796     return successRealResult({
797     .value = (lprod < rprod) ? lm : rm,
798     .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
799     });
800     } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
801     vmfloat lm = lhs->asReal()->evalReal();
802     vmint rm = rhs->asInt()->evalInt();
803     vmfloat lprod = lm * lhs->unitFactor();
804     vmfloat rprod = rm * rhs->unitFactor();
805     return successRealResult({
806     .value = (lprod < rprod) ? lm : rm,
807     .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
808     });
809     } else if (lhs->exprType() == INT_EXPR && rhs->exprType() == REAL_EXPR) {
810     vmint lm = lhs->asInt()->evalInt();
811     vmfloat rm = rhs->asReal()->evalReal();
812     vmfloat lprod = lm * lhs->unitFactor();
813     vmfloat rprod = rm * rhs->unitFactor();
814     return successRealResult({
815     .value = (lprod < rprod) ? lm : rm,
816     .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
817     });
818 schoenebeck 3577 } else {
819 schoenebeck 3581 vmint lm = lhs->asInt()->evalInt();
820     vmint rm = rhs->asInt()->evalInt();
821     vmfloat lprod = lm * lhs->unitFactor();
822     vmfloat rprod = rm * rhs->unitFactor();
823     return successIntResult({
824     .value = (lprod < rprod) ? lm : rm,
825     .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
826     });
827 schoenebeck 3577 }
828 schoenebeck 2970 }
829    
830     ///////////////////////////////////////////////////////////////////////////
831     // built-in script function: max()
832    
833 schoenebeck 3577 ExprType_t CoreVMFunction_max::returnType(VMFnArgs* args) {
834     return (args->arg(0)->exprType() == REAL_EXPR ||
835     args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
836     }
837    
838 schoenebeck 3581 StdUnit_t CoreVMFunction_max::returnUnitType(VMFnArgs* args) {
839 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
840 schoenebeck 3581 }
841    
842     bool CoreVMFunction_max::returnsFinal(VMFnArgs* args) {
843 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal() ||
844     args->arg(1)->asNumber()->isFinal();
845 schoenebeck 3581 }
846    
847 schoenebeck 3577 bool CoreVMFunction_max::acceptsArgType(vmint iArg, ExprType_t type) const {
848     return type == INT_EXPR || type == REAL_EXPR;
849     }
850    
851 schoenebeck 3581 void CoreVMFunction_max::checkArgs(VMFnArgs* args,
852     std::function<void(String)> err,
853     std::function<void(String)> wrn)
854     {
855     // super class checks
856     Super::checkArgs(args, err, wrn);
857    
858     // own checks ...
859 schoenebeck 3582 if (args->arg(0)->asNumber()->unitType() !=
860     args->arg(1)->asNumber()->unitType())
861 schoenebeck 3581 {
862 schoenebeck 3582 String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
863     String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
864 schoenebeck 3581 err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
865     return;
866     }
867     if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
868     String a = typeStr(args->arg(0)->exprType());
869     String b = typeStr(args->arg(1)->exprType());
870     String c = typeStr(REAL_EXPR);
871     wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be " + c + ".");
872     return;
873     }
874 schoenebeck 3582 if (args->arg(0)->asNumber()->isFinal() !=
875     args->arg(1)->asNumber()->isFinal())
876 schoenebeck 3581 {
877 schoenebeck 3582 String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
878     String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
879 schoenebeck 3581 wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
880     }
881     }
882    
883 schoenebeck 2970 VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
884 schoenebeck 3582 VMNumberExpr* lhs = args->arg(0)->asNumber();
885     VMNumberExpr* rhs = args->arg(1)->asNumber();
886 schoenebeck 3581 if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
887     vmfloat lm = lhs->asReal()->evalReal();
888     vmfloat rm = rhs->asReal()->evalReal();
889     vmfloat lprod = lm * lhs->unitFactor();
890     vmfloat rprod = rm * rhs->unitFactor();
891     return successRealResult({
892     .value = (lprod > rprod) ? lm : rm,
893     .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
894     });
895     } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
896     vmfloat lm = lhs->asReal()->evalReal();
897     vmint rm = rhs->asInt()->evalInt();
898     vmfloat lprod = lm * lhs->unitFactor();
899     vmfloat rprod = rm * rhs->unitFactor();
900     return successRealResult({
901     .value = (lprod > rprod) ? lm : rm,
902     .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
903     });
904     } else if (lhs->exprType() == INT_EXPR && rhs->exprType() == REAL_EXPR) {
905     vmint lm = lhs->asInt()->evalInt();
906     vmfloat rm = rhs->asReal()->evalReal();
907     vmfloat lprod = lm * lhs->unitFactor();
908     vmfloat rprod = rm * rhs->unitFactor();
909     return successRealResult({
910     .value = (lprod > rprod) ? lm : rm,
911     .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
912     });
913 schoenebeck 3577 } else {
914 schoenebeck 3581 vmint lm = lhs->asInt()->evalInt();
915     vmint rm = rhs->asInt()->evalInt();
916     vmfloat lprod = lm * lhs->unitFactor();
917     vmfloat rprod = rm * rhs->unitFactor();
918     return successIntResult({
919     .value = (lprod > rprod) ? lm : rm,
920     .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
921     });
922 schoenebeck 3577 }
923 schoenebeck 2970 }
924    
925 schoenebeck 3221 ///////////////////////////////////////////////////////////////////////////
926     // built-in script function: array_equal()
927    
928 schoenebeck 3581 bool CoreVMFunction_array_equal::acceptsArgType(vmint iArg, ExprType_t type) const {
929     return isArray(type);
930     }
931    
932     void CoreVMFunction_array_equal::checkArgs(VMFnArgs* args,
933     std::function<void(String)> err,
934     std::function<void(String)> wrn)
935     {
936     // super class checks
937     Super::checkArgs(args, err, wrn);
938    
939     // own checks ...
940     if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
941     String a = typeStr(args->arg(0)->exprType());
942     String b = typeStr(args->arg(1)->exprType());
943     err("Argument 1 is " + a + ", whereas argument 2 is " + b + ".");
944     return;
945     }
946     if (args->arg(0)->asArray()->arraySize() !=
947     args->arg(1)->asArray()->arraySize())
948     {
949     wrn("Result of function call is always false, since the passed two arrays were declared with different array sizes.");
950     }
951     }
952    
953 schoenebeck 3221 VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
954 schoenebeck 3581 VMArrayExpr* l = args->arg(0)->asArray();
955     VMArrayExpr* r = args->arg(1)->asArray();
956 schoenebeck 3221 if (l->arraySize() != r->arraySize()) {
957 schoenebeck 3581 //wrnMsg("array_equal(): the two arrays differ in size");
958 schoenebeck 3221 return successResult(0); // false
959     }
960 schoenebeck 3557 const vmint n = l->arraySize();
961 schoenebeck 3581 // checkArgs() above ensured that we either have INT_ARR_EXPR on both sides
962     // or REAL_ARR_EXPR on both sides, so we can simplify here (a bit)
963     if (l->exprType() == INT_ARR_EXPR) {
964     VMIntArrayExpr* lia = l->asIntArray();
965     VMIntArrayExpr* ria = r->asIntArray();
966     for (vmint i = 0; i < n; ++i) {
967     vmint lvalue = lia->evalIntElement(i);
968     vmint rvalue = ria->evalIntElement(i);
969     vmfloat lfactor = lia->unitFactorOfElement(i);
970     vmfloat rfactor = ria->unitFactorOfElement(i);
971     if (lfactor == rfactor) {
972     if (lvalue != rvalue)
973     return successResult(0); // false
974     else
975     continue;
976     }
977     if (lfactor < rfactor) {
978     if (lvalue != Unit::convIntToUnitFactor(rvalue, rfactor, lfactor))
979     return successResult(0); // false
980     else
981     continue;
982     } else {
983     if (rvalue != Unit::convIntToUnitFactor(lvalue, lfactor, rfactor))
984     return successResult(0); // false
985     else
986     continue;
987     }
988     }
989     } else {
990     VMRealArrayExpr* lra = l->asRealArray();
991     VMRealArrayExpr* rra = r->asRealArray();
992     for (vmint i = 0; i < n; ++i) {
993     vmfloat lvalue = lra->evalRealElement(i);
994     vmfloat rvalue = rra->evalRealElement(i);
995     vmfloat lfactor = lra->unitFactorOfElement(i);
996     vmfloat rfactor = rra->unitFactorOfElement(i);
997     if (lfactor == rfactor) {
998     if (!_fEqualX(lvalue, rvalue))
999     return successResult(0); // false
1000     else
1001     continue;
1002     }
1003     if (lfactor < rfactor) {
1004     if (!_fEqualX(lvalue, Unit::convRealToUnitFactor(rvalue, rfactor, lfactor)))
1005     return successResult(0); // false
1006     else
1007     continue;
1008     } else {
1009     if (!_fEqualX(rvalue, Unit::convRealToUnitFactor(lvalue, lfactor, rfactor)))
1010     return successResult(0); // false
1011     else
1012     continue;
1013     }
1014     }
1015     }
1016 schoenebeck 3221 return successResult(1); // true
1017     }
1018    
1019     ///////////////////////////////////////////////////////////////////////////
1020     // built-in script function: search()
1021    
1022 schoenebeck 3557 bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
1023 schoenebeck 3221 if (iArg == 0)
1024 schoenebeck 3581 return isArray(type);
1025 schoenebeck 3221 else
1026 schoenebeck 3581 return type == INT_EXPR || type == REAL_EXPR;
1027 schoenebeck 3221 }
1028    
1029 schoenebeck 3581 void CoreVMFunction_search::checkArgs(VMFnArgs* args,
1030     std::function<void(String)> err,
1031     std::function<void(String)> wrn)
1032     {
1033     // super class checks
1034     Super::checkArgs(args, err, wrn);
1035    
1036     // own checks ...
1037     if (args->arg(0)->exprType() == INT_ARR_EXPR &&
1038     args->arg(1)->exprType() != INT_EXPR)
1039     {
1040     String a = typeStr(INT_ARR_EXPR);
1041     String bIs = typeStr(args->arg(1)->exprType());
1042     String bShould = typeStr(INT_EXPR);
1043     err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
1044     return;
1045     }
1046     if (args->arg(0)->exprType() == REAL_ARR_EXPR &&
1047     args->arg(1)->exprType() != REAL_EXPR)
1048     {
1049     String a = typeStr(REAL_ARR_EXPR);
1050     String bIs = typeStr(args->arg(1)->exprType());
1051     String bShould = typeStr(REAL_EXPR);
1052     err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
1053     return;
1054     }
1055     }
1056    
1057 schoenebeck 3221 VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
1058 schoenebeck 3581 VMArrayExpr* a = args->arg(0)->asArray();
1059 schoenebeck 3557 const vmint n = a->arraySize();
1060 schoenebeck 3581 if (a->exprType() == INT_ARR_EXPR) {
1061     const vmint needle = args->arg(1)->asInt()->evalInt();
1062     VMIntArrayExpr* intArray = a->asIntArray();
1063     for (vmint i = 0; i < n; ++i)
1064     if (intArray->evalIntElement(i) == needle)
1065     return successResult(i);
1066     } else { // real array ...
1067     const vmfloat needle = args->arg(1)->asReal()->evalReal();
1068     VMRealArrayExpr* realArray = a->asRealArray();
1069     for (vmint i = 0; i < n; ++i) {
1070     const vmfloat value = realArray->evalRealElement(i);
1071     if (_fEqualX(value, needle))
1072     return successResult(i);
1073     }
1074     }
1075 schoenebeck 3221 return successResult(-1); // not found
1076     }
1077    
1078     ///////////////////////////////////////////////////////////////////////////
1079     // built-in script function: sort()
1080    
1081 schoenebeck 3557 bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
1082 schoenebeck 3221 if (iArg == 0)
1083 schoenebeck 3581 return isArray(type);
1084 schoenebeck 3221 else
1085     return type == INT_EXPR;
1086     }
1087    
1088 schoenebeck 3581 // The following structs and template classes act as adapters for allowing to
1089     // use std sort algorithms on our arrays. It might look a bit more complicated
1090     // than it ought to be, but there is one reason for the large amount of
1091     // 'adapter' code below: the STL std algorithms rely on 'lvalues' to do their
1092 schoenebeck 3590 // (e.g. sorting) jobs, that is they expect containers to have 'localizeable'
1093 schoenebeck 3581 // data which essentially means their data should reside somewhere in memory and
1094     // directly be accessible (readable and writable) there, which is not the case
1095     // with our VM interfaces which actually always require virtual getter and
1096     // setter methods to be called instead. So we must emulate lvalues by custom
1097     // classes/structs which forward between our getters/setters and the lvalue
1098     // access operators used by the STL std algorithms.
1099    
1100     struct IntArrayAccessor {
1101     static inline vmint getPrimaryValue(VMIntArrayExpr* arr, vmint index) {
1102     return arr->evalIntElement(index);
1103     }
1104     static inline void setPrimaryValue(VMIntArrayExpr* arr, vmint index, vmint value) {
1105     arr->assignIntElement(index, value);
1106     }
1107     };
1108    
1109     struct RealArrayAccessor {
1110     static inline vmfloat getPrimaryValue(VMRealArrayExpr* arr, vmint index) {
1111     return arr->evalRealElement(index);
1112     }
1113     static inline void setPrimaryValue(VMRealArrayExpr* arr, vmint index, vmfloat value) {
1114     arr->assignRealElement(index, value);
1115     }
1116     };
1117    
1118     template<class T_array> // i.e. T_array is either VMIntArrayExpr or VMRealArrayExpr
1119 schoenebeck 3221 struct ArrElemPOD {
1120 schoenebeck 3581 T_array* m_array;
1121 schoenebeck 3557 vmint m_index;
1122 schoenebeck 3221 };
1123    
1124 schoenebeck 3581 // This class is used for temporary values by std::sort().
1125     template<class T_value> // i.e. T_value is either vmint or vmfloat
1126     struct ScalarNmbrVal {
1127     T_value primValue;
1128     vmfloat unitFactor;
1129 schoenebeck 3221
1130 schoenebeck 3581 inline bool operator<(const ScalarNmbrVal& other) const {
1131     return getProdValue() < other.getProdValue();
1132     }
1133     inline bool operator>(const ScalarNmbrVal& other) const {
1134     return getProdValue() > other.getProdValue();
1135     }
1136     inline vmfloat getProdValue() const {
1137     // simple solution for both vmint and vmfloat, should be fine for just sorting
1138     return primValue * unitFactor;
1139     }
1140     };
1141    
1142     // This class emulates lvalue access (access by reference) which is used by ArrExprIter::operator*() below.
1143     template<class T_array, // T_array is either VMIntArrayExpr or VMRealArrayExpr
1144     class T_value, // T_value is either vmint or vmfloat
1145     class T_accessor> // T_accessor is either IntArrayAccessor or RealArrayAccessor
1146     class ArrElemRef : protected ArrElemPOD<T_array> {
1147 schoenebeck 3221 public:
1148 schoenebeck 3595 typedef ::LinuxSampler::ScalarNmbrVal<T_value> ScalarNmbrVal; // GCC 8.x requires this very detailed form of typedef (that is ::LinuxSampler:: as prefix), IMO a GCC bug
1149 schoenebeck 3581
1150     inline ArrElemRef(T_array* a, vmint index) {
1151     this->m_array = a;
1152     this->m_index = index;
1153 schoenebeck 3221 }
1154 schoenebeck 3581 inline ArrElemRef(const ArrElemRef& ref) {
1155     this->m_array = ref.m_array;
1156     this->m_index = ref.m_index;
1157 schoenebeck 3221 }
1158     inline ArrElemRef& operator=(const ArrElemRef& e) {
1159 schoenebeck 3581 setPrimValue(e.getPrimValue());
1160     setUnitFactor(e.getUnitFactor());
1161 schoenebeck 3221 return *this;
1162     }
1163 schoenebeck 3581 inline ArrElemRef& operator=(ScalarNmbrVal value) {
1164     setPrimValue(value.primValue);
1165     setUnitFactor(value.unitFactor);
1166 schoenebeck 3221 return *this;
1167     }
1168     inline bool operator==(const ArrElemRef& e) const {
1169 schoenebeck 3581 return getProdValue() == e.getProdValue();
1170 schoenebeck 3221 }
1171     inline bool operator!=(const ArrElemRef& e) const {
1172     return !(operator==(e));
1173     }
1174     inline bool operator<(const ArrElemRef& e) const {
1175 schoenebeck 3581 return getProdValue() < e.getProdValue();
1176 schoenebeck 3221 }
1177     inline bool operator>(const ArrElemRef& e) const {
1178 schoenebeck 3581 return getProdValue() > e.getProdValue();
1179 schoenebeck 3221 }
1180     inline bool operator<=(const ArrElemRef& e) const {
1181 schoenebeck 3581 return getProdValue() <= e.getProdValue();
1182 schoenebeck 3221 }
1183     inline bool operator>=(const ArrElemRef& e) const {
1184 schoenebeck 3581 return getProdValue() >= e.getProdValue();
1185 schoenebeck 3221 }
1186 schoenebeck 3581 inline bool operator==(const ScalarNmbrVal& s) const {
1187     return getProdValue() == s.getProdValue();
1188 schoenebeck 3221 }
1189 schoenebeck 3581 inline bool operator!=(const ScalarNmbrVal& s) const {
1190     return !(operator==(s));
1191 schoenebeck 3221 }
1192 schoenebeck 3581 inline bool operator<(const ScalarNmbrVal& s) const {
1193     return getProdValue() < s.getProdValue();
1194     }
1195     inline bool operator>(const ScalarNmbrVal& s) const {
1196     return getProdValue() > s.getProdValue();
1197     }
1198     inline bool operator<=(const ScalarNmbrVal& s) const {
1199     return getProdValue() <= s.getProdValue();
1200     }
1201     inline bool operator>=(const ScalarNmbrVal& s) const {
1202     return getProdValue() >= s.getProdValue();
1203     }
1204     inline operator ScalarNmbrVal() {
1205     return {
1206     .primValue = getPrimValue() ,
1207     .unitFactor = getUnitFactor()
1208     };
1209     }
1210 schoenebeck 3221 protected:
1211 schoenebeck 3581 inline T_value getPrimValue() const {
1212     return T_accessor::getPrimaryValue( this->m_array, this->m_index );
1213 schoenebeck 3221 }
1214 schoenebeck 3581 inline void setPrimValue(T_value value) {
1215     T_accessor::setPrimaryValue( this->m_array, this->m_index, value );
1216 schoenebeck 3221 }
1217 schoenebeck 3581 inline vmfloat getUnitFactor() const {
1218     return this->m_array->unitFactorOfElement(this->m_index);
1219 schoenebeck 3221 }
1220 schoenebeck 3581 inline void setUnitFactor(vmfloat factor) {
1221     this->m_array->assignElementUnitFactor(this->m_index, factor);
1222 schoenebeck 3221 }
1223 schoenebeck 3581 inline vmfloat getProdValue() const {
1224     // simple solution for both vmint and vmfloat, should be fine for just sorting
1225     vmfloat primary = (vmfloat) getPrimValue();
1226     vmfloat factor = getUnitFactor();
1227     return primary * factor;
1228 schoenebeck 3221 }
1229 schoenebeck 3581
1230     // allow swap() functions below to access protected methods here
1231     friend void swap(class ArrElemRef<T_array,T_value,T_accessor> a,
1232     class ArrElemRef<T_array,T_value,T_accessor> b);
1233 schoenebeck 3221 };
1234    
1235 schoenebeck 3581 // custom iterator class to be used by std:sort() on our VM arrays
1236     template<class T_array, class T_value, class T_accessor>
1237     class ArrExprIter : public ArrElemPOD<T_array> {
1238 schoenebeck 3221 public:
1239     typedef std::random_access_iterator_tag iterator_category;
1240     typedef ssize_t difference_type;
1241 schoenebeck 3595 typedef ::LinuxSampler::ArrElemRef<T_array, T_value, T_accessor> ArrElemRef; // GCC 8.x requires this very detailed form of typedef (that is ::LinuxSampler:: as prefix), IMO a GCC bug
1242 schoenebeck 3581 typedef ArrElemRef reference; // type used by STL for access by reference
1243     typedef void pointer; // type used by STL for -> operator result, we don't use that operator at all so just void it
1244     typedef ScalarNmbrVal<T_value> value_type; // type used by STL for temporary values
1245 schoenebeck 3221
1246 schoenebeck 3581 ArrExprIter(T_array* a, vmint index) {
1247     this->m_array = a;
1248     this->m_index = index;
1249 schoenebeck 3221 }
1250 schoenebeck 3581 ArrExprIter(const ArrElemRef& ref) {
1251     this->m_array = ref.m_array;
1252     this->m_index = ref.m_index;
1253     }
1254 schoenebeck 3221 inline ArrElemRef operator*() {
1255 schoenebeck 3581 return ArrElemRef(this->m_array, this->m_index);
1256 schoenebeck 3221 }
1257     inline ArrExprIter& operator++() { // prefix increment
1258 schoenebeck 3581 ++(this->m_index);
1259 schoenebeck 3221 return *this;
1260     }
1261     inline ArrExprIter& operator--() { // prefix decrement
1262 schoenebeck 3581 --(this->m_index);
1263 schoenebeck 3221 return *this;
1264     }
1265     inline ArrExprIter operator++(int) { // postfix increment
1266     ArrExprIter it = *this;
1267 schoenebeck 3581 ++(this->m_index);
1268 schoenebeck 3221 return it;
1269     }
1270     inline ArrExprIter operator--(int) { // postfix decrement
1271     ArrExprIter it = *this;
1272 schoenebeck 3581 --(this->m_index);
1273 schoenebeck 3221 return it;
1274     }
1275 schoenebeck 3345 inline ArrExprIter& operator+=(difference_type d) {
1276 schoenebeck 3581 this->m_index += d;
1277 schoenebeck 3345 return *this;
1278     }
1279     inline ArrExprIter& operator-=(difference_type d) {
1280 schoenebeck 3581 this->m_index -= d;
1281 schoenebeck 3345 return *this;
1282     }
1283 schoenebeck 3221 inline bool operator==(const ArrExprIter& other) const {
1284 schoenebeck 3581 return this->m_index == other.m_index;
1285 schoenebeck 3221 }
1286     inline bool operator!=(const ArrExprIter& other) const {
1287 schoenebeck 3581 return this->m_index != other.m_index;
1288 schoenebeck 3221 }
1289     inline bool operator<(const ArrExprIter& other) const {
1290 schoenebeck 3581 return this->m_index < other.m_index;
1291 schoenebeck 3221 }
1292     inline bool operator>(const ArrExprIter& other) const {
1293 schoenebeck 3581 return this->m_index > other.m_index;
1294 schoenebeck 3221 }
1295     inline bool operator<=(const ArrExprIter& other) const {
1296 schoenebeck 3581 return this->m_index <= other.m_index;
1297 schoenebeck 3221 }
1298     inline bool operator>=(const ArrExprIter& other) const {
1299 schoenebeck 3581 return this->m_index >= other.m_index;
1300 schoenebeck 3221 }
1301     inline difference_type operator+(const ArrExprIter& other) const {
1302 schoenebeck 3581 return this->m_index + other.m_index;
1303 schoenebeck 3221 }
1304     inline difference_type operator-(const ArrExprIter& other) const {
1305 schoenebeck 3581 return this->m_index - other.m_index;
1306 schoenebeck 3221 }
1307     inline ArrExprIter operator-(difference_type d) const {
1308 schoenebeck 3581 return ArrExprIter(this->m_array, this->m_index - d);
1309 schoenebeck 3221 }
1310     inline ArrExprIter operator+(difference_type d) const {
1311 schoenebeck 3581 return ArrExprIter(this->m_array, this->m_index + d);
1312 schoenebeck 3221 }
1313     inline ArrExprIter operator*(difference_type factor) const {
1314 schoenebeck 3581 return ArrExprIter(this->m_array, this->m_index * factor);
1315 schoenebeck 3221 }
1316     };
1317    
1318 schoenebeck 3581 typedef ArrExprIter<VMIntArrayExpr,vmint,IntArrayAccessor> IntArrExprIter;
1319     typedef ArrExprIter<VMRealArrayExpr,vmfloat,RealArrayAccessor> RealArrExprIter;
1320    
1321     // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1322 schoenebeck 3595 inline void swap(IntArrExprIter::ArrElemRef a,
1323     IntArrExprIter::ArrElemRef b)
1324 schoenebeck 3581 {
1325     vmint valueA = a.getPrimValue();
1326     vmint valueB = b.getPrimValue();
1327     vmfloat factorA = a.getUnitFactor();
1328     vmfloat factorB = b.getUnitFactor();
1329     a.setPrimValue(valueB);
1330     a.setUnitFactor(factorB);
1331     b.setPrimValue(valueA);
1332     b.setUnitFactor(factorA);
1333     }
1334    
1335     // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1336 schoenebeck 3595 inline void swap(RealArrExprIter::ArrElemRef a,
1337     RealArrExprIter::ArrElemRef b)
1338 schoenebeck 3581 {
1339     vmfloat valueA = a.getPrimValue();
1340     vmfloat valueB = b.getPrimValue();
1341     vmfloat factorA = a.getUnitFactor();
1342     vmfloat factorB = b.getUnitFactor();
1343     a.setPrimValue(valueB);
1344     a.setUnitFactor(factorB);
1345     b.setPrimValue(valueA);
1346     b.setUnitFactor(factorA);
1347     }
1348    
1349     // used to sort in descending order (unlike the default behaviour of std::sort() which is ascending order)
1350     template<class T> // T is either IntArrExprIter or RealArrExprIter
1351 schoenebeck 3221 struct DescArrExprSorter {
1352 schoenebeck 3581 inline bool operator()(const typename T::value_type a, const typename T::value_type b) const {
1353 schoenebeck 3221 return a > b;
1354     }
1355     };
1356    
1357     VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
1358 schoenebeck 3581 const bool bAscending =
1359 schoenebeck 3221 (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
1360 schoenebeck 3581
1361     if (args->arg(0)->exprType() == INT_ARR_EXPR) {
1362     VMIntArrayExpr* a = args->arg(0)->asIntArray();
1363     vmint n = a->arraySize();
1364     IntArrExprIter itBegin(a, 0);
1365     IntArrExprIter itEnd(a, n);
1366     if (bAscending) {
1367     std::sort(itBegin, itEnd);
1368     } else {
1369     DescArrExprSorter<IntArrExprIter> sorter;
1370     std::sort(itBegin, itEnd, sorter);
1371     }
1372 schoenebeck 3221 } else {
1373 schoenebeck 3581 VMRealArrayExpr* a = args->arg(0)->asRealArray();
1374     vmint n = a->arraySize();
1375     RealArrExprIter itBegin(a, 0);
1376     RealArrExprIter itEnd(a, n);
1377     if (bAscending) {
1378     std::sort(itBegin, itEnd);
1379     } else {
1380     DescArrExprSorter<RealArrExprIter> sorter;
1381     std::sort(itBegin, itEnd, sorter);
1382     }
1383 schoenebeck 3221 }
1384 schoenebeck 3581
1385 schoenebeck 3221 return successResult();
1386     }
1387    
1388 schoenebeck 3573 ///////////////////////////////////////////////////////////////////////////
1389     // built-in script function: real_to_int() and int()
1390    
1391 schoenebeck 3581 StdUnit_t CoreVMFunction_real_to_int::returnUnitType(VMFnArgs* args) {
1392 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
1393 schoenebeck 3581 }
1394    
1395     bool CoreVMFunction_real_to_int::returnsFinal(VMFnArgs* args) {
1396 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
1397 schoenebeck 3581 }
1398    
1399 schoenebeck 3573 VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {
1400 schoenebeck 3581 VMRealExpr* realExpr = args->arg(0)->asReal();
1401     vmfloat f = realExpr->evalReal();
1402     return successResult({
1403     .value = vmint(f),
1404     .unitFactor = realExpr->unitFactor()
1405     });
1406 schoenebeck 3573 }
1407    
1408     ///////////////////////////////////////////////////////////////////////////
1409     // built-in script function: int_to_real() and real()
1410    
1411 schoenebeck 3581 StdUnit_t CoreVMFunction_int_to_real::returnUnitType(VMFnArgs* args) {
1412 schoenebeck 3582 return args->arg(0)->asNumber()->unitType();
1413 schoenebeck 3581 }
1414    
1415     bool CoreVMFunction_int_to_real::returnsFinal(VMFnArgs* args) {
1416 schoenebeck 3582 return args->arg(0)->asNumber()->isFinal();
1417 schoenebeck 3581 }
1418    
1419 schoenebeck 3573 VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {
1420 schoenebeck 3581 VMIntExpr* intExpr = args->arg(0)->asInt();
1421     vmint i = intExpr->evalInt();
1422     return successResult({
1423     .value = vmfloat(i),
1424     .unitFactor = intExpr->unitFactor()
1425     });
1426 schoenebeck 3573 }
1427    
1428 schoenebeck 3590 ///////////////////////////////////////////////////////////////////////////
1429     // built-in script function: round()
1430    
1431     StdUnit_t CoreVMFunction_round::returnUnitType(VMFnArgs* args) {
1432     return args->arg(0)->asNumber()->unitType();
1433     }
1434    
1435     bool CoreVMFunction_round::returnsFinal(VMFnArgs* args) {
1436     return args->arg(0)->asNumber()->isFinal();
1437     }
1438    
1439     VMFnResult* CoreVMFunction_round::exec(VMFnArgs* args) {
1440     VMRealExpr* realExpr = args->arg(0)->asReal();
1441     vmfloat f = realExpr->evalReal();
1442     if (sizeof(vmfloat) == sizeof(float))
1443     f = ::roundf(f);
1444     else
1445     f = ::round(f);
1446     return successResult({
1447     .value = f,
1448     .unitFactor = realExpr->unitFactor()
1449     });
1450     }
1451    
1452     ///////////////////////////////////////////////////////////////////////////
1453     // built-in script function: ceil()
1454    
1455     StdUnit_t CoreVMFunction_ceil::returnUnitType(VMFnArgs* args) {
1456     return args->arg(0)->asNumber()->unitType();
1457     }
1458    
1459     bool CoreVMFunction_ceil::returnsFinal(VMFnArgs* args) {
1460     return args->arg(0)->asNumber()->isFinal();
1461     }
1462    
1463     VMFnResult* CoreVMFunction_ceil::exec(VMFnArgs* args) {
1464     VMRealExpr* realExpr = args->arg(0)->asReal();
1465     vmfloat f = realExpr->evalReal();
1466     if (sizeof(vmfloat) == sizeof(float))
1467     f = ::ceilf(f);
1468     else
1469     f = ::ceil(f);
1470     return successResult({
1471     .value = f,
1472     .unitFactor = realExpr->unitFactor()
1473     });
1474     }
1475    
1476     ///////////////////////////////////////////////////////////////////////////
1477     // built-in script function: floor()
1478    
1479     StdUnit_t CoreVMFunction_floor::returnUnitType(VMFnArgs* args) {
1480     return args->arg(0)->asNumber()->unitType();
1481     }
1482    
1483     bool CoreVMFunction_floor::returnsFinal(VMFnArgs* args) {
1484     return args->arg(0)->asNumber()->isFinal();
1485     }
1486    
1487     VMFnResult* CoreVMFunction_floor::exec(VMFnArgs* args) {
1488     VMRealExpr* realExpr = args->arg(0)->asReal();
1489     vmfloat f = realExpr->evalReal();
1490     if (sizeof(vmfloat) == sizeof(float))
1491     f = ::floorf(f);
1492     else
1493     f = ::floor(f);
1494     return successResult({
1495     .value = f,
1496     .unitFactor = realExpr->unitFactor()
1497     });
1498     }
1499    
1500     ///////////////////////////////////////////////////////////////////////////
1501     // built-in script function: sqrt()
1502    
1503     StdUnit_t CoreVMFunction_sqrt::returnUnitType(VMFnArgs* args) {
1504     return args->arg(0)->asNumber()->unitType();
1505     }
1506    
1507     bool CoreVMFunction_sqrt::returnsFinal(VMFnArgs* args) {
1508     return args->arg(0)->asNumber()->isFinal();
1509     }
1510    
1511     VMFnResult* CoreVMFunction_sqrt::exec(VMFnArgs* args) {
1512     VMRealExpr* realExpr = args->arg(0)->asReal();
1513     vmfloat f = realExpr->evalReal();
1514     if (sizeof(vmfloat) == sizeof(float))
1515     f = ::sqrtf(f);
1516     else
1517     f = ::sqrt(f);
1518     return successResult({
1519     .value = f,
1520     .unitFactor = realExpr->unitFactor()
1521     });
1522     }
1523    
1524     ///////////////////////////////////////////////////////////////////////////
1525     // built-in script function: log()
1526    
1527     StdUnit_t CoreVMFunction_log::returnUnitType(VMFnArgs* args) {
1528     return args->arg(0)->asNumber()->unitType();
1529     }
1530    
1531     bool CoreVMFunction_log::returnsFinal(VMFnArgs* args) {
1532     return args->arg(0)->asNumber()->isFinal();
1533     }
1534    
1535     VMFnResult* CoreVMFunction_log::exec(VMFnArgs* args) {
1536     VMRealExpr* realExpr = args->arg(0)->asReal();
1537     vmfloat f = realExpr->evalReal();
1538     if (sizeof(vmfloat) == sizeof(float))
1539     f = ::logf(f);
1540     else
1541     f = ::log(f);
1542     return successResult({
1543     .value = f,
1544     .unitFactor = realExpr->unitFactor()
1545     });
1546     }
1547    
1548     ///////////////////////////////////////////////////////////////////////////
1549     // built-in script function: log2()
1550    
1551     StdUnit_t CoreVMFunction_log2::returnUnitType(VMFnArgs* args) {
1552     return args->arg(0)->asNumber()->unitType();
1553     }
1554    
1555     bool CoreVMFunction_log2::returnsFinal(VMFnArgs* args) {
1556     return args->arg(0)->asNumber()->isFinal();
1557     }
1558    
1559     VMFnResult* CoreVMFunction_log2::exec(VMFnArgs* args) {
1560     VMRealExpr* realExpr = args->arg(0)->asReal();
1561     vmfloat f = realExpr->evalReal();
1562     if (sizeof(vmfloat) == sizeof(float))
1563     f = ::log2f(f);
1564     else
1565     f = ::log2(f);
1566     return successResult({
1567     .value = f,
1568     .unitFactor = realExpr->unitFactor()
1569     });
1570     }
1571    
1572     ///////////////////////////////////////////////////////////////////////////
1573     // built-in script function: log10()
1574    
1575     StdUnit_t CoreVMFunction_log10::returnUnitType(VMFnArgs* args) {
1576     return args->arg(0)->asNumber()->unitType();
1577     }
1578    
1579     bool CoreVMFunction_log10::returnsFinal(VMFnArgs* args) {
1580     return args->arg(0)->asNumber()->isFinal();
1581     }
1582    
1583     VMFnResult* CoreVMFunction_log10::exec(VMFnArgs* args) {
1584     VMRealExpr* realExpr = args->arg(0)->asReal();
1585     vmfloat f = realExpr->evalReal();
1586     if (sizeof(vmfloat) == sizeof(float))
1587     f = ::log10f(f);
1588     else
1589     f = ::log10(f);
1590     return successResult({
1591     .value = f,
1592     .unitFactor = realExpr->unitFactor()
1593     });
1594     }
1595    
1596     ///////////////////////////////////////////////////////////////////////////
1597     // built-in script function: exp()
1598    
1599     StdUnit_t CoreVMFunction_exp::returnUnitType(VMFnArgs* args) {
1600     return args->arg(0)->asNumber()->unitType();
1601     }
1602    
1603     bool CoreVMFunction_exp::returnsFinal(VMFnArgs* args) {
1604     return args->arg(0)->asNumber()->isFinal();
1605     }
1606    
1607     VMFnResult* CoreVMFunction_exp::exec(VMFnArgs* args) {
1608     VMRealExpr* realExpr = args->arg(0)->asReal();
1609     vmfloat f = realExpr->evalReal();
1610     if (sizeof(vmfloat) == sizeof(float))
1611     f = ::expf(f);
1612     else
1613     f = ::exp(f);
1614     return successResult({
1615     .value = f,
1616     .unitFactor = realExpr->unitFactor()
1617     });
1618     }
1619    
1620     ///////////////////////////////////////////////////////////////////////////
1621     // built-in script function: pow()
1622    
1623     bool CoreVMFunction_pow::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
1624     if (iArg == 0)
1625     return true;
1626     else
1627     return type == VM_NO_UNIT;
1628     }
1629    
1630     bool CoreVMFunction_pow::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
1631     return iArg == 0;
1632     }
1633    
1634     StdUnit_t CoreVMFunction_pow::returnUnitType(VMFnArgs* args) {
1635     // pow() only allows unit for its 1st argument
1636     return args->arg(0)->asNumber()->unitType();
1637     }
1638    
1639     bool CoreVMFunction_pow::returnsFinal(VMFnArgs* args) {
1640     // pow() only allows 'final'ness for its 1st argument
1641     return args->arg(0)->asNumber()->isFinal();
1642     }
1643    
1644     VMFnResult* CoreVMFunction_pow::exec(VMFnArgs* args) {
1645     VMRealExpr* arg0 = args->arg(0)->asReal();
1646     VMRealExpr* arg1 = args->arg(1)->asReal();
1647     vmfloat a = arg0->evalReal();
1648     vmfloat b = arg1->evalReal();
1649     if (sizeof(vmfloat) == sizeof(float)) {
1650     return successResult({
1651     .value = ::powf(a,b),
1652     .unitFactor = arg0->unitFactor()
1653     });
1654     } else {
1655     return successResult({
1656 persson 3596 .value = static_cast<vmfloat>(::pow(a,b)),
1657 schoenebeck 3590 .unitFactor = arg0->unitFactor()
1658     });
1659     }
1660     }
1661    
1662     ///////////////////////////////////////////////////////////////////////////
1663     // built-in script function: sin()
1664    
1665     StdUnit_t CoreVMFunction_sin::returnUnitType(VMFnArgs* args) {
1666     return args->arg(0)->asNumber()->unitType();
1667     }
1668    
1669     bool CoreVMFunction_sin::returnsFinal(VMFnArgs* args) {
1670     return args->arg(0)->asNumber()->isFinal();
1671     }
1672    
1673     VMFnResult* CoreVMFunction_sin::exec(VMFnArgs* args) {
1674     VMRealExpr* realExpr = args->arg(0)->asReal();
1675     vmfloat f = realExpr->evalReal();
1676     if (sizeof(vmfloat) == sizeof(float))
1677     f = ::sinf(f);
1678     else
1679     f = ::sin(f);
1680     return successResult({
1681     .value = f,
1682     .unitFactor = realExpr->unitFactor()
1683     });
1684     }
1685    
1686     ///////////////////////////////////////////////////////////////////////////
1687     // built-in script function: cos()
1688    
1689     StdUnit_t CoreVMFunction_cos::returnUnitType(VMFnArgs* args) {
1690     return args->arg(0)->asNumber()->unitType();
1691     }
1692    
1693     bool CoreVMFunction_cos::returnsFinal(VMFnArgs* args) {
1694     return args->arg(0)->asNumber()->isFinal();
1695     }
1696    
1697     VMFnResult* CoreVMFunction_cos::exec(VMFnArgs* args) {
1698     VMRealExpr* realExpr = args->arg(0)->asReal();
1699     vmfloat f = realExpr->evalReal();
1700     if (sizeof(vmfloat) == sizeof(float))
1701     f = ::cosf(f);
1702     else
1703     f = ::cos(f);
1704     return successResult({
1705     .value = f,
1706     .unitFactor = realExpr->unitFactor()
1707     });
1708     }
1709    
1710     ///////////////////////////////////////////////////////////////////////////
1711     // built-in script function: tan()
1712    
1713     StdUnit_t CoreVMFunction_tan::returnUnitType(VMFnArgs* args) {
1714     return args->arg(0)->asNumber()->unitType();
1715     }
1716    
1717     bool CoreVMFunction_tan::returnsFinal(VMFnArgs* args) {
1718     return args->arg(0)->asNumber()->isFinal();
1719     }
1720    
1721     VMFnResult* CoreVMFunction_tan::exec(VMFnArgs* args) {
1722     VMRealExpr* realExpr = args->arg(0)->asReal();
1723     vmfloat f = realExpr->evalReal();
1724     if (sizeof(vmfloat) == sizeof(float))
1725     f = ::tanf(f);
1726     else
1727     f = ::tan(f);
1728     return successResult({
1729     .value = f,
1730     .unitFactor = realExpr->unitFactor()
1731     });
1732     }
1733    
1734     ///////////////////////////////////////////////////////////////////////////
1735     // built-in script function: asin()
1736    
1737     StdUnit_t CoreVMFunction_asin::returnUnitType(VMFnArgs* args) {
1738     return args->arg(0)->asNumber()->unitType();
1739     }
1740    
1741     bool CoreVMFunction_asin::returnsFinal(VMFnArgs* args) {
1742     return args->arg(0)->asNumber()->isFinal();
1743     }
1744    
1745     VMFnResult* CoreVMFunction_asin::exec(VMFnArgs* args) {
1746     VMRealExpr* realExpr = args->arg(0)->asReal();
1747     vmfloat f = realExpr->evalReal();
1748     if (sizeof(vmfloat) == sizeof(float))
1749     f = ::asinf(f);
1750     else
1751     f = ::asin(f);
1752     return successResult({
1753     .value = f,
1754     .unitFactor = realExpr->unitFactor()
1755     });
1756     }
1757    
1758     ///////////////////////////////////////////////////////////////////////////
1759     // built-in script function: acos()
1760    
1761     StdUnit_t CoreVMFunction_acos::returnUnitType(VMFnArgs* args) {
1762     return args->arg(0)->asNumber()->unitType();
1763     }
1764    
1765     bool CoreVMFunction_acos::returnsFinal(VMFnArgs* args) {
1766     return args->arg(0)->asNumber()->isFinal();
1767     }
1768    
1769     VMFnResult* CoreVMFunction_acos::exec(VMFnArgs* args) {
1770     VMRealExpr* realExpr = args->arg(0)->asReal();
1771     vmfloat f = realExpr->evalReal();
1772     if (sizeof(vmfloat) == sizeof(float))
1773     f = ::acosf(f);
1774     else
1775     f = ::acos(f);
1776     return successResult({
1777     .value = f,
1778     .unitFactor = realExpr->unitFactor()
1779     });
1780     }
1781    
1782     ///////////////////////////////////////////////////////////////////////////
1783     // built-in script function: atan()
1784    
1785     StdUnit_t CoreVMFunction_atan::returnUnitType(VMFnArgs* args) {
1786     return args->arg(0)->asNumber()->unitType();
1787     }
1788    
1789     bool CoreVMFunction_atan::returnsFinal(VMFnArgs* args) {
1790     return args->arg(0)->asNumber()->isFinal();
1791     }
1792    
1793     VMFnResult* CoreVMFunction_atan::exec(VMFnArgs* args) {
1794     VMRealExpr* realExpr = args->arg(0)->asReal();
1795     vmfloat f = realExpr->evalReal();
1796     if (sizeof(vmfloat) == sizeof(float))
1797     f = ::atanf(f);
1798     else
1799     f = ::atan(f);
1800     return successResult({
1801     .value = f,
1802     .unitFactor = realExpr->unitFactor()
1803     });
1804     }
1805    
1806 schoenebeck 2581 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC