/[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 3804 - (show annotations) (download)
Thu Aug 6 12:15:02 2020 UTC (3 years, 8 months ago) by schoenebeck
File size: 61951 byte(s)
NKSP: Fixed built-in exit() function to behave as return statement.

* VM API: Introduced new signal STMT_RETURN_SIGNALLED.

* NKSP exit() function: signal STMT_RETURN_SIGNALLED instead of
  STMT_ABORT_SIGNALLED.

* NKSP AST: Introduced common base class 'Subroutine' for 'EventHandler'
  and for new 'UserFunction' class.

* NKSP parser: Use 'UserFunction' class instead of 'Statements' class
  for user declared NKSP functions.

* ScriptVM: Handle new STMT_RETURN_SIGNALLED signal by unwinding the
  stack to previous, calling subroutine.

* NKSP tests: Added test cases for exit() acting as return statement.

* Bumped version (2.1.1.svn62).

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

  ViewVC Help
Powered by ViewVC