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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 3076 by schoenebeck, Thu Jan 5 18:00:52 2017 UTC revision 3678 by schoenebeck, Fri Dec 27 22:46:08 2019 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2015 Christian Schoenebeck   * Copyright (c) 2014-2019 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 10  Line 10 
10  #include "CoreVMFunctions.h"  #include "CoreVMFunctions.h"
11    
12  #include <iostream>  #include <iostream>
13    #include <algorithm> // for std::sort()
14  #include <math.h>  #include <math.h>
15  #include <stdlib.h>  #include <stdlib.h>
16  #include "tree.h"  #include "tree.h"
17  #include "ScriptVM.h"  #include "ScriptVM.h"
18    #include "../common/RTMath.h"
19    
20  namespace LinuxSampler {  namespace LinuxSampler {
21    
22    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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
30  // class VMEmptyResultFunction  // class VMEmptyResultFunction
31    
# Line 33  VMFnResult* VMEmptyResultFunction::succe Line 42  VMFnResult* VMEmptyResultFunction::succe
42  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
43  // class VMIntResultFunction  // class VMIntResultFunction
44    
45  VMFnResult* VMIntResultFunction::errorResult(int i) {  VMFnResult* VMIntResultFunction::errorResult(vmint i) {
46      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
47      result.value = i;      result.value = i;
48        result.unitPrefixFactor = VM_NO_FACTOR;
49      return &result;      return &result;
50  }  }
51    
52  VMFnResult* VMIntResultFunction::successResult(int i) {  VMFnResult* VMIntResultFunction::successResult(vmint i) {
53      result.flags = STMT_SUCCESS;      result.flags = STMT_SUCCESS;
54      result.value = i;      result.value = i;
55        result.unitPrefixFactor = VM_NO_FACTOR;
56        return &result;
57    }
58    
59    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    ///////////////////////////////////////////////////////////////////////////
74    // 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        result.unitPrefixFactor = VM_NO_FACTOR;
80        return &result;
81    }
82    
83    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    VMFnResult* VMRealResultFunction::successResult(vmfloat f) {
91        result.flags = STMT_SUCCESS;
92        result.value = f;
93        result.unitPrefixFactor = VM_NO_FACTOR;
94        return &result;
95    }
96    
97    VMFnResult* VMRealResultFunction::successResult(VMRealFnResDef res) {
98        result.flags = STMT_SUCCESS;
99        result.value = res.value;
100        result.unitPrefixFactor = res.unitFactor;
101      return &result;      return &result;
102  }  }
103    
# Line 61  VMFnResult* VMStringResultFunction::succ Line 117  VMFnResult* VMStringResultFunction::succ
117  }  }
118    
119  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
120    // class VMNumberResultFunction
121    
122    VMFnResult* VMNumberResultFunction::errorResult(vmint i) {
123        intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
124        intResult.value = i;
125        intResult.unitPrefixFactor = VM_NO_FACTOR;
126        return &intResult;
127    }
128    
129    VMFnResult* VMNumberResultFunction::errorResult(vmfloat f) {
130        realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
131        realResult.value = f;
132        realResult.unitPrefixFactor = VM_NO_FACTOR;
133        return &realResult;
134    }
135    
136    VMFnResult* VMNumberResultFunction::successResult(vmint i) {
137        intResult.flags = STMT_SUCCESS;
138        intResult.value = i;
139        intResult.unitPrefixFactor = VM_NO_FACTOR;
140        return &intResult;
141    }
142    
143    VMFnResult* VMNumberResultFunction::successResult(vmfloat f) {
144        realResult.flags = STMT_SUCCESS;
145        realResult.value = f;
146        realResult.unitPrefixFactor = VM_NO_FACTOR;
147        return &realResult;
148    }
149    
150    VMFnResult* VMNumberResultFunction::errorIntResult(VMIntFnResDef res) {
151        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    VMFnResult* VMNumberResultFunction::errorRealResult(VMRealFnResDef res) {
158        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    VMFnResult* VMNumberResultFunction::successIntResult(VMIntFnResDef res) {
165        intResult.flags = STMT_SUCCESS;
166        intResult.value = res.value;
167        intResult.unitPrefixFactor = res.unitFactor;
168        return &intResult;
169    }
170    
171    VMFnResult* VMNumberResultFunction::successRealResult(VMRealFnResDef res) {
172        realResult.flags = STMT_SUCCESS;
173        realResult.value = res.value;
174        realResult.unitPrefixFactor = res.unitFactor;
175        return &realResult;
176    }
177    
178    ///////////////////////////////////////////////////////////////////////////
179  // built-in script function:  message()  // built-in script function:  message()
180    
181  bool CoreVMFunction_message::acceptsArgType(int iArg, ExprType_t type) const {  bool CoreVMFunction_message::acceptsArgType(vmint iArg, ExprType_t type) const {
182      return type == INT_EXPR || type == STRING_EXPR;      return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
183  }  }
184    
185  VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_message::exec(VMFnArgs* args) {
186      if (!args->argsCount()) return errorResult();      if (!args->argsCount()) return errorResult();
187    
188        uint64_t usecs = RTMath::unsafeMicroSeconds(RTMath::real_clock);
189    
190      VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(args->arg(0));      VMStringExpr* strExpr = dynamic_cast<VMStringExpr*>(args->arg(0));
191      if (strExpr) {      if (strExpr) {
192          std::cout << "[ScriptVM] " << strExpr->evalStr() << "\n";          printf("[ScriptVM %.3f] %s\n", usecs/1000000.f, strExpr->evalStr().c_str());
193            return successResult();
194        }
195    
196        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();          return successResult();
200      }      }
201    
202      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
203      if (intExpr) {      if (intExpr) {
204          std::cout << "[ScriptVM] " << intExpr->evalInt() << "\n";          printf("[ScriptVM %.3f] %lld\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
205          return successResult();          return successResult();
206      }      }
207    
# Line 88  VMFnResult* CoreVMFunction_message::exec Line 211  VMFnResult* CoreVMFunction_message::exec
211  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
212  // built-in script function:  exit()  // built-in script function:  exit()
213    
214    vmint CoreVMFunction_exit::maxAllowedArgs() const {
215        return (vm->isExitResultEnabled()) ? 1 : 0;
216    }
217    
218    bool CoreVMFunction_exit::acceptsArgType(vmint iArg, ExprType_t type) const {
219        if (!vm->isExitResultEnabled()) return false;
220        return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
221    }
222    
223    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  VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
238      this->result.flags = STMT_ABORT_SIGNALLED;      this->result.flags = STMT_ABORT_SIGNALLED;
239        if (vm->isExitResultEnabled() && args->argsCount()) {
240            ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
241            switch (args->arg(0)->exprType()) {
242                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                    ctx->exitRes.value = &ctx->exitRes.intLiteral;
251                    break;
252                }
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                    ctx->exitRes.value = &ctx->exitRes.realLiteral;
262                    break;
263                }
264                case STRING_EXPR:
265                    ctx->exitRes.stringLiteral = StringLiteral(
266                        args->arg(0)->asString()->evalStr()
267                    );
268                    ctx->exitRes.value = &ctx->exitRes.stringLiteral;
269                    break;
270                default:
271                    ; // noop - just to shut up the compiler
272            }
273        }
274      return &result;      return &result;
275  }  }
276    
277  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
278  // built-in script function:  wait()  // built-in script function:  wait()
279    
280    bool CoreVMFunction_wait::acceptsArgType(vmint iArg, ExprType_t type) const {
281        return type == INT_EXPR || type == REAL_EXPR;
282    }
283    
284    bool CoreVMFunction_wait::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
285        return type == VM_NO_UNIT || type == VM_SECOND;
286    }
287    
288    bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
289        return type == VM_SECOND; // only allow metric prefix(es) if 'seconds' is used as unit type
290    }
291    
292  VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_wait::exec(VMFnArgs* args) {
293      ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());      ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
294      VMIntExpr* expr = dynamic_cast<VMIntExpr*>(args->arg(0));      VMNumberExpr* expr = args->arg(0)->asNumber();
295      int us = expr->evalInt();      StdUnit_t unit = expr->unitType();
296        vmint us = (unit) ? expr->evalCastInt(VM_MICRO) : expr->evalCastInt();
297      if (us < 0) {      if (us < 0) {
298          wrnMsg("wait(): argument may not be negative! Aborting script!");          wrnMsg("wait(): argument may not be negative! Aborting script!");
299          this->result.flags = STMT_ABORT_SIGNALLED;          this->result.flags = STMT_ABORT_SIGNALLED;
# Line 116  VMFnResult* CoreVMFunction_wait::exec(VM Line 310  VMFnResult* CoreVMFunction_wait::exec(VM
310  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
311  // built-in script function:  abs()  // built-in script function:  abs()
312    
313  bool CoreVMFunction_abs::acceptsArgType(int iArg, ExprType_t type) const {  ExprType_t CoreVMFunction_abs::returnType(VMFnArgs* args) {
314      return type == INT_EXPR;      return args->arg(0)->exprType();
315    }
316    
317    StdUnit_t CoreVMFunction_abs::returnUnitType(VMFnArgs* args) {
318        return args->arg(0)->asNumber()->unitType();
319    }
320    
321    bool CoreVMFunction_abs::returnsFinal(VMFnArgs* args) {
322        return args->arg(0)->asNumber()->isFinal();
323    }
324    
325    bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
326        return type == INT_EXPR || type == REAL_EXPR;
327  }  }
328    
329  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
330      return successResult( ::abs(args->arg(0)->asInt()->evalInt()) );      VMExpr* arg = args->arg(0);
331        if (arg->exprType() == REAL_EXPR) {
332            VMRealExpr* expr = arg->asReal();
333            return successRealResult({
334                .value = static_cast<vmfloat>(::fabs(expr->evalReal())),
335                .unitFactor = expr->unitFactor()
336            });
337        } else {
338            VMIntExpr* expr = arg->asInt();
339            return successIntResult({
340                .value = std::abs(expr->evalInt()),
341                .unitFactor = expr->unitFactor()
342            });
343        }
344  }  }
345    
346  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
347  // built-in script function:  random()  // built-in script function:  random()
348    
349  bool CoreVMFunction_random::acceptsArgType(int iArg, ExprType_t type) const {  ExprType_t CoreVMFunction_random::returnType(VMFnArgs* args) {
350      return type == INT_EXPR;      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        return args->arg(0)->asNumber()->unitType();
358    }
359    
360    bool CoreVMFunction_random::returnsFinal(VMFnArgs* args) {
361        return args->arg(0)->asNumber()->isFinal() ||
362               args->arg(1)->asNumber()->isFinal();
363    }
364    
365    bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
366        return type == INT_EXPR || type == REAL_EXPR;
367    }
368    
369    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        if (args->arg(0)->asNumber()->unitType() !=
378            args->arg(1)->asNumber()->unitType())
379        {
380            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
381            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
382            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
383            return;
384        }
385        if (args->arg(0)->asNumber()->isFinal() !=
386            args->arg(1)->asNumber()->isFinal())
387        {
388            String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
389            String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
390            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
391        }
392  }  }
393    
394  VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_random::exec(VMFnArgs* args) {
     int iMin = args->arg(0)->asInt()->evalInt();  
     int iMax = args->arg(1)->asInt()->evalInt();  
395      float f = float(::rand()) / float(RAND_MAX);      float f = float(::rand()) / float(RAND_MAX);
396      return successResult(  
397          iMin + roundf( f * float(iMax - iMin) )      VMNumberExpr* arg0 = args->arg(0)->asNumber();
398      );      VMNumberExpr* arg1 = args->arg(1)->asNumber();
399    
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  }  }
444    
445  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
446  // built-in script function:  num_elements()  // built-in script function:  num_elements()
447    
448  bool CoreVMFunction_num_elements::acceptsArgType(int iArg, ExprType_t type) const {  bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
449      return type == INT_ARR_EXPR;      return isArray(type);
450  }  }
451    
452  VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
453      return successResult( args->arg(0)->asIntArray()->arraySize() );      return successResult( args->arg(0)->asArray()->arraySize() );
454  }  }
455    
456  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
457  // built-in script function:  inc()  // built-in script function:  inc()
458    
459    StdUnit_t CoreVMFunction_inc::returnUnitType(VMFnArgs* args) {
460        return args->arg(0)->asNumber()->unitType();
461    }
462    
463    bool CoreVMFunction_inc::returnsFinal(VMFnArgs* args) {
464        return args->arg(0)->asNumber()->isFinal();
465    }
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        if (args->arg(0)->asNumber()->unitType()) {
476            String unitType = unitTypeStr(args->arg(0)->asNumber()->unitType());
477            wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be incremented by one.");
478        }
479    }
480    
481  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
482      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
483      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
484      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
485      if (!in || !out) successResult(0);      vmint i = in->evalInt() + 1;
486      int i = in->evalInt() + 1;      IntLiteral tmp({
487      IntLiteral tmp(i);          .value = i,
488            .unitFactor = in->unitFactor()
489        });
490      out->assignExpr(&tmp);      out->assignExpr(&tmp);
491      return successResult(i);      return successResult({
492            .value = i,
493            .unitFactor = in->unitFactor()
494        });
495  }  }
496    
497  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
498  // built-in script function:  dec()  // built-in script function:  dec()
499    
500    StdUnit_t CoreVMFunction_dec::returnUnitType(VMFnArgs* args) {
501        return args->arg(0)->asNumber()->unitType();
502    }
503    
504    bool CoreVMFunction_dec::returnsFinal(VMFnArgs* args) {
505        return args->arg(0)->asNumber()->isFinal();
506    }
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        if (args->arg(0)->asNumber()->unitType()) {
517            String unitType = unitTypeStr(args->arg(0)->asNumber()->unitType());
518            wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be decremented by one.");
519        }
520    }
521    
522  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
523      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
524      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
525      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
526      if (!in || !out) successResult(0);      vmint i = in->evalInt() - 1;
527      int i = in->evalInt() - 1;      IntLiteral tmp({
528      IntLiteral tmp(i);          .value = i,
529            .unitFactor = in->unitFactor()
530        });
531      out->assignExpr(&tmp);      out->assignExpr(&tmp);
532      return successResult(i);      return successResult({
533            .value = i,
534            .unitFactor = in->unitFactor()
535        });
536  }  }
537    
538  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
539  // built-in script function:  in_range()  // built-in script function:  in_range()
540    
541  VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {  bool CoreVMFunction_in_range::acceptsArgType(vmint iArg, ExprType_t type) const {
542      int i  = args->arg(0)->asInt()->evalInt();      return type == INT_EXPR || type == REAL_EXPR;
543      int lo = args->arg(1)->asInt()->evalInt();  }
544      int hi = args->arg(2)->asInt()->evalInt();  
545      if (lo > hi) { // swap lo and hi  void CoreVMFunction_in_range::checkArgs(VMFnArgs* args,
546          int tmp = lo;                                          std::function<void(String)> err,
547          lo = hi;                                          std::function<void(String)> wrn)
548          hi = tmp;  {
549        // super class checks
550        Super::checkArgs(args, err, wrn);
551    
552        // own checks ...
553        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        {
558            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            err("Arguments must all have same unit, however argument 1 is " + a +
562                ", argument 2 is " + b + ", argument 3 is " + c + ".");
563            return;
564        }
565        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      return successResult(i >= lo && i <= hi);  }
576    
577    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        VMNumberExpr* argNeedle = args->arg(0)->asNumber();
586        VMNumberExpr* argLo = args->arg(1)->asNumber();
587        VMNumberExpr* argHi = args->arg(2)->asNumber();
588    
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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
603  // built-in script function:  sh_left()  // built-in script function:  sh_left()
604    
605    bool CoreVMFunction_sh_left::returnsFinal(VMFnArgs* args) {
606        return args->arg(0)->asNumber()->isFinal();
607    }
608    
609  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
610      int i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
611      int n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
612      return successResult(i << n);      return successResult(i << n);
613  }  }
614    
615  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
616  // built-in script function:  sh_right()  // built-in script function:  sh_right()
617    
618    bool CoreVMFunction_sh_right::returnsFinal(VMFnArgs* args) {
619        return args->arg(0)->asNumber()->isFinal();
620    }
621    
622  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
623      int i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
624      int n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
625      return successResult(i >> n);      return successResult(i >> n);
626  }  }
627    
628  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
629    // 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  // built-in script function:  min()  // built-in script function:  min()
646    
647    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    StdUnit_t CoreVMFunction_min::returnUnitType(VMFnArgs* args) {
653        return args->arg(0)->asNumber()->unitType();
654    }
655    
656    bool CoreVMFunction_min::returnsFinal(VMFnArgs* args) {
657        return args->arg(0)->asNumber()->isFinal() ||
658               args->arg(1)->asNumber()->isFinal();
659    }
660    
661    bool CoreVMFunction_min::acceptsArgType(vmint iArg, ExprType_t type) const {
662        return type == INT_EXPR || type == REAL_EXPR;
663    }
664    
665    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        if (args->arg(0)->asNumber()->unitType() !=
674            args->arg(1)->asNumber()->unitType())
675        {
676            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
677            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
678            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        if (args->arg(0)->asNumber()->isFinal() !=
689            args->arg(1)->asNumber()->isFinal())
690        {
691            String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
692            String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
693            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
694        }
695    }
696    
697  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
698      int l = args->arg(0)->asInt()->evalInt();      VMNumberExpr* lhs = args->arg(0)->asNumber();
699      int r = args->arg(1)->asInt()->evalInt();      VMNumberExpr* rhs = args->arg(1)->asNumber();
700      return successResult(l < r ? l : r);      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        } else {
728            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        }
737  }  }
738    
739  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
740  // built-in script function:  max()  // built-in script function:  max()
741    
742    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    StdUnit_t CoreVMFunction_max::returnUnitType(VMFnArgs* args) {
748        return args->arg(0)->asNumber()->unitType();
749    }
750    
751    bool CoreVMFunction_max::returnsFinal(VMFnArgs* args) {
752        return args->arg(0)->asNumber()->isFinal() ||
753               args->arg(1)->asNumber()->isFinal();
754    }
755    
756    bool CoreVMFunction_max::acceptsArgType(vmint iArg, ExprType_t type) const {
757        return type == INT_EXPR || type == REAL_EXPR;
758    }
759    
760    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        if (args->arg(0)->asNumber()->unitType() !=
769            args->arg(1)->asNumber()->unitType())
770        {
771            String a = unitTypeStr(args->arg(0)->asNumber()->unitType());
772            String b = unitTypeStr(args->arg(1)->asNumber()->unitType());
773            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        if (args->arg(0)->asNumber()->isFinal() !=
784            args->arg(1)->asNumber()->isFinal())
785        {
786            String a = args->arg(0)->asNumber()->isFinal() ? "'final'" : "not 'final'";
787            String b = args->arg(1)->asNumber()->isFinal() ? "'final'" : "not 'final'";
788            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
789        }
790    }
791    
792  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
793      int l = args->arg(0)->asInt()->evalInt();      VMNumberExpr* lhs = args->arg(0)->asNumber();
794      int r = args->arg(1)->asInt()->evalInt();      VMNumberExpr* rhs = args->arg(1)->asNumber();
795      return successResult(l > r ? l : r);      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        } else {
823            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        }
832    }
833    
834    ///////////////////////////////////////////////////////////////////////////
835    // built-in script function:  array_equal()
836    
837    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    VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
863        VMArrayExpr* l = args->arg(0)->asArray();
864        VMArrayExpr* r = args->arg(1)->asArray();
865        if (l->arraySize() != r->arraySize()) {
866            //wrnMsg("array_equal(): the two arrays differ in size");
867            return successResult(0); // false
868        }
869        const vmint n = l->arraySize();
870        // 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        return successResult(1); // true
926    }
927    
928    ///////////////////////////////////////////////////////////////////////////
929    // built-in script function:  search()
930    
931    bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
932        if (iArg == 0)
933            return isArray(type);
934        else
935            return type == INT_EXPR || type == REAL_EXPR;
936    }
937    
938    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    VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
967        VMArrayExpr* a = args->arg(0)->asArray();
968        const vmint n = a->arraySize();
969        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        return successResult(-1); // not found
985    }
986    
987    ///////////////////////////////////////////////////////////////////////////
988    // built-in script function:  sort()
989    
990    bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
991        if (iArg == 0)
992            return isArray(type);
993        else
994            return type == INT_EXPR;
995    }
996    
997    // 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    // (e.g. sorting) jobs, that is they expect containers to have 'localizeable'
1002    // 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    struct ArrElemPOD {
1029        T_array* m_array;
1030        vmint m_index;
1031    };
1032    
1033    // 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    
1039        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    public:
1057        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    
1059        inline ArrElemRef(T_array* a, vmint index) {
1060            this->m_array = a;
1061            this->m_index = index;
1062        }
1063        inline ArrElemRef(const ArrElemRef& ref) {
1064            this->m_array = ref.m_array;
1065            this->m_index = ref.m_index;
1066        }
1067        inline ArrElemRef& operator=(const ArrElemRef& e) {
1068            setPrimValue(e.getPrimValue());
1069            setUnitFactor(e.getUnitFactor());
1070            return *this;
1071        }
1072        inline ArrElemRef& operator=(ScalarNmbrVal value) {
1073            setPrimValue(value.primValue);
1074            setUnitFactor(value.unitFactor);
1075            return *this;
1076        }
1077        inline bool operator==(const ArrElemRef& e) const {
1078            return getProdValue() == e.getProdValue();
1079        }
1080        inline bool operator!=(const ArrElemRef& e) const {
1081            return !(operator==(e));
1082        }
1083        inline bool operator<(const ArrElemRef& e) const {
1084            return getProdValue() < e.getProdValue();
1085        }
1086        inline bool operator>(const ArrElemRef& e) const {
1087            return getProdValue() > e.getProdValue();
1088        }
1089        inline bool operator<=(const ArrElemRef& e) const {
1090            return getProdValue() <= e.getProdValue();
1091        }
1092        inline bool operator>=(const ArrElemRef& e) const {
1093            return getProdValue() >= e.getProdValue();
1094        }
1095        inline bool operator==(const ScalarNmbrVal& s) const {
1096            return getProdValue() == s.getProdValue();
1097        }
1098        inline bool operator!=(const ScalarNmbrVal& s) const {
1099            return !(operator==(s));
1100        }
1101        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    protected:
1120        inline T_value getPrimValue() const {
1121            return T_accessor::getPrimaryValue( this->m_array, this->m_index );
1122        }
1123        inline void setPrimValue(T_value value) {
1124            T_accessor::setPrimaryValue( this->m_array, this->m_index, value );
1125        }
1126        inline vmfloat getUnitFactor() const {
1127            return this->m_array->unitFactorOfElement(this->m_index);
1128        }
1129        inline void setUnitFactor(vmfloat factor) {
1130            this->m_array->assignElementUnitFactor(this->m_index, factor);
1131        }
1132        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        }
1138    
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    };
1143    
1144    // 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    public:
1148        typedef std::random_access_iterator_tag iterator_category;
1149        typedef ssize_t difference_type;
1150        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        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    
1155        ArrExprIter(T_array* a, vmint index) {
1156            this->m_array = a;
1157            this->m_index = index;
1158        }
1159        ArrExprIter(const ArrElemRef& ref) {
1160            this->m_array = ref.m_array;
1161            this->m_index = ref.m_index;
1162        }
1163        inline ArrElemRef operator*() {
1164            return ArrElemRef(this->m_array, this->m_index);
1165        }
1166        inline ArrExprIter& operator++() { // prefix increment
1167            ++(this->m_index);
1168            return *this;
1169        }
1170        inline ArrExprIter& operator--() { // prefix decrement
1171            --(this->m_index);
1172            return *this;
1173        }
1174        inline ArrExprIter operator++(int) { // postfix increment
1175            ArrExprIter it = *this;
1176            ++(this->m_index);
1177            return it;
1178        }
1179        inline ArrExprIter operator--(int) { // postfix decrement
1180            ArrExprIter it = *this;
1181            --(this->m_index);
1182            return it;
1183        }
1184        inline ArrExprIter& operator+=(difference_type d) {
1185            this->m_index += d;
1186            return *this;
1187        }
1188        inline ArrExprIter& operator-=(difference_type d) {
1189            this->m_index -= d;
1190            return *this;
1191        }
1192        inline bool operator==(const ArrExprIter& other) const {
1193            return this->m_index == other.m_index;
1194        }
1195        inline bool operator!=(const ArrExprIter& other) const {
1196            return this->m_index != other.m_index;
1197        }
1198        inline bool operator<(const ArrExprIter& other) const {
1199            return this->m_index < other.m_index;
1200        }
1201        inline bool operator>(const ArrExprIter& other) const {
1202            return this->m_index > other.m_index;
1203        }
1204        inline bool operator<=(const ArrExprIter& other) const {
1205            return this->m_index <= other.m_index;
1206        }
1207        inline bool operator>=(const ArrExprIter& other) const {
1208            return this->m_index >= other.m_index;
1209        }
1210        inline difference_type operator+(const ArrExprIter& other) const {
1211            return this->m_index + other.m_index;
1212        }
1213        inline difference_type operator-(const ArrExprIter& other) const {
1214            return this->m_index - other.m_index;
1215        }
1216        inline ArrExprIter operator-(difference_type d) const {
1217            return ArrExprIter(this->m_array, this->m_index - d);
1218        }
1219        inline ArrExprIter operator+(difference_type d) const {
1220            return ArrExprIter(this->m_array, this->m_index + d);
1221        }
1222        inline ArrExprIter operator*(difference_type factor) const {
1223            return ArrExprIter(this->m_array, this->m_index * factor);
1224        }
1225    };
1226    
1227    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    inline void swap(IntArrExprIter::ArrElemRef a,
1232                     IntArrExprIter::ArrElemRef b)
1233    {
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    inline void swap(RealArrExprIter::ArrElemRef a,
1246                     RealArrExprIter::ArrElemRef b)
1247    {
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    struct DescArrExprSorter {
1261        inline bool operator()(const typename T::value_type a, const typename T::value_type b) const {
1262            return a > b;
1263        }
1264    };
1265    
1266    VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
1267        const bool bAscending =
1268            (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
1269    
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        } else {
1282            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        }
1293    
1294        return successResult();
1295    }
1296    
1297    ///////////////////////////////////////////////////////////////////////////
1298    // built-in script function:  real_to_int()  and  int()
1299    
1300    StdUnit_t CoreVMFunction_real_to_int::returnUnitType(VMFnArgs* args) {
1301        return args->arg(0)->asNumber()->unitType();
1302    }
1303    
1304    bool CoreVMFunction_real_to_int::returnsFinal(VMFnArgs* args) {
1305        return args->arg(0)->asNumber()->isFinal();
1306    }
1307    
1308    VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {
1309        VMRealExpr* realExpr = args->arg(0)->asReal();
1310        vmfloat f = realExpr->evalReal();
1311        return successResult({
1312            .value = vmint(f),
1313            .unitFactor = realExpr->unitFactor()
1314        });
1315    }
1316    
1317    ///////////////////////////////////////////////////////////////////////////
1318    // built-in script function:  int_to_real()  and  real()
1319    
1320    StdUnit_t CoreVMFunction_int_to_real::returnUnitType(VMFnArgs* args) {
1321        return args->arg(0)->asNumber()->unitType();
1322    }
1323    
1324    bool CoreVMFunction_int_to_real::returnsFinal(VMFnArgs* args) {
1325        return args->arg(0)->asNumber()->isFinal();
1326    }
1327    
1328    VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {
1329        VMIntExpr* intExpr = args->arg(0)->asInt();
1330        vmint i = intExpr->evalInt();
1331        return successResult({
1332            .value = vmfloat(i),
1333            .unitFactor = intExpr->unitFactor()
1334        });
1335    }
1336    
1337    ///////////////////////////////////////////////////////////////////////////
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                .value = static_cast<vmfloat>(::pow(a,b)),
1566                .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  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.3076  
changed lines
  Added in v.3678

  ViewVC Help
Powered by ViewVC