/[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 3580 by schoenebeck, Wed Aug 28 15:23:23 2019 UTC revision 3581 by schoenebeck, Fri Aug 30 11:40:25 2019 UTC
# 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 VMEmptyResultFunction  // class VMEmptyResultFunction
31    
# Line 38  VMFnResult* VMEmptyResultFunction::succe Line 45  VMFnResult* VMEmptyResultFunction::succe
45  VMFnResult* VMIntResultFunction::errorResult(vmint i) {  VMFnResult* VMIntResultFunction::errorResult(vmint i) {
46      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
47      result.value = i;      result.value = i;
48        result.unitPrefixFactor = VM_NO_FACTOR;
49      return &result;      return &result;
50  }  }
51    
52  VMFnResult* VMIntResultFunction::successResult(vmint i) {  VMFnResult* VMIntResultFunction::successResult(vmint i) {
53      result.flags = STMT_SUCCESS;      result.flags = STMT_SUCCESS;
54      result.value = i;      result.value = i;
55        result.unitPrefixFactor = VM_NO_FACTOR;
56        return &result;
57    }
58    
59    VMFnResult* VMIntResultFunction::errorResult(VMIntFnResDef res) {
60        result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
61        result.value = res.value;
62        result.unitPrefixFactor = res.unitFactor;
63        return &result;
64    }
65    
66    VMFnResult* VMIntResultFunction::successResult(VMIntFnResDef res) {
67        result.flags = STMT_SUCCESS;
68        result.value = res.value;
69        result.unitPrefixFactor = res.unitFactor;
70      return &result;      return &result;
71  }  }
72    
# Line 53  VMFnResult* VMIntResultFunction::success Line 76  VMFnResult* VMIntResultFunction::success
76  VMFnResult* VMRealResultFunction::errorResult(vmfloat f) {  VMFnResult* VMRealResultFunction::errorResult(vmfloat f) {
77      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
78      result.value = f;      result.value = f;
79        result.unitPrefixFactor = VM_NO_FACTOR;
80        return &result;
81    }
82    
83    VMFnResult* VMRealResultFunction::errorResult(VMRealFnResDef res) {
84        result.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
85        result.value = res.value;
86        result.unitPrefixFactor = res.unitFactor;
87      return &result;      return &result;
88  }  }
89    
90  VMFnResult* VMRealResultFunction::successResult(vmfloat f) {  VMFnResult* VMRealResultFunction::successResult(vmfloat f) {
91      result.flags = STMT_SUCCESS;      result.flags = STMT_SUCCESS;
92      result.value = f;      result.value = f;
93        result.unitPrefixFactor = VM_NO_FACTOR;
94        return &result;
95    }
96    
97    VMFnResult* VMRealResultFunction::successResult(VMRealFnResDef res) {
98        result.flags = STMT_SUCCESS;
99        result.value = res.value;
100        result.unitPrefixFactor = res.unitFactor;
101      return &result;      return &result;
102  }  }
103    
# Line 83  VMFnResult* VMStringResultFunction::succ Line 122  VMFnResult* VMStringResultFunction::succ
122  VMFnResult* VMScalarNumberResultFunction::errorResult(vmint i) {  VMFnResult* VMScalarNumberResultFunction::errorResult(vmint i) {
123      intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
124      intResult.value = i;      intResult.value = i;
125        intResult.unitPrefixFactor = VM_NO_FACTOR;
126      return &intResult;      return &intResult;
127  }  }
128    
129  VMFnResult* VMScalarNumberResultFunction::errorResult(vmfloat f) {  VMFnResult* VMScalarNumberResultFunction::errorResult(vmfloat f) {
130      realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);      realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
131      realResult.value = f;      realResult.value = f;
132        realResult.unitPrefixFactor = VM_NO_FACTOR;
133      return &realResult;      return &realResult;
134  }  }
135    
136  VMFnResult* VMScalarNumberResultFunction::successResult(vmint i) {  VMFnResult* VMScalarNumberResultFunction::successResult(vmint i) {
137      intResult.flags = STMT_SUCCESS;      intResult.flags = STMT_SUCCESS;
138      intResult.value = i;      intResult.value = i;
139        intResult.unitPrefixFactor = VM_NO_FACTOR;
140      return &intResult;      return &intResult;
141  }  }
142    
143  VMFnResult* VMScalarNumberResultFunction::successResult(vmfloat f) {  VMFnResult* VMScalarNumberResultFunction::successResult(vmfloat f) {
144      realResult.flags = STMT_SUCCESS;      realResult.flags = STMT_SUCCESS;
145      realResult.value = f;      realResult.value = f;
146        realResult.unitPrefixFactor = VM_NO_FACTOR;
147        return &realResult;
148    }
149    
150    VMFnResult* VMScalarNumberResultFunction::errorIntResult(VMIntFnResDef res) {
151        intResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
152        intResult.value = res.value;
153        intResult.unitPrefixFactor = res.unitFactor;
154        return &intResult;
155    }
156    
157    VMFnResult* VMScalarNumberResultFunction::errorRealResult(VMRealFnResDef res) {
158        realResult.flags = StmtFlags_t(STMT_ABORT_SIGNALLED | STMT_ERROR_OCCURRED);
159        realResult.value = res.value;
160        realResult.unitPrefixFactor = res.unitFactor;
161        return &realResult;
162    }
163    
164    VMFnResult* VMScalarNumberResultFunction::successIntResult(VMIntFnResDef res) {
165        intResult.flags = STMT_SUCCESS;
166        intResult.value = res.value;
167        intResult.unitPrefixFactor = res.unitFactor;
168        return &intResult;
169    }
170    
171    VMFnResult* VMScalarNumberResultFunction::successRealResult(VMRealFnResDef res) {
172        realResult.flags = STMT_SUCCESS;
173        realResult.value = res.value;
174        realResult.unitPrefixFactor = res.unitFactor;
175      return &realResult;      return &realResult;
176  }  }
177    
# Line 149  bool CoreVMFunction_exit::acceptsArgType Line 220  bool CoreVMFunction_exit::acceptsArgType
220      return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;      return type == INT_EXPR || type == REAL_EXPR || type == STRING_EXPR;
221  }  }
222    
223    bool CoreVMFunction_exit::acceptsArgUnitType(vmint iArg, StdUnit_t type) const {
224        if (!vm->isExitResultEnabled()) return false;
225        return true;
226    }
227    
228    bool CoreVMFunction_exit::acceptsArgUnitPrefix(vmint iArg, StdUnit_t type) const {
229        if (!vm->isExitResultEnabled()) return false;
230        return true;
231    }
232    bool CoreVMFunction_exit::acceptsArgFinal(vmint iArg) const {
233        if (!vm->isExitResultEnabled()) return false;
234        return true;
235    }
236    
237  VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_exit::exec(VMFnArgs* args) {
238      this->result.flags = STMT_ABORT_SIGNALLED;      this->result.flags = STMT_ABORT_SIGNALLED;
239      if (vm->isExitResultEnabled() && args->argsCount()) {      if (vm->isExitResultEnabled() && args->argsCount()) {
240          ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());          ExecContext* ctx = dynamic_cast<ExecContext*>(vm->currentVMExecContext());
241          switch (args->arg(0)->exprType()) {          switch (args->arg(0)->exprType()) {
242              case INT_EXPR:              case INT_EXPR: {
243                  ctx->exitRes.intLiteral.value = args->arg(0)->asInt()->evalInt();                  VMIntExpr* expr = args->arg(0)->asInt();
244                    ctx->exitRes.intLiteral = IntLiteral({
245                        .value = expr->evalInt(),
246                        .unitFactor = expr->unitFactor(),
247                        .unitType = expr->unitType(),
248                        .isFinal = expr->isFinal()
249                    });
250                  ctx->exitRes.value = &ctx->exitRes.intLiteral;                  ctx->exitRes.value = &ctx->exitRes.intLiteral;
251                  break;                  break;
252              case REAL_EXPR:              }
253                  ctx->exitRes.realLiteral.value = args->arg(0)->asReal()->evalReal();              case REAL_EXPR: {
254                    VMRealExpr* expr = args->arg(0)->asReal();
255                    ctx->exitRes.realLiteral = RealLiteral({
256                        .value = expr->evalReal(),
257                        .unitFactor = expr->unitFactor(),
258                        .unitType = expr->unitType(),
259                        .isFinal = expr->isFinal()
260                    });
261                  ctx->exitRes.value = &ctx->exitRes.realLiteral;                  ctx->exitRes.value = &ctx->exitRes.realLiteral;
262                  break;                  break;
263                }
264              case STRING_EXPR:              case STRING_EXPR:
265                  ctx->exitRes.stringLiteral.value = args->arg(0)->asString()->evalStr();                  ctx->exitRes.stringLiteral = StringLiteral(
266                        args->arg(0)->asString()->evalStr()
267                    );
268                  ctx->exitRes.value = &ctx->exitRes.stringLiteral;                  ctx->exitRes.value = &ctx->exitRes.stringLiteral;
269                  break;                  break;
270              default:              default:
# Line 212  ExprType_t CoreVMFunction_abs::returnTyp Line 313  ExprType_t CoreVMFunction_abs::returnTyp
313      return args->arg(0)->exprType();      return args->arg(0)->exprType();
314  }  }
315    
316    StdUnit_t CoreVMFunction_abs::returnUnitType(VMFnArgs* args) {
317        return args->arg(0)->asScalarNumberExpr()->unitType();
318    }
319    
320    bool CoreVMFunction_abs::returnsFinal(VMFnArgs* args) {
321        return args->arg(0)->asScalarNumberExpr()->isFinal();
322    }
323    
324  bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_abs::acceptsArgType(vmint iArg, ExprType_t type) const {
325      return type == INT_EXPR || type == REAL_EXPR;      return type == INT_EXPR || type == REAL_EXPR;
326  }  }
327    
328  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_abs::exec(VMFnArgs* args) {
329      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
330      if (arg->exprType() == REAL_EXPR)      if (arg->exprType() == REAL_EXPR) {
331          return successResult( ::fabs(arg->asReal()->evalReal()) );          VMRealExpr* expr = arg->asReal();
332      else          return successRealResult({
333          return successResult( ::abs(arg->asInt()->evalInt()) );              .value = ::fabs(expr->evalReal()),
334                .unitFactor = expr->unitFactor()
335            });
336        } else {
337            VMIntExpr* expr = arg->asInt();
338            return successIntResult({
339                .value = ::abs(expr->evalInt()),
340                .unitFactor = expr->unitFactor()
341            });
342        }
343  }  }
344    
345  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
346  // built-in script function:  random()  // built-in script function:  random()
347    
348    ExprType_t CoreVMFunction_random::returnType(VMFnArgs* args) {
349        return (args->arg(0)->exprType() == INT_EXPR &&
350                args->arg(1)->exprType() == INT_EXPR) ? INT_EXPR : REAL_EXPR;
351    }
352    
353    StdUnit_t CoreVMFunction_random::returnUnitType(VMFnArgs* args) {
354        // we ensure in checkArgs() below (which is called before this method here)
355        // that both arguments must be of same unit type, so either one is fine here
356        return args->arg(0)->asScalarNumberExpr()->unitType();
357    }
358    
359    bool CoreVMFunction_random::returnsFinal(VMFnArgs* args) {
360        return args->arg(0)->asScalarNumberExpr()->isFinal() ||
361               args->arg(1)->asScalarNumberExpr()->isFinal();
362    }
363    
364  bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_random::acceptsArgType(vmint iArg, ExprType_t type) const {
365      return type == INT_EXPR;      return type == INT_EXPR || type == REAL_EXPR;
366    }
367    
368    void CoreVMFunction_random::checkArgs(VMFnArgs* args,
369                                          std::function<void(String)> err,
370                                          std::function<void(String)> wrn)
371    {
372        // super class checks
373        Super::checkArgs(args, err, wrn);
374    
375        // own checks ...
376        if (args->arg(0)->asScalarNumberExpr()->unitType() !=
377            args->arg(1)->asScalarNumberExpr()->unitType())
378        {
379            String a = unitTypeStr(args->arg(0)->asScalarNumberExpr()->unitType());
380            String b = unitTypeStr(args->arg(1)->asScalarNumberExpr()->unitType());
381            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
382            return;
383        }
384        if (args->arg(0)->asScalarNumberExpr()->isFinal() !=
385            args->arg(1)->asScalarNumberExpr()->isFinal())
386        {
387            String a = args->arg(0)->asScalarNumberExpr()->isFinal() ? "'final'" : "not 'final'";
388            String b = args->arg(1)->asScalarNumberExpr()->isFinal() ? "'final'" : "not 'final'";
389            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
390        }
391  }  }
392    
393  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();  
394      float f = float(::rand()) / float(RAND_MAX);      float f = float(::rand()) / float(RAND_MAX);
395      return successResult(  
396          iMin + roundf( f * float(iMax - iMin) )      VMScalarNumberExpr* arg0 = args->arg(0)->asScalarNumberExpr();
397      );      VMScalarNumberExpr* arg1 = args->arg(1)->asScalarNumberExpr();
398    
399        if (arg0->exprType() == INT_EXPR && arg1->exprType() == INT_EXPR) {
400            vmint iMin = args->arg(0)->asInt()->evalInt();
401            vmint iMax = args->arg(1)->asInt()->evalInt();
402            if (arg0->unitFactor() == arg1->unitFactor()) {
403                return successIntResult({
404                    .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
405                    .unitFactor = arg0->unitFactor()
406                });
407            } else if (arg0->unitFactor() < arg1->unitFactor()) {
408                iMax = Unit::convIntToUnitFactor(iMax, arg1, arg0);
409                return successIntResult({
410                    .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
411                    .unitFactor = arg0->unitFactor()
412                });
413            } else { // arg0->unitFactor() > arg1->unitFactor() ...
414                iMin = Unit::convIntToUnitFactor(iMin, arg0, arg1);
415                return successIntResult({
416                    .value = vmint( iMin + roundf( f * float(iMax - iMin) ) ),
417                    .unitFactor = arg1->unitFactor()
418                });
419            }
420        } else {
421            vmfloat fMin = arg0->evalCastReal();
422            vmfloat fMax = arg1->evalCastReal();
423            if (arg0->unitFactor() == arg1->unitFactor()) {
424                return successRealResult({
425                    .value = fMin + f * (fMax - fMin),
426                    .unitFactor = arg0->unitFactor()
427                });
428            } else if (arg0->unitFactor() < arg1->unitFactor()) {
429                fMax = Unit::convRealToUnitFactor(fMax, arg1, arg0);
430                return successRealResult({
431                    .value = fMin + f * (fMax - fMin),
432                    .unitFactor = arg0->unitFactor()
433                });
434            } else { // arg0->unitFactor() > arg1->unitFactor() ...
435                fMin = Unit::convRealToUnitFactor(fMin, arg0, arg1);
436                return successRealResult({
437                    .value = fMin + f * (fMax - fMin),
438                    .unitFactor = arg1->unitFactor()
439                });
440            }
441        }
442  }  }
443    
444  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
445  // built-in script function:  num_elements()  // built-in script function:  num_elements()
446    
447  bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_num_elements::acceptsArgType(vmint iArg, ExprType_t type) const {
448      return type == INT_ARR_EXPR;      return isArray(type);
449  }  }
450    
451  VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_num_elements::exec(VMFnArgs* args) {
452      return successResult( args->arg(0)->asIntArray()->arraySize() );      return successResult( args->arg(0)->asArray()->arraySize() );
453  }  }
454    
455  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
456  // built-in script function:  inc()  // built-in script function:  inc()
457    
458    StdUnit_t CoreVMFunction_inc::returnUnitType(VMFnArgs* args) {
459        return args->arg(0)->asScalarNumberExpr()->unitType();
460    }
461    
462    bool CoreVMFunction_inc::returnsFinal(VMFnArgs* args) {
463        return args->arg(0)->asScalarNumberExpr()->isFinal();
464    }
465    
466    void CoreVMFunction_inc::checkArgs(VMFnArgs* args,
467                                       std::function<void(String)> err,
468                                       std::function<void(String)> wrn)
469    {
470        // super class checks
471        Super::checkArgs(args, err, wrn);
472    
473        // own checks ...
474        if (args->arg(0)->asScalarNumberExpr()->unitType()) {
475            String unitType = unitTypeStr(args->arg(0)->asScalarNumberExpr()->unitType());
476            wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be incremented by one.");
477        }
478    }
479    
480  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_inc::exec(VMFnArgs* args) {
481      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
482      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
483      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
     if (!in || !out) successResult(0);  
484      vmint i = in->evalInt() + 1;      vmint i = in->evalInt() + 1;
485      IntLiteral tmp(i);      IntLiteral tmp({
486            .value = i,
487            .unitFactor = in->unitFactor()
488        });
489      out->assignExpr(&tmp);      out->assignExpr(&tmp);
490      return successResult(i);      return successResult({
491            .value = i,
492            .unitFactor = in->unitFactor()
493        });
494  }  }
495    
496  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
497  // built-in script function:  dec()  // built-in script function:  dec()
498    
499    StdUnit_t CoreVMFunction_dec::returnUnitType(VMFnArgs* args) {
500        return args->arg(0)->asScalarNumberExpr()->unitType();
501    }
502    
503    bool CoreVMFunction_dec::returnsFinal(VMFnArgs* args) {
504        return args->arg(0)->asScalarNumberExpr()->isFinal();
505    }
506    
507    void CoreVMFunction_dec::checkArgs(VMFnArgs* args,
508                                       std::function<void(String)> err,
509                                       std::function<void(String)> wrn)
510    {
511        // super class checks
512        Super::checkArgs(args, err, wrn);
513    
514        // own checks ...
515        if (args->arg(0)->asScalarNumberExpr()->unitType()) {
516            String unitType = unitTypeStr(args->arg(0)->asScalarNumberExpr()->unitType());
517            wrn("Argument has a unit type (" + unitType + "), only the number before the unit will be decremented by one.");
518        }
519    }
520    
521  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_dec::exec(VMFnArgs* args) {
522      VMExpr* arg = args->arg(0);      VMExpr* arg = args->arg(0);
523      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);      VMIntExpr* in = dynamic_cast<VMIntExpr*>(arg);
524      VMVariable* out = dynamic_cast<VMVariable*>(arg);      VMVariable* out = dynamic_cast<VMVariable*>(arg);
     if (!in || !out) successResult(0);  
525      vmint i = in->evalInt() - 1;      vmint i = in->evalInt() - 1;
526      IntLiteral tmp(i);      IntLiteral tmp({
527            .value = i,
528            .unitFactor = in->unitFactor()
529        });
530      out->assignExpr(&tmp);      out->assignExpr(&tmp);
531      return successResult(i);      return successResult({
532            .value = i,
533            .unitFactor = in->unitFactor()
534        });
535  }  }
536    
537  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
538  // built-in script function:  in_range()  // built-in script function:  in_range()
539    
540  VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {  bool CoreVMFunction_in_range::acceptsArgType(vmint iArg, ExprType_t type) const {
541      vmint i  = args->arg(0)->asInt()->evalInt();      return type == INT_EXPR || type == REAL_EXPR;
542      vmint lo = args->arg(1)->asInt()->evalInt();  }
543      vmint hi = args->arg(2)->asInt()->evalInt();  
544      if (lo > hi) { // swap lo and hi  void CoreVMFunction_in_range::checkArgs(VMFnArgs* args,
545          vmint tmp = lo;                                          std::function<void(String)> err,
546          lo = hi;                                          std::function<void(String)> wrn)
547          hi = tmp;  {
548        // super class checks
549        Super::checkArgs(args, err, wrn);
550    
551        // own checks ...
552        if (args->arg(0)->asScalarNumberExpr()->unitType() !=
553            args->arg(1)->asScalarNumberExpr()->unitType() ||
554            args->arg(1)->asScalarNumberExpr()->unitType() !=
555            args->arg(2)->asScalarNumberExpr()->unitType())
556        {
557            String a = unitTypeStr(args->arg(0)->asScalarNumberExpr()->unitType());
558            String b = unitTypeStr(args->arg(1)->asScalarNumberExpr()->unitType());
559            String c = unitTypeStr(args->arg(2)->asScalarNumberExpr()->unitType());
560            err("Arguments must all have same unit, however argument 1 is " + a +
561                ", argument 2 is " + b + ", argument 3 is " + c + ".");
562            return;
563        }
564        if (args->arg(0)->exprType() != args->arg(1)->exprType() ||
565            args->arg(1)->exprType() != args->arg(2)->exprType())
566        {
567            String a = typeStr(args->arg(0)->exprType());
568            String b = typeStr(args->arg(1)->exprType());
569            String c = typeStr(args->arg(2)->exprType());
570            String r = typeStr(REAL_EXPR);
571            wrn("Argument 1 is " + a + ", argument 2 is " + b +
572                ", argument 3 is " + c + ", function result will be " + r + ".");
573      }      }
574      return successResult(i >= lo && i <= hi);  }
575    
576    template<class T>
577    inline void _swapByValue(T& a, T& b) {
578        T tmp = a;
579        a = b;
580        b = tmp;
581    }
582    
583    VMFnResult* CoreVMFunction_in_range::exec(VMFnArgs* args) {
584        VMScalarNumberExpr* argNeedle = args->arg(0)->asScalarNumberExpr();
585        VMScalarNumberExpr* argLo = args->arg(1)->asScalarNumberExpr();
586        VMScalarNumberExpr* argHi = args->arg(2)->asScalarNumberExpr();
587    
588        vmfloat needle = argNeedle->evalCastReal();
589        vmfloat lo = argLo->evalCastReal();
590        vmfloat hi = argHi->evalCastReal();
591    
592        needle *= argNeedle->unitFactor();
593        lo *= argLo->unitFactor();
594        hi *= argHi->unitFactor();
595    
596        if (lo > hi) _swapByValue(lo, hi);
597    
598        return successResult(needle >= lo && needle <= hi);
599  }  }
600    
601  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
602  // built-in script function:  sh_left()  // built-in script function:  sh_left()
603    
604    bool CoreVMFunction_sh_left::returnsFinal(VMFnArgs* args) {
605        return args->arg(0)->asScalarNumberExpr()->isFinal();
606    }
607    
608  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sh_left::exec(VMFnArgs* args) {
609      vmint i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
610      vmint n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
# Line 306  VMFnResult* CoreVMFunction_sh_left::exec Line 614  VMFnResult* CoreVMFunction_sh_left::exec
614  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
615  // built-in script function:  sh_right()  // built-in script function:  sh_right()
616    
617    bool CoreVMFunction_sh_right::returnsFinal(VMFnArgs* args) {
618        return args->arg(0)->asScalarNumberExpr()->isFinal();
619    }
620    
621  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sh_right::exec(VMFnArgs* args) {
622      vmint i = args->arg(0)->asInt()->evalInt();      vmint i = args->arg(0)->asInt()->evalInt();
623      vmint n = args->arg(1)->asInt()->evalInt();      vmint n = args->arg(1)->asInt()->evalInt();
# Line 320  ExprType_t CoreVMFunction_min::returnTyp Line 632  ExprType_t CoreVMFunction_min::returnTyp
632              args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;              args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
633  }  }
634    
635    StdUnit_t CoreVMFunction_min::returnUnitType(VMFnArgs* args) {
636        return args->arg(0)->asScalarNumberExpr()->unitType();
637    }
638    
639    bool CoreVMFunction_min::returnsFinal(VMFnArgs* args) {
640        return args->arg(0)->asScalarNumberExpr()->isFinal() ||
641               args->arg(1)->asScalarNumberExpr()->isFinal();
642    }
643    
644  bool CoreVMFunction_min::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_min::acceptsArgType(vmint iArg, ExprType_t type) const {
645      return type == INT_EXPR || type == REAL_EXPR;      return type == INT_EXPR || type == REAL_EXPR;
646  }  }
647    
648    void CoreVMFunction_min::checkArgs(VMFnArgs* args,
649                                       std::function<void(String)> err,
650                                       std::function<void(String)> wrn)
651    {
652        // super class checks
653        Super::checkArgs(args, err, wrn);
654    
655        // own checks ...
656        if (args->arg(0)->asScalarNumberExpr()->unitType() !=
657            args->arg(1)->asScalarNumberExpr()->unitType())
658        {
659            String a = unitTypeStr(args->arg(0)->asScalarNumberExpr()->unitType());
660            String b = unitTypeStr(args->arg(1)->asScalarNumberExpr()->unitType());
661            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
662            return;
663        }
664        if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
665            String a = typeStr(args->arg(0)->exprType());
666            String b = typeStr(args->arg(1)->exprType());
667            String c = typeStr(REAL_EXPR);
668            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be " + c + ".");
669            return;
670        }
671        if (args->arg(0)->asScalarNumberExpr()->isFinal() !=
672            args->arg(1)->asScalarNumberExpr()->isFinal())
673        {
674            String a = args->arg(0)->asScalarNumberExpr()->isFinal() ? "'final'" : "not 'final'";
675            String b = args->arg(1)->asScalarNumberExpr()->isFinal() ? "'final'" : "not 'final'";
676            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
677        }
678    }
679    
680  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_min::exec(VMFnArgs* args) {
681      VMExpr* a = args->arg(0);      VMScalarNumberExpr* lhs = args->arg(0)->asScalarNumberExpr();
682      VMExpr* b = args->arg(1);      VMScalarNumberExpr* rhs = args->arg(1)->asScalarNumberExpr();
683      if (a->exprType() == REAL_EXPR && b->exprType() == REAL_EXPR) {      if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
684          vmfloat l = a->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
685          vmfloat r = b->asReal()->evalReal();          vmfloat rm = rhs->asReal()->evalReal();
686          return successResult(l < r ? l : r);          vmfloat lprod = lm * lhs->unitFactor();
687      } else if (a->exprType() == REAL_EXPR && b->exprType() == INT_EXPR) {          vmfloat rprod = rm * rhs->unitFactor();
688          vmfloat l = a->asReal()->evalReal();          return successRealResult({
689          vmint   r = b->asInt()->evalInt();              .value = (lprod < rprod) ? lm : rm,
690          return successResult(l < r ? l : r);              .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
691      } else if (a->exprType() == INT_EXPR && b->exprType() == REAL_EXPR) {          });
692          vmint   l = a->asInt()->evalInt();      } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
693          vmfloat r = b->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
694          return successResult(l < r ? l : r);          vmint   rm = rhs->asInt()->evalInt();
695            vmfloat lprod = lm * lhs->unitFactor();
696            vmfloat rprod = rm * rhs->unitFactor();
697            return successRealResult({
698                .value = (lprod < rprod) ? lm : rm,
699                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
700            });
701        } else if (lhs->exprType() == INT_EXPR && rhs->exprType() == REAL_EXPR) {
702            vmint   lm = lhs->asInt()->evalInt();
703            vmfloat rm = rhs->asReal()->evalReal();
704            vmfloat lprod = lm * lhs->unitFactor();
705            vmfloat rprod = rm * rhs->unitFactor();
706            return successRealResult({
707                .value = (lprod < rprod) ? lm : rm,
708                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
709            });
710      } else {      } else {
711          vmint l = a->asInt()->evalInt();          vmint lm = lhs->asInt()->evalInt();
712          vmint r = b->asInt()->evalInt();          vmint rm = rhs->asInt()->evalInt();
713          return successResult(l < r ? l : r);          vmfloat lprod = lm * lhs->unitFactor();
714            vmfloat rprod = rm * rhs->unitFactor();
715            return successIntResult({
716                .value = (lprod < rprod) ? lm : rm,
717                .unitFactor = (lprod < rprod) ? lhs->unitFactor() : rhs->unitFactor()
718            });
719      }      }
720  }  }
721    
# Line 354  ExprType_t CoreVMFunction_max::returnTyp Line 727  ExprType_t CoreVMFunction_max::returnTyp
727              args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;              args->arg(1)->exprType() == REAL_EXPR) ? REAL_EXPR : INT_EXPR;
728  }  }
729    
730    StdUnit_t CoreVMFunction_max::returnUnitType(VMFnArgs* args) {
731        return args->arg(0)->asScalarNumberExpr()->unitType();
732    }
733    
734    bool CoreVMFunction_max::returnsFinal(VMFnArgs* args) {
735        return args->arg(0)->asScalarNumberExpr()->isFinal() ||
736               args->arg(1)->asScalarNumberExpr()->isFinal();
737    }
738    
739  bool CoreVMFunction_max::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_max::acceptsArgType(vmint iArg, ExprType_t type) const {
740      return type == INT_EXPR || type == REAL_EXPR;      return type == INT_EXPR || type == REAL_EXPR;
741  }  }
742    
743    void CoreVMFunction_max::checkArgs(VMFnArgs* args,
744                                       std::function<void(String)> err,
745                                       std::function<void(String)> wrn)
746    {
747        // super class checks
748        Super::checkArgs(args, err, wrn);
749    
750        // own checks ...
751        if (args->arg(0)->asScalarNumberExpr()->unitType() !=
752            args->arg(1)->asScalarNumberExpr()->unitType())
753        {
754            String a = unitTypeStr(args->arg(0)->asScalarNumberExpr()->unitType());
755            String b = unitTypeStr(args->arg(1)->asScalarNumberExpr()->unitType());
756            err("Argument 1 has unit type " + a + ", whereas argument 2 has unit type " + b + ".");
757            return;
758        }
759        if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
760            String a = typeStr(args->arg(0)->exprType());
761            String b = typeStr(args->arg(1)->exprType());
762            String c = typeStr(REAL_EXPR);
763            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be " + c + ".");
764            return;
765        }
766        if (args->arg(0)->asScalarNumberExpr()->isFinal() !=
767            args->arg(1)->asScalarNumberExpr()->isFinal())
768        {
769            String a = args->arg(0)->asScalarNumberExpr()->isFinal() ? "'final'" : "not 'final'";
770            String b = args->arg(1)->asScalarNumberExpr()->isFinal() ? "'final'" : "not 'final'";
771            wrn("Argument 1 is " + a + ", whereas argument 2 is " + b + ", function result will be final.");
772        }
773    }
774    
775  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_max::exec(VMFnArgs* args) {
776      VMExpr* a = args->arg(0);      VMScalarNumberExpr* lhs = args->arg(0)->asScalarNumberExpr();
777      VMExpr* b = args->arg(1);      VMScalarNumberExpr* rhs = args->arg(1)->asScalarNumberExpr();
778      if (a->exprType() == REAL_EXPR && b->exprType() == REAL_EXPR) {      if (lhs->exprType() == REAL_EXPR && rhs->exprType() == REAL_EXPR) {
779          vmfloat l = a->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
780          vmfloat r = b->asReal()->evalReal();          vmfloat rm = rhs->asReal()->evalReal();
781          return successResult(l > r ? l : r);          vmfloat lprod = lm * lhs->unitFactor();
782      } else if (a->exprType() == REAL_EXPR && b->exprType() == INT_EXPR) {          vmfloat rprod = rm * rhs->unitFactor();
783          vmfloat l = a->asReal()->evalReal();          return successRealResult({
784          vmint   r = b->asInt()->evalInt();              .value = (lprod > rprod) ? lm : rm,
785          return successResult(l > r ? l : r);              .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
786      } else if (a->exprType() == INT_EXPR && b->exprType() == REAL_EXPR) {          });
787          vmint   l = a->asInt()->evalInt();      } else if (lhs->exprType() == REAL_EXPR && rhs->exprType() == INT_EXPR) {
788          vmfloat r = b->asReal()->evalReal();          vmfloat lm = lhs->asReal()->evalReal();
789          return successResult(l > r ? l : r);          vmint   rm = rhs->asInt()->evalInt();
790            vmfloat lprod = lm * lhs->unitFactor();
791            vmfloat rprod = rm * rhs->unitFactor();
792            return successRealResult({
793                .value = (lprod > rprod) ? lm : rm,
794                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
795            });
796        } else if (lhs->exprType() == INT_EXPR && rhs->exprType() == REAL_EXPR) {
797            vmint   lm = lhs->asInt()->evalInt();
798            vmfloat rm = rhs->asReal()->evalReal();
799            vmfloat lprod = lm * lhs->unitFactor();
800            vmfloat rprod = rm * rhs->unitFactor();
801            return successRealResult({
802                .value = (lprod > rprod) ? lm : rm,
803                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
804            });
805      } else {      } else {
806          vmint l = a->asInt()->evalInt();          vmint lm = lhs->asInt()->evalInt();
807          vmint r = b->asInt()->evalInt();          vmint rm = rhs->asInt()->evalInt();
808          return successResult(l > r ? l : r);          vmfloat lprod = lm * lhs->unitFactor();
809            vmfloat rprod = rm * rhs->unitFactor();
810            return successIntResult({
811                .value = (lprod > rprod) ? lm : rm,
812                .unitFactor = (lprod > rprod) ? lhs->unitFactor() : rhs->unitFactor()
813            });
814      }      }
815  }  }
816    
817  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
818  // built-in script function:  array_equal()  // built-in script function:  array_equal()
819    
820    bool CoreVMFunction_array_equal::acceptsArgType(vmint iArg, ExprType_t type) const {
821        return isArray(type);
822    }
823    
824    void CoreVMFunction_array_equal::checkArgs(VMFnArgs* args,
825                                               std::function<void(String)> err,
826                                               std::function<void(String)> wrn)
827    {
828        // super class checks
829        Super::checkArgs(args, err, wrn);
830    
831        // own checks ...
832        if (args->arg(0)->exprType() != args->arg(1)->exprType()) {
833            String a = typeStr(args->arg(0)->exprType());
834            String b = typeStr(args->arg(1)->exprType());
835            err("Argument 1 is " + a + ", whereas argument 2 is " + b + ".");
836            return;
837        }
838        if (args->arg(0)->asArray()->arraySize() !=
839            args->arg(1)->asArray()->arraySize())
840        {
841            wrn("Result of function call is always false, since the passed two arrays were declared with different array sizes.");
842        }
843    }
844    
845  VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_array_equal::exec(VMFnArgs* args) {
846      VMIntArrayExpr* l = args->arg(0)->asIntArray();      VMArrayExpr* l = args->arg(0)->asArray();
847      VMIntArrayExpr* r = args->arg(1)->asIntArray();      VMArrayExpr* r = args->arg(1)->asArray();
848      if (l->arraySize() != r->arraySize()) {      if (l->arraySize() != r->arraySize()) {
849          wrnMsg("array_equal(): the two arrays differ in size");          //wrnMsg("array_equal(): the two arrays differ in size");
850          return successResult(0); // false          return successResult(0); // false
851      }      }
852      const vmint n = l->arraySize();      const vmint n = l->arraySize();
853      for (vmint i = 0; i < n; ++i)      // checkArgs() above ensured that we either have INT_ARR_EXPR on both sides
854          if (l->evalIntElement(i) != r->evalIntElement(i))      // or REAL_ARR_EXPR on both sides, so we can simplify here (a bit)
855              return successResult(0); // false      if (l->exprType() == INT_ARR_EXPR) {
856            VMIntArrayExpr* lia = l->asIntArray();
857            VMIntArrayExpr* ria = r->asIntArray();
858            for (vmint i = 0; i < n; ++i) {
859                vmint lvalue = lia->evalIntElement(i);
860                vmint rvalue = ria->evalIntElement(i);
861                vmfloat lfactor = lia->unitFactorOfElement(i);
862                vmfloat rfactor = ria->unitFactorOfElement(i);
863                if (lfactor == rfactor) {
864                    if (lvalue != rvalue)
865                        return successResult(0); // false
866                    else
867                        continue;
868                }
869                if (lfactor < rfactor) {
870                    if (lvalue != Unit::convIntToUnitFactor(rvalue, rfactor, lfactor))
871                        return successResult(0); // false
872                    else
873                        continue;
874                } else {
875                    if (rvalue != Unit::convIntToUnitFactor(lvalue, lfactor, rfactor))
876                        return successResult(0); // false
877                    else
878                        continue;
879                }
880            }
881        } else {
882            VMRealArrayExpr* lra = l->asRealArray();
883            VMRealArrayExpr* rra = r->asRealArray();
884            for (vmint i = 0; i < n; ++i) {
885                vmfloat lvalue = lra->evalRealElement(i);
886                vmfloat rvalue = rra->evalRealElement(i);
887                vmfloat lfactor = lra->unitFactorOfElement(i);
888                vmfloat rfactor = rra->unitFactorOfElement(i);
889                if (lfactor == rfactor) {
890                    if (!_fEqualX(lvalue, rvalue))
891                        return successResult(0); // false
892                    else
893                        continue;
894                }
895                if (lfactor < rfactor) {
896                    if (!_fEqualX(lvalue, Unit::convRealToUnitFactor(rvalue, rfactor, lfactor)))
897                        return successResult(0); // false
898                    else
899                        continue;
900                } else {
901                    if (!_fEqualX(rvalue, Unit::convRealToUnitFactor(lvalue, lfactor, rfactor)))
902                        return successResult(0); // false
903                    else
904                        continue;
905                }
906            }
907        }
908      return successResult(1); // true      return successResult(1); // true
909  }  }
910    
# Line 406  ExprType_t CoreVMFunction_search::argTyp Line 917  ExprType_t CoreVMFunction_search::argTyp
917    
918  bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_search::acceptsArgType(vmint iArg, ExprType_t type) const {
919      if (iArg == 0)      if (iArg == 0)
920          return type == INT_ARR_EXPR;          return isArray(type);
921      else      else
922          return type == INT_EXPR;          return type == INT_EXPR || type == REAL_EXPR;
923    }
924    
925    void CoreVMFunction_search::checkArgs(VMFnArgs* args,
926                                          std::function<void(String)> err,
927                                          std::function<void(String)> wrn)
928    {
929        // super class checks
930        Super::checkArgs(args, err, wrn);
931    
932        // own checks ...
933        if (args->arg(0)->exprType() == INT_ARR_EXPR &&
934            args->arg(1)->exprType() != INT_EXPR)
935        {
936            String a = typeStr(INT_ARR_EXPR);
937            String bIs = typeStr(args->arg(1)->exprType());
938            String bShould = typeStr(INT_EXPR);
939            err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
940            return;
941        }
942        if (args->arg(0)->exprType() == REAL_ARR_EXPR &&
943            args->arg(1)->exprType() != REAL_EXPR)
944        {
945            String a = typeStr(REAL_ARR_EXPR);
946            String bIs = typeStr(args->arg(1)->exprType());
947            String bShould = typeStr(REAL_EXPR);
948            err("Argument 1 is " + a + ", hence argument 2 should be " + bShould + ", is " + bIs + " though.");
949            return;
950        }
951  }  }
952    
953  VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_search::exec(VMFnArgs* args) {
954      VMIntArrayExpr* a = args->arg(0)->asIntArray();      VMArrayExpr* a = args->arg(0)->asArray();
     const vmint needle = args->arg(1)->asInt()->evalInt();  
955      const vmint n = a->arraySize();      const vmint n = a->arraySize();
956      for (vmint i = 0; i < n; ++i)      if (a->exprType() == INT_ARR_EXPR) {
957          if (a->evalIntElement(i) == needle)          const vmint needle = args->arg(1)->asInt()->evalInt();
958              return successResult(i);          VMIntArrayExpr* intArray = a->asIntArray();
959            for (vmint i = 0; i < n; ++i)
960                if (intArray->evalIntElement(i) == needle)
961                    return successResult(i);
962        } else { // real array ...
963            const vmfloat needle = args->arg(1)->asReal()->evalReal();
964            VMRealArrayExpr* realArray = a->asRealArray();
965            for (vmint i = 0; i < n; ++i) {
966                const vmfloat value = realArray->evalRealElement(i);
967                if (_fEqualX(value, needle))
968                    return successResult(i);
969            }
970        }
971      return successResult(-1); // not found      return successResult(-1); // not found
972  }  }
973    
# Line 430  ExprType_t CoreVMFunction_sort::argType( Line 980  ExprType_t CoreVMFunction_sort::argType(
980    
981  bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {  bool CoreVMFunction_sort::acceptsArgType(vmint iArg, ExprType_t type) const {
982      if (iArg == 0)      if (iArg == 0)
983          return type == INT_ARR_EXPR;          return isArray(type);
984      else      else
985          return type == INT_EXPR;          return type == INT_EXPR;
986  }  }
987    
988    // The following structs and template classes act as adapters for allowing to
989    // use std sort algorithms on our arrays. It might look a bit more complicated
990    // than it ought to be, but there is one reason for the large amount of
991    // 'adapter' code below: the STL std algorithms rely on 'lvalues' to do their
992    // e.g. sorting) jobs, that is they expect containers to have 'localizeable'
993    // data which essentially means their data should reside somewhere in memory and
994    // directly be accessible (readable and writable) there, which is not the case
995    // with our VM interfaces which actually always require virtual getter and
996    // setter methods to be called instead. So we must emulate lvalues by custom
997    // classes/structs which forward between our getters/setters and the lvalue
998    // access operators used by the STL std algorithms.
999    
1000    struct IntArrayAccessor {
1001        static inline vmint getPrimaryValue(VMIntArrayExpr* arr, vmint index) {
1002            return arr->evalIntElement(index);
1003        }
1004        static inline void setPrimaryValue(VMIntArrayExpr* arr, vmint index, vmint value) {
1005            arr->assignIntElement(index, value);
1006        }
1007    };
1008    
1009    struct RealArrayAccessor {
1010        static inline vmfloat getPrimaryValue(VMRealArrayExpr* arr, vmint index) {
1011            return arr->evalRealElement(index);
1012        }
1013        static inline void setPrimaryValue(VMRealArrayExpr* arr, vmint index, vmfloat value) {
1014            arr->assignRealElement(index, value);
1015        }
1016    };
1017    
1018    template<class T_array> // i.e. T_array is either VMIntArrayExpr or VMRealArrayExpr
1019  struct ArrElemPOD {  struct ArrElemPOD {
1020      VMIntArrayExpr* m_array;      T_array* m_array;
1021      vmint m_index;      vmint m_index;
1022  };  };
1023    
1024  static inline void swap(class ArrElemRef a, class ArrElemRef b);  // This class is used for temporary values by std::sort().
1025    template<class T_value> // i.e. T_value is either vmint or vmfloat
1026    struct ScalarNmbrVal {
1027        T_value primValue;
1028        vmfloat unitFactor;
1029    
1030        inline bool operator<(const ScalarNmbrVal& other) const {
1031            return getProdValue() < other.getProdValue();
1032        }
1033        inline bool operator>(const ScalarNmbrVal& other) const {
1034            return getProdValue() > other.getProdValue();
1035        }
1036        inline vmfloat getProdValue() const {
1037            // simple solution for both vmint and vmfloat, should be fine for just sorting
1038            return primValue * unitFactor;
1039        }
1040    };
1041    
1042  class ArrElemRef : protected ArrElemPOD {  // This class emulates lvalue access (access by reference) which is used by ArrExprIter::operator*() below.
1043    template<class T_array, // T_array is either VMIntArrayExpr or VMRealArrayExpr
1044             class T_value, // T_value is either vmint or vmfloat
1045             class T_accessor> // T_accessor is either IntArrayAccessor or RealArrayAccessor
1046    class ArrElemRef : protected ArrElemPOD<T_array> {
1047  public:  public:
1048      ArrElemRef() {      typedef ScalarNmbrVal<T_value> ScalarNmbrVal;
1049          m_array = NULL;  
1050          m_index = 0;      inline ArrElemRef(T_array* a, vmint index) {
1051      }          this->m_array = a;
1052      ArrElemRef(VMIntArrayExpr* a, vmint index) {          this->m_index = index;
1053          m_array = a;      }
1054          m_index = index;      inline ArrElemRef(const ArrElemRef& ref) {
1055            this->m_array = ref.m_array;
1056            this->m_index = ref.m_index;
1057      }      }
1058      inline ArrElemRef& operator=(const ArrElemRef& e) {      inline ArrElemRef& operator=(const ArrElemRef& e) {
1059          setValue(e.getValue());          setPrimValue(e.getPrimValue());
1060            setUnitFactor(e.getUnitFactor());
1061          return *this;          return *this;
1062      }      }
1063      inline ArrElemRef& operator=(vmint val) {      inline ArrElemRef& operator=(ScalarNmbrVal value) {
1064          setValue(val);          setPrimValue(value.primValue);
1065            setUnitFactor(value.unitFactor);
1066          return *this;          return *this;
1067      }      }
1068      inline bool operator==(const ArrElemRef& e) const {      inline bool operator==(const ArrElemRef& e) const {
1069          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;  
1070      }      }
1071      inline bool operator!=(const ArrElemRef& e) const {      inline bool operator!=(const ArrElemRef& e) const {
1072          return !(operator==(e));          return !(operator==(e));
1073      }      }
     inline bool operator!=(vmint val) const {  
         return !(operator==(val));  
     }  
1074      inline bool operator<(const ArrElemRef& e) const {      inline bool operator<(const ArrElemRef& e) const {
1075          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;  
1076      }      }
1077      inline bool operator>(const ArrElemRef& e) const {      inline bool operator>(const ArrElemRef& e) const {
1078          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;  
1079      }      }
1080      inline bool operator<=(const ArrElemRef& e) const {      inline bool operator<=(const ArrElemRef& e) const {
1081          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;  
1082      }      }
1083      inline bool operator>=(const ArrElemRef& e) const {      inline bool operator>=(const ArrElemRef& e) const {
1084          if (m_index == e.m_index)          return getProdValue() >= e.getProdValue();
1085              return true;      }
1086          return getValue() >= e.getValue();      inline bool operator==(const ScalarNmbrVal& s) const {
1087            return getProdValue() == s.getProdValue();
1088        }
1089        inline bool operator!=(const ScalarNmbrVal& s) const {
1090            return !(operator==(s));
1091        }
1092        inline bool operator<(const ScalarNmbrVal& s) const {
1093            return getProdValue() < s.getProdValue();
1094        }
1095        inline bool operator>(const ScalarNmbrVal& s) const {
1096            return getProdValue() > s.getProdValue();
1097        }
1098        inline bool operator<=(const ScalarNmbrVal& s) const {
1099            return getProdValue() <= s.getProdValue();
1100      }      }
1101      inline bool operator>=(vmint val) const {      inline bool operator>=(const ScalarNmbrVal& s) const {
1102          return getValue() >= val;          return getProdValue() >= s.getProdValue();
1103      }      }
1104      inline operator vmint() const {      inline operator ScalarNmbrVal() {
1105          return getValue();          return {
1106                .primValue = getPrimValue() ,
1107                .unitFactor = getUnitFactor()
1108            };
1109      }      }
1110  protected:  protected:
1111      inline vmint getValue() const {      inline T_value getPrimValue() const {
1112          return m_array->evalIntElement(m_index);          return T_accessor::getPrimaryValue( this->m_array, this->m_index );
1113      }      }
1114      inline void setValue(vmint value) {      inline void setPrimValue(T_value value) {
1115          m_array->assignIntElement(m_index, value);          T_accessor::setPrimaryValue( this->m_array, this->m_index, value );
1116      }      }
1117        inline vmfloat getUnitFactor() const {
1118      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;  
1119      }      }
1120      inline ArrElemRef operator*() {      inline void setUnitFactor(vmfloat factor) {
1121          return *(ArrElemRef*)this;          this->m_array->assignElementUnitFactor(this->m_index, factor);
1122        }
1123        inline vmfloat getProdValue() const {
1124            // simple solution for both vmint and vmfloat, should be fine for just sorting
1125            vmfloat primary = (vmfloat) getPrimValue();
1126            vmfloat factor  = getUnitFactor();
1127            return primary * factor;
1128      }      }
 };  
1129    
1130  static inline void swap(ArrElemRef a, ArrElemRef b) {      // allow swap() functions below to access protected methods here
1131      vmint valueA = a.getValue();      friend void swap(class ArrElemRef<T_array,T_value,T_accessor> a,
1132      vmint valueB = b.getValue();                       class ArrElemRef<T_array,T_value,T_accessor> b);
1133      a.setValue(valueB);  };
     b.setValue(valueA);  
 }  
1134    
1135  class ArrExprIter : public ArrElemPOD {  // custom iterator class to be used by std:sort() on our VM arrays
1136    template<class T_array, class T_value, class T_accessor>
1137    class ArrExprIter : public ArrElemPOD<T_array> {
1138  public:  public:
1139      typedef std::random_access_iterator_tag iterator_category;      typedef std::random_access_iterator_tag iterator_category;
     typedef vmint value_type;  
1140      typedef ssize_t difference_type;      typedef ssize_t difference_type;
1141      typedef ArrElemPtr pointer;      typedef ArrElemRef<T_array, T_value, T_accessor> ArrElemRef;
1142      typedef ArrElemRef reference;      typedef ArrElemRef reference; // type used by STL for access by reference
1143        typedef void pointer; // type used by STL for -> operator result, we don't use that operator at all so just void it
1144      ArrExprIter(VMIntArrayExpr* a, vmint index) {      typedef ScalarNmbrVal<T_value> value_type; // type used by STL for temporary values
1145          m_array = a;  
1146          m_index = index;      ArrExprIter(T_array* a, vmint index) {
1147            this->m_array = a;
1148            this->m_index = index;
1149        }
1150        ArrExprIter(const ArrElemRef& ref) {
1151            this->m_array = ref.m_array;
1152            this->m_index = ref.m_index;
1153      }      }
1154      inline ArrElemRef operator*() {      inline ArrElemRef operator*() {
1155          return *(ArrElemRef*)this;          return ArrElemRef(this->m_array, this->m_index);
1156      }      }
1157      inline ArrExprIter& operator++() { // prefix increment      inline ArrExprIter& operator++() { // prefix increment
1158          ++m_index;          ++(this->m_index);
1159          return *this;          return *this;
1160      }      }
1161      inline ArrExprIter& operator--() { // prefix decrement      inline ArrExprIter& operator--() { // prefix decrement
1162          --m_index;          --(this->m_index);
1163          return *this;          return *this;
1164      }      }
1165      inline ArrExprIter operator++(int) { // postfix increment      inline ArrExprIter operator++(int) { // postfix increment
1166          ArrExprIter it = *this;          ArrExprIter it = *this;
1167          ++m_index;          ++(this->m_index);
1168          return it;          return it;
1169      }      }
1170      inline ArrExprIter operator--(int) { // postfix decrement      inline ArrExprIter operator--(int) { // postfix decrement
1171          ArrExprIter it = *this;          ArrExprIter it = *this;
1172          --m_index;          --(this->m_index);
1173          return it;          return it;
1174      }      }
1175      inline ArrExprIter& operator+=(difference_type d) {      inline ArrExprIter& operator+=(difference_type d) {
1176          m_index += d;          this->m_index += d;
1177          return *this;          return *this;
1178      }      }
1179      inline ArrExprIter& operator-=(difference_type d) {      inline ArrExprIter& operator-=(difference_type d) {
1180          m_index -= d;          this->m_index -= d;
1181          return *this;          return *this;
1182      }      }
1183      inline bool operator==(const ArrExprIter& other) const {      inline bool operator==(const ArrExprIter& other) const {
1184          return m_index == other.m_index;          return this->m_index == other.m_index;
1185      }      }
1186      inline bool operator!=(const ArrExprIter& other) const {      inline bool operator!=(const ArrExprIter& other) const {
1187          return m_index != other.m_index;          return this->m_index != other.m_index;
1188      }      }
1189      inline bool operator<(const ArrExprIter& other) const {      inline bool operator<(const ArrExprIter& other) const {
1190          return m_index < other.m_index;          return this->m_index < other.m_index;
1191      }      }
1192      inline bool operator>(const ArrExprIter& other) const {      inline bool operator>(const ArrExprIter& other) const {
1193          return m_index > other.m_index;          return this->m_index > other.m_index;
1194      }      }
1195      inline bool operator<=(const ArrExprIter& other) const {      inline bool operator<=(const ArrExprIter& other) const {
1196          return m_index <= other.m_index;          return this->m_index <= other.m_index;
1197      }      }
1198      inline bool operator>=(const ArrExprIter& other) const {      inline bool operator>=(const ArrExprIter& other) const {
1199          return m_index >= other.m_index;          return this->m_index >= other.m_index;
1200      }      }
1201      inline difference_type operator+(const ArrExprIter& other) const {      inline difference_type operator+(const ArrExprIter& other) const {
1202          return m_index + other.m_index;          return this->m_index + other.m_index;
1203      }      }
1204      inline difference_type operator-(const ArrExprIter& other) const {      inline difference_type operator-(const ArrExprIter& other) const {
1205          return m_index - other.m_index;          return this->m_index - other.m_index;
1206      }      }
1207      inline ArrExprIter operator-(difference_type d) const {      inline ArrExprIter operator-(difference_type d) const {
1208          return ArrExprIter(m_array, m_index - d);          return ArrExprIter(this->m_array, this->m_index - d);
1209      }      }
1210      inline ArrExprIter operator+(difference_type d) const {      inline ArrExprIter operator+(difference_type d) const {
1211          return ArrExprIter(m_array, m_index + d);          return ArrExprIter(this->m_array, this->m_index + d);
1212      }      }
1213      inline ArrExprIter operator*(difference_type factor) const {      inline ArrExprIter operator*(difference_type factor) const {
1214          return ArrExprIter(m_array, m_index * factor);          return ArrExprIter(this->m_array, this->m_index * factor);
1215      }      }
1216  };  };
1217    
1218    typedef ArrExprIter<VMIntArrayExpr,vmint,IntArrayAccessor> IntArrExprIter;
1219    typedef ArrExprIter<VMRealArrayExpr,vmfloat,RealArrayAccessor> RealArrExprIter;
1220    
1221    // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1222    static inline void swap(IntArrExprIter::ArrElemRef a,
1223                            IntArrExprIter::ArrElemRef b)
1224    {
1225        vmint valueA = a.getPrimValue();
1226        vmint valueB = b.getPrimValue();
1227        vmfloat factorA = a.getUnitFactor();
1228        vmfloat factorB = b.getUnitFactor();
1229        a.setPrimValue(valueB);
1230        a.setUnitFactor(factorB);
1231        b.setPrimValue(valueA);
1232        b.setUnitFactor(factorA);
1233    }
1234    
1235    // intentionally not a template function to avoid potential clashes with other (i.e. system's) swap() functions
1236    static inline void swap(RealArrExprIter::ArrElemRef a,
1237                            RealArrExprIter::ArrElemRef b)
1238    {
1239        vmfloat valueA = a.getPrimValue();
1240        vmfloat valueB = b.getPrimValue();
1241        vmfloat factorA = a.getUnitFactor();
1242        vmfloat factorB = b.getUnitFactor();
1243        a.setPrimValue(valueB);
1244        a.setUnitFactor(factorB);
1245        b.setPrimValue(valueA);
1246        b.setUnitFactor(factorA);
1247    }
1248    
1249    // used to sort in descending order (unlike the default behaviour of std::sort() which is ascending order)
1250    template<class T> // T is either IntArrExprIter or RealArrExprIter
1251  struct DescArrExprSorter {  struct DescArrExprSorter {
1252      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 {
1253          return a > b;          return a > b;
1254      }      }
1255  };  };
1256    
1257  VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_sort::exec(VMFnArgs* args) {
1258      VMIntArrayExpr* a = args->arg(0)->asIntArray();      const bool bAscending =
     bool bAscending =  
1259          (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();          (args->argsCount() < 2) ? true : !args->arg(1)->asInt()->evalInt();
1260      vmint n = a->arraySize();  
1261      ArrExprIter itBegin(a, 0);      if (args->arg(0)->exprType() == INT_ARR_EXPR) {
1262      ArrExprIter itEnd(a, n);          VMIntArrayExpr* a = args->arg(0)->asIntArray();
1263      if (bAscending) {          vmint n = a->arraySize();
1264          std::sort(itBegin, itEnd);          IntArrExprIter itBegin(a, 0);
1265            IntArrExprIter itEnd(a, n);
1266            if (bAscending) {
1267                std::sort(itBegin, itEnd);
1268            } else {
1269                DescArrExprSorter<IntArrExprIter> sorter;
1270                std::sort(itBegin, itEnd, sorter);
1271            }
1272      } else {      } else {
1273          DescArrExprSorter sorter;          VMRealArrayExpr* a = args->arg(0)->asRealArray();
1274          std::sort(itBegin, itEnd, sorter);          vmint n = a->arraySize();
1275            RealArrExprIter itBegin(a, 0);
1276            RealArrExprIter itEnd(a, n);
1277            if (bAscending) {
1278                std::sort(itBegin, itEnd);
1279            } else {
1280                DescArrExprSorter<RealArrExprIter> sorter;
1281                std::sort(itBegin, itEnd, sorter);
1282            }
1283      }      }
1284    
1285      return successResult();      return successResult();
1286  }  }
1287    
1288  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
1289  // built-in script function:  real_to_int()  and  int()  // built-in script function:  real_to_int()  and  int()
1290    
1291    StdUnit_t CoreVMFunction_real_to_int::returnUnitType(VMFnArgs* args) {
1292        return args->arg(0)->asScalarNumberExpr()->unitType();
1293    }
1294    
1295    bool CoreVMFunction_real_to_int::returnsFinal(VMFnArgs* args) {
1296        return args->arg(0)->asScalarNumberExpr()->isFinal();
1297    }
1298    
1299  VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_real_to_int::exec(VMFnArgs* args) {
1300      vmfloat f = args->arg(0)->asReal()->evalReal();      VMRealExpr* realExpr = args->arg(0)->asReal();
1301      return successResult(vmint(f));      vmfloat f = realExpr->evalReal();
1302        return successResult({
1303            .value = vmint(f),
1304            .unitFactor = realExpr->unitFactor()
1305        });
1306  }  }
1307    
1308  ///////////////////////////////////////////////////////////////////////////  ///////////////////////////////////////////////////////////////////////////
1309  // built-in script function:  int_to_real()  and  real()  // built-in script function:  int_to_real()  and  real()
1310    
1311    StdUnit_t CoreVMFunction_int_to_real::returnUnitType(VMFnArgs* args) {
1312        return args->arg(0)->asScalarNumberExpr()->unitType();
1313    }
1314    
1315    bool CoreVMFunction_int_to_real::returnsFinal(VMFnArgs* args) {
1316        return args->arg(0)->asScalarNumberExpr()->isFinal();
1317    }
1318    
1319  VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {  VMFnResult* CoreVMFunction_int_to_real::exec(VMFnArgs* args) {
1320      vmint i = args->arg(0)->asInt()->evalInt();      VMIntExpr* intExpr = args->arg(0)->asInt();
1321      return successResult(i);      vmint i = intExpr->evalInt();
1322        return successResult({
1323            .value = vmfloat(i),
1324            .unitFactor = intExpr->unitFactor()
1325        });
1326  }  }
1327    
1328  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.3580  
changed lines
  Added in v.3581

  ViewVC Help
Powered by ViewVC