/[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 3577 by schoenebeck, Wed Aug 28 15:23:23 2019 UTC revision 3747 by schoenebeck, Sun Feb 16 11:31:46 2020 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014-2019 Christian Schoenebeck   * Copyright (c) 2014-2020 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 19  Line 19 
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  // 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  // 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) {  VMFnResult* VMIntResultFunction::errorResult(vmint i) {
81      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
82      result.value = i;      result->value = i;
83      return &result;      result->unitPrefixFactor = VM_NO_FACTOR;
84        result->unitBaseType = VM_NO_UNIT;
85        return result;
86  }  }
87    
88  VMFnResult* VMIntResultFunction::successResult(vmint i) {  VMFnResult* VMIntResultFunction::successResult(vmint i) {
89      result.flags = STMT_SUCCESS;      result->flags = STMT_SUCCESS;
90      result.value = i;      result->value = i;
91      return &result;      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  // 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) {  VMFnResult* VMRealResultFunction::errorResult(vmfloat f) {
124      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      result->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
125      result.value = f;      result->value = f;
126      return &result;      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) {  VMFnResult* VMRealResultFunction::successResult(vmfloat f) {
140      result.flags = STMT_SUCCESS;      result->flags = STMT_SUCCESS;
141      result.value = f;      result->value = f;
142      return &result;      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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
156  // class VMStringResultFunction  // class VMStringResultFunction
157    
158    void VMStringResultFunction::bindResult(VMFnResult* res) {
159        result = dynamic_cast<VMStringResult*>(res);
160    }
161    
162    VMFnResult* VMStringResultFunction::boundResult() const {
163        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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
179  // class VMScalarNumberResultFunction  // 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* VMScalarNumberResultFunction::errorResult(vmint i) {  VMFnResult* VMNumberResultFunction::errorResult(vmint i) {
206      intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      intResult->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
207      intResult.value = i;      intResult->value = i;
208      return &intResult;      intResult->unitPrefixFactor = VM_NO_FACTOR;
209        intResult->unitBaseType = VM_NO_UNIT;
210        return intResult;
211  }  }
212    
213  VMFnResult* VMScalarNumberResultFunction::errorResult(vmfloat f) {  VMFnResult* VMNumberResultFunction::errorResult(vmfloat f) {
214      realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      realResult->flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
215      realResult.value = f;      realResult->value = f;
216      return &realResult;      realResult->unitPrefixFactor = VM_NO_FACTOR;
217        intResult->unitBaseType = VM_NO_UNIT;
218        return realResult;
219  }  }
220    
221  VMFnResult* VMScalarNumberResultFunction::successResult(vmint i) {  VMFnResult* VMNumberResultFunction::successResult(vmint i) {
222      intResult.flags = STMT_SUCCESS;      intResult->flags = STMT_SUCCESS;
223      intResult.value = i;      intResult->value = i;
224      return &intResult;      intResult->unitPrefixFactor = VM_NO_FACTOR;
225        intResult->unitBaseType = VM_NO_UNIT;
226        return intResult;
227  }  }
228    
229  VMFnResult* VMScalarNumberResultFunction::successResult(vmfloat f) {  VMFnResult* VMNumberResultFunction::successResult(vmfloat f) {
230      realResult.flags = STMT_SUCCESS;      realResult->flags = STMT_SUCCESS;
231      realResult.value = f;      realResult->value = f;
232      return &realResult;      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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
# Line 130  VMFnResult* CoreVMFunction_message::exec Line 292  VMFnResult* CoreVMFunction_message::exec
292    
293      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));      VMIntExpr* intExpr = dynamic_cast<VMIntExpr*>(args->arg(0));
294      if (intExpr) {      if (intExpr) {
295          printf("[ScriptVM %.3f] %lld\n", usecs/1000000.f, (int64_t)intExpr->evalInt());          printf("[ScriptVM %.3f] %" PRId64 "\n", usecs/1000000.f, (int64_t)intExpr->evalInt());
296          return successResult();          return successResult();
297      }      }
298    
# Line 149  bool CoreVMFunction_exit::acceptsArgType Line 311  bool CoreVMFunction_exit::acceptsArgType
311      return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;      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      if (vm->isExitResultEnabled() && args->argsCount()) {      if (vm->isExitResultEnabled() && args->argsCount()) {
331          ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());          ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
332          switch (args->arg(0)->exprType()) {          switch (args->arg(0)->exprType()) {
333              case INT_EXPR:              case INT_EXPR: {
334                  ctx->exitRes.intLiteral.value = args->arg(0)->asInt()->evalInt();                  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;                  ctx->exitRes.value = &ctx->exitRes.intLiteral;
342                  break;                  break;
343              case REAL_EXPR:              }
344                  ctx->exitRes.realLiteral.value = args->arg(0)->asReal()->evalReal();              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;                  ctx->exitRes.value = &ctx->exitRes.realLiteral;
353                  break;                  break;
354                }
355              case STRING_EXPR:              case STRING_EXPR:
356                  ctx->exitRes.stringLiteral.value = args->arg(0)->asString()->evalStr();                  ctx->exitRes.stringLiteral = StringLiteral(
357                        args->arg(0)->asString()->evalStr()
358                    );
359                  ctx->exitRes.value = &ctx->exitRes.stringLiteral;                  ctx->exitRes.value = &ctx->exitRes.stringLiteral;
360                  break;                  break;
361              default:              default:
362                  ; // noop - just to shut up the compiler                  ; // noop - just to shut up the compiler
363          }          }
364      }      }
365      return &result;      return result;
366  }  }
367    
368  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
369  // built-in script function:  wait()  // 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 {  bool CoreVMFunction_wait::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
376      if (iArg == 0)      return type == VM_NO_UNIT || type == VM_SECOND;
         return type == VM_NO_UNIT || type == VM_SECOND;  
     else  
         return type == VM_NO_UNIT;  
377  }  }
378    
379  bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {  bool CoreVMFunction_wait::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
380      return iArg == 0 && type == VM_SECOND;      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      StdUnit_t unit = expr->unitType();      StdUnit_t unit = expr->unitType();
387      vmint us = (unit) ? expr->evalInt(VM_MICRO) : expr->evalInt();      vmint us = (unit) ? expr->evalCastInt(VM_MICRO) : expr->evalCastInt();
388      if (us < 0) {      if (us < 0) {
389          wrnMsg("wait(): argument may not be negative! Aborting script!");          wrnMsg("wait(): argument may not be negative! Aborting handler!");
390          this->result.flags = STMT_ABORT_SIGNALLED;          this->result->flags = STMT_ABORT_SIGNALLED;
391      } else if (us == 0) {      } else if (us == 0) {
392          wrnMsg("wait(): argument may not be zero! Aborting script!");          wrnMsg("wait(): argument may not be zero! Aborting handler!");
393          this->result.flags = STMT_ABORT_SIGNALLED;          this->result->flags = STMT_ABORT_SIGNALLED;
394      } else {      } else {
395          ctx->suspendMicroseconds = us;          ctx->suspendMicroseconds = us;
396          this->result.flags = STMT_SUSPEND_SIGNALLED;          this->result->flags = STMT_SUSPEND_SIGNALLED;
397      }      }
398      return &result;      return result;
399  }  }
400    
401  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
# Line 212  ExprType_t CoreVMFunction_abs::returnTyp Line 405  ExprType_t CoreVMFunction_abs::returnTyp
405      return args->arg(0)->exprType();      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 {  bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
417      return type == INT_EXPR || type == REAL_EXPR;      return type == INT_EXPR || type == REAL_EXPR;
418  }  }
419    
420  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
421      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
422      if (arg->exprType() == REAL_EXPR)      if (arg->exprType() == REAL_EXPR) {
423          return successResult( ::fabs(arg->asReal()->evalReal()) );          VMRealExpr* expr = arg->asReal();
424      else          return successRealResult({
425          return successResult( ::abs(arg->asInt()->evalInt()) );              .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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
438  // built-in script function:  random()  // 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 {  bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
457      return type == INT_EXPR;      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) {
     vmint iMin = args->arg(0)->asInt()->evalInt();  
     vmint 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  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
537  // built-in script function:  num_elements()  // built-in script function:  num_elements()
538    
539  bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
540      return type == INT_ARR_EXPR;      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()  // 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) {  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
573      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
574      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
575      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
     if (!in || !out) successResult(0);  
576      vmint i = in->evalInt() + 1;      vmint i = in->evalInt() + 1;
577      IntLiteral tmp(i);      IntLiteral tmp({
578            .value = i,
579            .unitFactor = in->unitFactor()
580        });
581      out->assignExpr(&tmp);      out->assignExpr(&tmp);
582      return successResult(i);      return successResult({
583            .value = i,
584            .unitFactor = in->unitFactor()
585        });
586  }  }
587    
588  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
589  // built-in script function:  dec()  // 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) {  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
614      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
615      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
616      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
     if (!in || !out) successResult(0);  
617      vmint i = in->evalInt() - 1;      vmint i = in->evalInt() - 1;
618      IntLiteral tmp(i);      IntLiteral tmp({
619            .value = i,
620            .unitFactor = in->unitFactor()
621        });
622      out->assignExpr(&tmp);      out->assignExpr(&tmp);
623      return successResult(i);      return successResult({
624            .value = i,
625            .unitFactor = in->unitFactor()
626        });
627  }  }
628    
629  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
630  // built-in script function:  in_range()  // built-in script function:  in_range()
631    
632  VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {  bool CoreVMFunction_in_range::acceptsArgType(vmint iArg, ExprType_t type) const {
633      vmint i  = args->arg(0)->asInt()->evalInt();      return type == INT_EXPR || type == REAL_EXPR;
634      vmint lo = args->arg(1)->asInt()->evalInt();  }
635      vmint hi = args->arg(2)->asInt()->evalInt();  
636      if (lo > hi) { // swap lo and hi  void CoreVMFunction_in_range::checkArgs(VMFnArgs* args,
637          vmint tmp = lo;                                          std::function<void(String)> err,
638          lo = hi;                                          std::function<void(String)> wrn)
639          hi = tmp;  {
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      return successResult(i >= lo && i <= hi);  }
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()  // 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) {  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
701      vmint i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
702      vmint n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
# Line 306  VMFnResult* CoreVMFunction_sh_left::exec Line 706  VMFnResult* CoreVMFunction_sh_left::exec
706  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
707  // built-in script function:  sh_right()  // 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) {  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
714      vmint i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
715      vmint n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
# Line 313  VMFnResult* CoreVMFunction_sh_right::exe Line 717  VMFnResult* CoreVMFunction_sh_right::exe
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()  // built-in script function:  min()
737    
738  ExprType_t CoreVMFunction_min::returnType(VMFnArgs* args) {  ExprType_t CoreVMFunction_min::returnType(VMFnArgs* args) {
# Line 320  ExprType_t CoreVMFunction_min::returnTyp Line 740  ExprType_t CoreVMFunction_min::returnTyp
740              args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;              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 {  bool CoreVMFunction_min::acceptsArgType(vmint iArg, ExprType_t type) const {
753      return type == INT_EXPR || type == REAL_EXPR;      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) {  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
789      VMExpr* a = args->arg(0);      VMNumberExpr* lhs = args->arg(0)->asNumber();
790      VMExpr* b = args->arg(1);      VMNumberExpr* rhs = args->arg(1)->asNumber();
791      if (a->exprType() == REAL_EXPR && b->exprType() == REAL_EXPR) {      if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
792          vmfloat l = a->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
793          vmfloat r = b->asReal()->evalReal();          vmfloat rm = rhs->asReal()->evalReal();
794          return successResult(l < r ? l : r);          vmfloat lprod = lm * lhs->unitFactor();
795      } else if (a->exprType() == REAL_EXPR && b->exprType() == INT_EXPR) {          vmfloat rprod = rm * rhs->unitFactor();
796          vmfloat l = a->asReal()->evalReal();          return successRealResult({
797          vmint   r = b->asInt()->evalInt();              .value = (lprod < rprod) ? lm : rm,
798          return successResult(l < r ? l : r);              .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
799      } else if (a->exprType() == INT_EXPR && b->exprType() == REAL_EXPR) {          });
800          vmint   l = a->asInt()->evalInt();      } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
801          vmfloat r = b->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
802          return successResult(l < r ? l : r);          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 {      } else {
819          vmint l = a->asInt()->evalInt();          vmint lm = lhs->asInt()->evalInt();
820          vmint r = b->asInt()->evalInt();          vmint rm = rhs->asInt()->evalInt();
821          return successResult(l < r ? l : r);          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    
# Line 354  ExprType_t CoreVMFunction_max::returnTyp Line 835  ExprType_t CoreVMFunction_max::returnTyp
835              args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;              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 {  bool CoreVMFunction_max::acceptsArgType(vmint iArg, ExprType_t type) const {
848      return type == INT_EXPR || type == REAL_EXPR;      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) {  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
884      VMExpr* a = args->arg(0);      VMNumberExpr* lhs = args->arg(0)->asNumber();
885      VMExpr* b = args->arg(1);      VMNumberExpr* rhs = args->arg(1)->asNumber();
886      if (a->exprType() == REAL_EXPR && b->exprType() == REAL_EXPR) {      if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
887          vmfloat l = a->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
888          vmfloat r = b->asReal()->evalReal();          vmfloat rm = rhs->asReal()->evalReal();
889          return successResult(l > r ? l : r);          vmfloat lprod = lm * lhs->unitFactor();
890      } else if (a->exprType() == REAL_EXPR && b->exprType() == INT_EXPR) {          vmfloat rprod = rm * rhs->unitFactor();
891          vmfloat l = a->asReal()->evalReal();          return successRealResult({
892          vmint   r = b->asInt()->evalInt();              .value = (lprod > rprod) ? lm : rm,
893          return successResult(l > r ? l : r);              .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
894      } else if (a->exprType() == INT_EXPR && b->exprType() == REAL_EXPR) {          });
895          vmint   l = a->asInt()->evalInt();      } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
896          vmfloat r = b->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
897          return successResult(l > r ? l : r);          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 {      } else {
914          vmint l = a->asInt()->evalInt();          vmint lm = lhs->asInt()->evalInt();
915          vmint r = b->asInt()->evalInt();          vmint rm = rhs->asInt()->evalInt();
916          return successResult(l > r ? l : r);          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()  // 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) {  VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
954      VMIntArrayExpr* l = args->arg(0)->asIntArray();      VMArrayExpr* l = args->arg(0)->asArray();
955      VMIntArrayExpr* r = args->arg(1)->asIntArray();      VMArrayExpr* r = args->arg(1)->asArray();
956      if (l->arraySize() != r->arraySize()) {      if (l->arraySize() != r->arraySize()) {
957          wrnMsg("array_equal(): the two arrays differ in size");          //wrnMsg("array_equal(): the two arrays differ in size");
958          return successResult(0); // false          return successResult(0); // false
959      }      }
960      const vmint n = l->arraySize();      const vmint n = l->arraySize();
961      for (vmint i = 0; i < n; ++i)      // checkArgs() above ensured that we either have INT_ARR_EXPR on both sides
962          if (l->evalIntElement(i) != r->evalIntElement(i))      // or REAL_ARR_EXPR on both sides, so we can simplify here (a bit)
963              return successResult(0); // false      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      return successResult(1); // true
1017  }  }
1018    
1019  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
1020  // built-in script function:  search()  // built-in script function:  search()
1021    
 ExprType_t CoreVMFunction_search::argType(vmint iArg) const {  
     return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;  
 }  
   
1022  bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
1023      if (iArg == 0)      if (iArg == 0)
1024          return type == INT_ARR_EXPR;          return isArray(type);
1025      else      else
1026          return type == INT_EXPR;          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) {  VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
1058      VMIntArrayExpr* a = args->arg(0)->asIntArray();      VMArrayExpr* a = args->arg(0)->asArray();
     const vmint needle = args->arg(1)->asInt()->evalInt();  
1059      const vmint n = a->arraySize();      const vmint n = a->arraySize();
1060      for (vmint i = 0; i < n; ++i)      if (a->exprType() == INT_ARR_EXPR) {
1061          if (a->evalIntElement(i) == needle)          const vmint needle = args->arg(1)->asInt()->evalInt();
1062              return successResult(i);          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      return successResult(-1); // not found
1076  }  }
1077    
1078  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
1079  // built-in script function:  sort()  // built-in script function:  sort()
1080    
 ExprType_t CoreVMFunction_sort::argType(vmint iArg) const {  
     return (iArg == 0) ? INT_ARR_EXPR : INT_EXPR;  
 }  
   
1081  bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
1082      if (iArg == 0)      if (iArg == 0)
1083          return type == INT_ARR_EXPR;          return isArray(type);
1084      else      else
1085          return type == INT_EXPR;          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 {  struct ArrElemPOD {
1120      VMIntArrayExpr* m_array;      T_array* m_array;
1121      vmint m_index;      vmint m_index;
1122  };  };
1123    
1124  static inline void swap(class ArrElemRef a, class ArrElemRef b);  // 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  class ArrElemRef : protected ArrElemPOD {  // 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:  public:
1148      ArrElemRef() {      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          m_array = NULL;  
1150          m_index = 0;      inline ArrElemRef(T_array* a, vmint index) {
1151      }          this->m_array = a;
1152      ArrElemRef(VMIntArrayExpr* a, vmint index) {          this->m_index = index;
1153          m_array = a;      }
1154          m_index = index;      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) {      inline ArrElemRef& operator=(const ArrElemRef& e) {
1159          setValue(e.getValue());          setPrimValue(e.getPrimValue());
1160            setUnitFactor(e.getUnitFactor());
1161          return *this;          return *this;
1162      }      }
1163      inline ArrElemRef& operator=(vmint val) {      inline ArrElemRef& operator=(ScalarNmbrVal value) {
1164          setValue(val);          setPrimValue(value.primValue);
1165            setUnitFactor(value.unitFactor);
1166          return *this;          return *this;
1167      }      }
1168      inline bool operator==(const ArrElemRef& e) const {      inline bool operator==(const ArrElemRef& e) const {
1169          if (m_index == e.m_index)          return getProdValue() == e.getProdValue();
             return true;  
         return getValue() == e.getValue();  
     }  
     inline bool operator==(vmint val) const {  
         return getValue() == val;  
1170      }      }
1171      inline bool operator!=(const ArrElemRef& e) const {      inline bool operator!=(const ArrElemRef& e) const {
1172          return !(operator==(e));          return !(operator==(e));
1173      }      }
     inline bool operator!=(vmint val) const {  
         return !(operator==(val));  
     }  
1174      inline bool operator<(const ArrElemRef& e) const {      inline bool operator<(const ArrElemRef& e) const {
1175          if (m_index == e.m_index)          return getProdValue() < e.getProdValue();
             return false;  
         return getValue() < e.getValue();  
     }  
     inline bool operator<(vmint val) const {  
         return getValue() < val;  
1176      }      }
1177      inline bool operator>(const ArrElemRef& e) const {      inline bool operator>(const ArrElemRef& e) const {
1178          if (m_index == e.m_index)          return getProdValue() > e.getProdValue();
             return false;  
         return getValue() > e.getValue();  
     }  
     inline bool operator>(vmint val) const {  
         return getValue() > val;  
1179      }      }
1180      inline bool operator<=(const ArrElemRef& e) const {      inline bool operator<=(const ArrElemRef& e) const {
1181          if (m_index == e.m_index)          return getProdValue() <= e.getProdValue();
             return true;  
         return getValue() <= e.getValue();  
     }  
     inline bool operator<=(vmint val) const {  
         return getValue() <= val;  
1182      }      }
1183      inline bool operator>=(const ArrElemRef& e) const {      inline bool operator>=(const ArrElemRef& e) const {
1184          if (m_index == e.m_index)          return getProdValue() >= e.getProdValue();
1185              return true;      }
1186          return getValue() >= e.getValue();      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>=(vmint val) const {      inline bool operator>(const ScalarNmbrVal& s) const {
1196          return getValue() >= val;          return getProdValue() > s.getProdValue();
1197      }      }
1198      inline operator vmint() const {      inline bool operator<=(const ScalarNmbrVal& s) const {
1199          return getValue();          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:  protected:
1211      inline vmint getValue() const {      inline T_value getPrimValue() const {
1212          return m_array->evalIntElement(m_index);          return T_accessor::getPrimaryValue( this->m_array, this->m_index );
1213      }      }
1214      inline void setValue(vmint value) {      inline void setPrimValue(T_value value) {
1215          m_array->assignIntElement(m_index, value);          T_accessor::setPrimaryValue( this->m_array, this->m_index, value );
1216      }      }
1217        inline vmfloat getUnitFactor() const {
1218      friend void swap(class ArrElemRef a, class ArrElemRef b);          return this->m_array->unitFactorOfElement(this->m_index);
 };  
   
 class ArrElemPtr : protected ArrElemPOD {  
 public:  
     ArrElemPtr() {  
         m_array = NULL;  
         m_index = 0;  
     }  
     ArrElemPtr(VMIntArrayExpr* a, vmint index) {  
         m_array = a;  
         m_index = index;  
1219      }      }
1220      inline ArrElemRef operator*() {      inline void setUnitFactor(vmfloat factor) {
1221          return *(ArrElemRef*)this;          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  static inline void swap(ArrElemRef a, ArrElemRef b) {      // allow swap() functions below to access protected methods here
1231      vmint valueA = a.getValue();      friend void swap(class ArrElemRef<T_array,T_value,T_accessor> a,
1232      vmint valueB = b.getValue();                       class ArrElemRef<T_array,T_value,T_accessor> b);
1233      a.setValue(valueB);  };
     b.setValue(valueA);  
 }  
1234    
1235  class ArrExprIter : public ArrElemPOD {  // 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:  public:
1239      typedef std::random_access_iterator_tag iterator_category;      typedef std::random_access_iterator_tag iterator_category;
     typedef vmint value_type;  
1240      typedef ssize_t difference_type;      typedef ssize_t difference_type;
1241      typedef ArrElemPtr pointer;      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;      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      ArrExprIter(VMIntArrayExpr* a, vmint index) {      typedef ScalarNmbrVal<T_value> value_type; // type used by STL for temporary values
1245          m_array = a;  
1246          m_index = index;      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*() {      inline ArrElemRef operator*() {
1255          return *(ArrElemRef*)this;          return ArrElemRef(this->m_array, this->m_index);
1256      }      }
1257      inline ArrExprIter& operator++() { // prefix increment      inline ArrExprIter& operator++() { // prefix increment
1258          ++m_index;          ++(this->m_index);
1259          return *this;          return *this;
1260      }      }
1261      inline ArrExprIter& operator--() { // prefix decrement      inline ArrExprIter& operator--() { // prefix decrement
1262          --m_index;          --(this->m_index);
1263          return *this;          return *this;
1264      }      }
1265      inline ArrExprIter operator++(int) { // postfix increment      inline ArrExprIter operator++(int) { // postfix increment
1266          ArrExprIter it = *this;          ArrExprIter it = *this;
1267          ++m_index;          ++(this->m_index);
1268          return it;          return it;
1269      }      }
1270      inline ArrExprIter operator--(int) { // postfix decrement      inline ArrExprIter operator--(int) { // postfix decrement
1271          ArrExprIter it = *this;          ArrExprIter it = *this;
1272          --m_index;          --(this->m_index);
1273          return it;          return it;
1274      }      }
1275      inline ArrExprIter& operator+=(difference_type d) {      inline ArrExprIter& operator+=(difference_type d) {
1276          m_index += d;          this->m_index += d;
1277          return *this;          return *this;
1278      }      }
1279      inline ArrExprIter& operator-=(difference_type d) {      inline ArrExprIter& operator-=(difference_type d) {
1280          m_index -= d;          this->m_index -= d;
1281          return *this;          return *this;
1282      }      }
1283      inline bool operator==(const ArrExprIter& other) const {      inline bool operator==(const ArrExprIter& other) const {
1284          return m_index == other.m_index;          return this->m_index == other.m_index;
1285      }      }
1286      inline bool operator!=(const ArrExprIter& other) const {      inline bool operator!=(const ArrExprIter& other) const {
1287          return m_index != other.m_index;          return this->m_index != other.m_index;
1288      }      }
1289      inline bool operator<(const ArrExprIter& other) const {      inline bool operator<(const ArrExprIter& other) const {
1290          return m_index < other.m_index;          return this->m_index < other.m_index;
1291      }      }
1292      inline bool operator>(const ArrExprIter& other) const {      inline bool operator>(const ArrExprIter& other) const {
1293          return m_index > other.m_index;          return this->m_index > other.m_index;
1294      }      }
1295      inline bool operator<=(const ArrExprIter& other) const {      inline bool operator<=(const ArrExprIter& other) const {
1296          return m_index <= other.m_index;          return this->m_index <= other.m_index;
1297      }      }
1298      inline bool operator>=(const ArrExprIter& other) const {      inline bool operator>=(const ArrExprIter& other) const {
1299          return m_index >= other.m_index;          return this->m_index >= other.m_index;
1300      }      }
1301      inline difference_type operator+(const ArrExprIter& other) const {      inline difference_type operator+(const ArrExprIter& other) const {
1302          return m_index + other.m_index;          return this->m_index + other.m_index;
1303      }      }
1304      inline difference_type operator-(const ArrExprIter& other) const {      inline difference_type operator-(const ArrExprIter& other) const {
1305          return m_index - other.m_index;          return this->m_index - other.m_index;
1306      }      }
1307      inline ArrExprIter operator-(difference_type d) const {      inline ArrExprIter operator-(difference_type d) const {
1308          return ArrExprIter(m_array, m_index - d);          return ArrExprIter(this->m_array, this->m_index - d);
1309      }      }
1310      inline ArrExprIter operator+(difference_type d) const {      inline ArrExprIter operator+(difference_type d) const {
1311          return ArrExprIter(m_array, m_index + d);          return ArrExprIter(this->m_array, this->m_index + d);
1312      }      }
1313      inline ArrExprIter operator*(difference_type factor) const {      inline ArrExprIter operator*(difference_type factor) const {
1314          return ArrExprIter(m_array, m_index * factor);          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 {  struct DescArrExprSorter {
1352      inline bool operator()(const vmint& a, const vmint& b) const {      inline bool operator()(const typename T::value_type a, const typename T::value_type b) const {
1353          return a > b;          return a > b;
1354      }      }
1355  };  };
1356    
1357  VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
1358      VMIntArrayExpr* a = args->arg(0)->asIntArray();      const bool bAscending =
     bool bAscending =  
1359          (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();          (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
1360      vmint n = a->arraySize();  
1361      ArrExprIter itBegin(a, 0);      if (args->arg(0)->exprType() == INT_ARR_EXPR) {
1362      ArrExprIter itEnd(a, n);          VMIntArrayExpr* a = args->arg(0)->asIntArray();
1363      if (bAscending) {          vmint n = a->arraySize();
1364          std::sort(itBegin, itEnd);          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 {      } else {
1373          DescArrExprSorter sorter;          VMRealArrayExpr* a = args->arg(0)->asRealArray();
1374          std::sort(itBegin, itEnd, sorter);          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();      return successResult();
1386  }  }
1387    
1388  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
1389  // built-in script function:  real_to_int()  and  int()  // 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) {  VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {
1400      vmfloat f = args->arg(0)->asReal()->evalReal();      VMRealExpr* realExpr = args->arg(0)->asReal();
1401      return successResult(vmint(f));      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()  // 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) {  VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {
1420      vmint i = args->arg(0)->asInt()->evalInt();      VMIntExpr* intExpr = args->arg(0)->asInt();
1421      return successResult(i);      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.3577  
changed lines
  Added in v.3747

  ViewVC Help
Powered by ViewVC