/[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 3744 - (hide annotations) (download)
Sat Feb 15 11:50:02 2020 UTC (4 years, 3 months ago) by schoenebeck
File size: 60470 byte(s)
* NKSP: Fixed intermediate function result values never having reflected
  any standard measuring unit type.

* Tests: Guard this fixed NKSP issue by test cases.

* Bumped version (2.1.1.svn49).

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

  ViewVC Help
Powered by ViewVC