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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3744 - (show annotations) (download)
Sat Feb 15 11:50:02 2020 UTC (4 years, 2 months ago) by schoenebeck
File size: 60470 byte(s)
* NKSP: Fixed intermediate function result values never having reflected
  any standard measuring unit type.

* Tests: Guard this fixed NKSP issue by test cases.

* Bumped version (2.1.1.svn49).

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

  ViewVC Help
Powered by ViewVC