/[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 3678 - (hide annotations) (download)
Fri Dec 27 22:46:08 2019 UTC (4 years, 4 months ago) by schoenebeck
File size: 59368 byte(s)
* NKSP: Added built-in script functions "msb()" and "lsb()".

* Bumped version (2.1.1.svn26).

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

  ViewVC Help
Powered by ViewVC