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

Legend:
Removed from v.2620  
changed lines
  Added in v.3747

  ViewVC Help
Powered by ViewVC