cmake: supernova - missing include_directories() for Jack
[supercollider.git] / lang / LangPrimSource / PyrMathPrim.cpp
blob2f25a2c96babaa3dde9867a414b67da16ccdcf77
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "PyrKernel.h"
22 #include "PyrPrimitive.h"
23 #include "PyrMathPrim.h"
24 #include "MiscInlineMath.h"
25 #include "SC_InlineUnaryOp.h"
26 #include "SC_InlineBinaryOp.h"
27 #include "PyrSignal.h"
28 #include "PyrParseNode.h"
29 #include "PyrMessage.h"
30 #include "clz.h"
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34 #include "SC_Endian.h"
35 #include "SCBase.h"
37 #include "boost/math/special_functions.hpp"
39 const int INT_MAX_BY_PyrSlot = INT_MAX / sizeof(PyrSlot);
41 inline bool IsSignal(PyrSlot* slot) { return (IsObj(slot) && slotRawObject(slot)->classptr == class_signal); }
42 inline bool NotSignal(PyrSlot* slot) { return (NotObj(slot) || slotRawObject(slot)->classptr != class_signal); }
45 /* functors for dispatching template code */
47 struct addNum
49 static inline double run(double lhs, double rhs)
51 return lhs + rhs;
53 static inline int run(int lhs, int rhs)
55 return lhs + rhs;
57 static inline PyrObject* signal_xf(VMGlobals *g, PyrObject* ina, float inb)
59 return signal_add_xf(g, ina, inb);
61 static inline PyrObject* signal_fx(VMGlobals *g, float ina, PyrObject* inb)
63 return signal_xf(g, inb, ina);
65 static inline PyrObject* signal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
67 return signal_add_xx(g, ina, inb);
71 struct mulNum
73 static inline double run(double lhs, double rhs)
75 return lhs * rhs;
77 static inline int run(int lhs, int rhs)
79 return lhs * rhs;
81 static inline PyrObject* signal_xf(VMGlobals *g, PyrObject* ina, float inb)
83 return signal_mul_xf(g, ina, inb);
85 static inline PyrObject* signal_fx(VMGlobals *g, float ina, PyrObject* inb)
87 return signal_xf(g, inb, ina);
89 static inline PyrObject* signal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
91 return signal_mul_xx(g, ina, inb);
95 struct subNum
97 static inline double run(double lhs, double rhs)
99 return lhs - rhs;
101 static inline int run(int lhs, int rhs)
103 return lhs - rhs;
105 static inline PyrObject* signal_xf(VMGlobals *g, PyrObject* ina, float inb)
107 return signal_sub_xf(g, ina, inb);
109 static inline PyrObject* signal_fx(VMGlobals *g, float ina, PyrObject* inb)
111 return signal_sub_fx(g, ina, inb);
113 static inline PyrObject* signal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
115 return signal_sub_xx(g, ina, inb);
119 template <typename Functor>
120 inline int prOpNum(VMGlobals *g, int numArgsPushed)
122 PyrSlot *a, *b;
123 PyrSymbol *msg;
125 a = g->sp - 1;
126 b = g->sp;
128 switch (GetTag(a)) {
129 case tagInt :
130 switch (GetTag(b)) {
131 case tagInt :
132 SetRaw(a, Functor::run(slotRawInt(a), slotRawInt(b)));
133 break;
134 case tagChar :
135 case tagPtr :
136 case tagNil :
137 case tagFalse :
138 case tagTrue :
139 goto send_normal_2;
140 case tagSym :
141 SetSymbol(a, slotRawSymbol(b));
142 break;
143 case tagObj :
144 if (isKindOf(slotRawObject(b), class_signal))
145 SetObject(a, Functor::signal_fx(g, slotRawInt(a), slotRawObject(b)));
146 else
147 goto send_normal_2;
148 break;
149 default :
150 SetFloat(a, slotRawInt(a) + slotRawFloat(b));
151 break;
153 break;
154 case tagChar :
155 case tagPtr :
156 case tagNil :
157 case tagFalse :
158 case tagTrue :
159 goto send_normal_2;
160 case tagSym :
161 // leave self in 'a'
162 break;
163 case tagObj :
164 if (isKindOf(slotRawObject(a), class_signal)) {
165 switch (GetTag(b)) {
166 case tagInt :
167 SetRaw(a, Functor::signal_xf(g, slotRawObject(a), slotRawInt(b)));
168 break;
169 case tagChar :
170 case tagPtr :
171 case tagNil :
172 case tagFalse :
173 case tagTrue :
174 goto send_normal_2;
175 case tagSym :
176 SetSymbol(a, slotRawSymbol(b));
177 break;
178 case tagObj :
179 if (isKindOf(slotRawObject(b), class_signal)) {
180 SetRaw(a, Functor::signal_xx(g, slotRawObject(a), slotRawObject(b)));
181 } else
182 goto send_normal_2;
183 break;
184 default : // double
185 SetRaw(a, Functor::signal_xf(g, slotRawObject(a), slotRawFloat(b)));
186 break;
188 } else
189 goto send_normal_2;
190 break;
191 default : // double
192 switch (GetTag(b)) {
193 case tagInt :
194 SetRaw(a, Functor::run(slotRawFloat(a), (double)slotRawInt(b)));
195 break;
196 case tagChar :
197 case tagPtr :
198 case tagNil :
199 case tagFalse :
200 case tagTrue :
201 goto send_normal_2;
202 case tagSym :
203 SetSymbol(a, slotRawSymbol(b));
204 break;
205 case tagObj :
206 if (isKindOf(slotRawObject(b), class_signal))
207 SetObject(a, Functor::signal_fx(g, slotRawFloat(a), slotRawObject(b)));
208 else
209 goto send_normal_2;
210 break;
211 default : // double
212 SetRaw(a, Functor::run(slotRawFloat(a), slotRawFloat(b)));
213 break;
215 break;
217 g->sp-- ; // drop
218 g->numpop = 0;
219 #if TAILCALLOPTIMIZE
220 g->tailCall = 0;
221 #endif
222 return errNone;
224 send_normal_2:
225 if (numArgsPushed != -1) // special case flag meaning it is a primitive
226 return errFailed; // arguments remain on the stack
228 msg = gSpecialBinarySelectors[g->primitiveIndex];
229 sendMessage(g, msg, 2);
230 return errNone;
233 template <typename Functor>
234 inline int prOpInt(VMGlobals *g, int numArgsPushed)
236 PyrSlot *a, *b;
237 PyrSymbol *msg;
239 a = g->sp - 1;
240 b = g->sp;
242 switch (GetTag(b)) {
243 case tagInt :
244 SetRaw(a, Functor::run(slotRawInt(a), slotRawInt(b)));
245 break;
246 case tagChar :
247 case tagPtr :
248 case tagNil :
249 case tagFalse :
250 case tagTrue :
251 goto send_normal_2;
252 case tagSym :
253 SetSymbol(a, slotRawSymbol(b));
254 break;
255 case tagObj :
256 if (isKindOf(slotRawObject(b), class_signal))
257 SetObject(a, Functor::signal_fx(g, slotRawInt(a), slotRawObject(b)));
258 else
259 goto send_normal_2;
260 break;
261 default :
262 SetFloat(a, Functor::run((double)slotRawInt(a), slotRawFloat(b)));
263 break;
265 g->sp-- ; // drop
266 g->numpop = 0;
267 #if TAILCALLOPTIMIZE
268 g->tailCall = 0;
269 #endif
270 return errNone;
272 send_normal_2:
273 if (numArgsPushed != -1) // special case flag meaning it is a primitive
274 return errFailed; // arguments remain on the stack
276 msg = gSpecialBinarySelectors[g->primitiveIndex];
277 sendMessage(g, msg, 2);
278 return errNone;
281 template <typename Functor>
282 inline int prOpFloat(VMGlobals *g, int numArgsPushed)
284 PyrSlot *a, *b;
285 PyrSymbol *msg;
287 a = g->sp - 1;
288 b = g->sp;
290 switch (GetTag(b)) {
291 case tagInt :
292 SetRaw(a, Functor::run(slotRawFloat(a), (double)slotRawInt(b)));
293 break;
294 case tagChar :
295 case tagPtr :
296 case tagNil :
297 case tagFalse :
298 case tagTrue :
299 goto send_normal_2;
300 case tagSym :
301 SetSymbol(a, slotRawSymbol(b));
302 break;
303 case tagObj :
304 if (isKindOf(slotRawObject(b), class_signal))
305 SetObject(a, Functor::signal_fx(g, slotRawFloat(a), slotRawObject(b)));
306 else
307 goto send_normal_2;
308 break;
309 default :
310 SetRaw(a, Functor::run(slotRawFloat(a), slotRawFloat(b)));
311 break;
313 g->sp-- ; // drop
314 g->numpop = 0;
315 #if TAILCALLOPTIMIZE
316 g->tailCall = 0;
317 #endif
318 return errNone;
320 send_normal_2:
321 if (numArgsPushed != -1) // special case flag meaning it is a primitive
322 return errFailed; // arguments remain on the stack
324 msg = gSpecialBinarySelectors[g->primitiveIndex];
325 sendMessage(g, msg, 2);
326 return errNone;
329 int prAddNum(VMGlobals *g, int numArgsPushed)
331 return prOpNum<addNum>(g, numArgsPushed);
334 int prSubNum(VMGlobals *g, int numArgsPushed)
336 return prOpNum<subNum>(g, numArgsPushed);
339 int prMulNum(VMGlobals *g, int numArgsPushed)
341 return prOpNum<mulNum>(g, numArgsPushed);
345 int prAddFloat(VMGlobals *g, int numArgsPushed)
347 return prOpFloat<addNum>(g, numArgsPushed);
350 int prSubFloat(VMGlobals *g, int numArgsPushed)
352 return prOpFloat<subNum>(g, numArgsPushed);
355 int prMulFloat(VMGlobals *g, int numArgsPushed)
357 return prOpFloat<mulNum>(g, numArgsPushed);
360 int prAddInt(VMGlobals *g, int numArgsPushed)
362 return prOpInt<addNum>(g, numArgsPushed);
365 int prSubInt(VMGlobals *g, int numArgsPushed)
367 return prOpInt<subNum>(g, numArgsPushed);
370 int prMulInt(VMGlobals *g, int numArgsPushed)
372 return prOpInt<mulNum>(g, numArgsPushed);
378 int prNthPrime(VMGlobals *g, int numArgsPushed);
379 int prNthPrime(VMGlobals *g, int numArgsPushed)
381 PyrSlot *a;
382 int n, p;
384 a = g->sp;
385 n = slotRawInt(a);
386 p = nthPrime(n);
387 if (p == 0) {
388 SetNil(a);
389 } else {
390 SetInt(a, p);
392 return errNone;
395 int prPrevPrime(VMGlobals *g, int numArgsPushed);
396 int prPrevPrime(VMGlobals *g, int numArgsPushed)
398 PyrSlot *a;
399 int n, p, i;
401 a = g->sp;
402 n = slotRawInt(a);
403 i = prevPrime(n);
404 p = nthPrime(i);
405 if (p == 0) {
406 SetNil(a);
407 } else {
408 SetInt(a, p);
410 return errNone;
413 int prNextPrime(VMGlobals *g, int numArgsPushed);
414 int prNextPrime(VMGlobals *g, int numArgsPushed)
416 PyrSlot *a;
417 int n, p, i;
419 a = g->sp;
420 n = slotRawInt(a);
421 i = nextPrime(n);
422 p = nthPrime(i);
423 if (p == 0) {
424 SetNil(a);
425 } else {
426 SetInt(a, p);
428 return errNone;
432 int prIsPrime(VMGlobals *g, int numArgsPushed);
433 int prIsPrime(VMGlobals *g, int numArgsPushed)
435 PyrSlot *a;
436 int n, p, sqrtn, i;
438 a = g->sp;
439 n = slotRawInt(a);
440 SetNil(a);
441 if (n <= 2) {
442 if (n == 2) { SetTrue(a); }
443 else { SetFalse(a); }
444 } else if (n <= nthPrime(NUMPRIMES-1)) {
445 // do a search of the primes table
446 i = findPrime(n);
447 if (i >= 0) { SetTrue(a); }
448 else { SetFalse(a); }
449 } else {
450 #ifdef SC_WIN32
451 sqrtn = (int)sqrt(static_cast<double>(n));
452 #else
453 sqrtn = (int)sqrt(n);
454 #endif
455 for (i=0; i<NUMPRIMES; ++i) {
456 p = nthPrime(i);
457 if (n % p == 0) { SetFalse(a); break; }
458 if (p >= sqrtn) { SetTrue(a); break; }
461 return errNone;
464 int prIndexOfPrime(VMGlobals *g, int numArgsPushed);
465 int prIndexOfPrime(VMGlobals *g, int numArgsPushed)
467 PyrSlot *a;
468 int n, p;
470 a = g->sp;
471 n = slotRawInt(a);
472 if (n <= 2) {
473 if (n == 2) { SetInt(a, 0); }
474 else { SetNil(a); }
475 } else if (n <= nthPrime(NUMPRIMES-1)) {
476 p = findPrime(n);
477 if (p < 0) {
478 SetNil(a);
479 } else {
480 SetInt(a, p);
482 } else {
483 SetNil(a);
485 return errNone;
489 int prAs32Bits(VMGlobals *g, int numArgsPushed);
490 int prAs32Bits(VMGlobals *g, int numArgsPushed)
492 PyrSlot *a = g->sp;
493 // return an integer that is a bit pattern for the 32 bit float representation
494 union { float f; int32 i; } u;
495 u.f = slotRawFloat(a);
496 SetInt(a, u.i);
497 return errNone;
500 int prHigh32Bits(VMGlobals *g, int numArgsPushed);
501 int prHigh32Bits(VMGlobals *g, int numArgsPushed)
503 PyrSlot *a = g->sp;
505 #if BYTE_ORDER == BIG_ENDIAN
506 union { struct { uint32 hi, lo; } i; double f; } du;
507 #else
508 union { struct { uint32 lo, hi; } i; double f; } du;
509 #endif
511 du.f = slotRawFloat(a);
512 SetInt(a, du.i.hi);
513 return errNone;
516 int prLow32Bits(VMGlobals *g, int numArgsPushed);
517 int prLow32Bits(VMGlobals *g, int numArgsPushed)
519 PyrSlot *a = g->sp;
521 #if BYTE_ORDER == BIG_ENDIAN
522 union { struct { uint32 hi, lo; } i; double f; } du;
523 #else
524 union { struct { uint32 lo, hi; } i; double f; } du;
525 #endif
527 du.f = slotRawFloat(a);
528 SetInt(a, du.i.lo);
529 return errNone;
532 int prFrom32Bits(VMGlobals *g, int numArgsPushed);
533 int prFrom32Bits(VMGlobals *g, int numArgsPushed)
535 PyrSlot *a = g->sp - 1;
536 PyrSlot *b = g->sp;
537 int err, word;
539 err = slotIntVal(b, &word);
540 if (err) return err;
542 union { float f; int32 i; } u;
543 u.i = word;
544 SetFloat(a, u.f);
546 return errNone;
549 int prFrom64Bits(VMGlobals *g, int numArgsPushed);
550 int prFrom64Bits(VMGlobals *g, int numArgsPushed)
552 PyrSlot *a = g->sp - 2;
553 PyrSlot *b = g->sp - 1;
554 PyrSlot *c = g->sp;
555 int err, hi, lo;
557 err = slotIntVal(b, &hi);
558 if (err) return err;
560 err = slotIntVal(c, &lo);
561 if (err) return err;
563 #if BYTE_ORDER == BIG_ENDIAN
564 union { struct { uint32 hi, lo; } i; double f; } du;
565 #else
566 union { struct { uint32 lo, hi; } i; double f; } du;
567 #endif
568 du.i.hi = hi;
569 du.i.lo = lo;
570 SetFloat(a, du.f);
572 return errNone;
575 int mathClipInt(struct VMGlobals *g, int numArgsPushed)
577 PyrSlot *a, *b, *c;
578 double lo, hi;
579 int err;
581 a = g->sp - 2;
582 b = g->sp - 1;
583 c = g->sp;
585 if (IsSym(b)) {
586 *a = *b;
587 } else if (IsSym(c)) {
588 *a = *c;
589 } else if (IsInt(b) && IsInt(c)) {
590 SetRaw(a, sc_clip(slotRawInt(a), slotRawInt(b), slotRawInt(c)));
591 } else {
592 err = slotDoubleVal(b, &lo);
593 if (err) return err;
594 err = slotDoubleVal(c, &hi);
595 if (err) return err;
596 SetFloat(a, sc_clip((double)slotRawInt(a), lo, hi));
598 return errNone;
601 int mathClipFloat(struct VMGlobals *g, int numArgsPushed)
603 PyrSlot *a, *b, *c;
604 double lo, hi;
605 int err;
607 a = g->sp - 2;
608 b = g->sp - 1;
609 c = g->sp;
611 if (IsSym(b)) {
612 *a = *b;
613 } else if (IsSym(c)) {
614 *a = *c;
615 } else {
616 err = slotDoubleVal(b, &lo);
617 if (err) return err;
618 err = slotDoubleVal(c, &hi);
619 if (err) return err;
620 SetRaw(a, sc_clip(slotRawFloat(a), lo, hi));
622 return errNone;
625 int mathClipSignal(struct VMGlobals *g, int numArgsPushed)
627 PyrSlot *a, *b, *c;
628 float lo, hi;
629 int err;
630 PyrObject *sig;
632 a = g->sp - 2;
633 b = g->sp - 1;
634 c = g->sp;
636 if (IsSym(b)) {
637 *a = *b;
638 } else if (IsSym(c)) {
639 *a = *c;
640 } else if (IsSignal(b) && IsSignal(c)) {
641 sig = signal_clip_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
642 SetObject(a, sig);
643 } else {
644 err = slotFloatVal(b, &lo);
645 if (err) return err;
646 err = slotFloatVal(c, &hi);
647 if (err) return err;
648 sig = signal_clip_f(g, slotRawObject(a), lo, hi);
649 SetObject(a, sig);
651 return errNone;
654 int mathWrapInt(struct VMGlobals *g, int numArgsPushed)
656 PyrSlot *a, *b, *c;
657 int err;
659 a = g->sp - 2;
660 b = g->sp - 1;
661 c = g->sp;
663 if (IsSym(b)) {
664 *a = *b;
665 } else if (IsSym(c)) {
666 *a = *c;
667 } else if (IsInt(b) && IsInt(c)) {
668 SetRaw(a, sc_mod((int)(slotRawInt(a) - slotRawInt(b)), (int)(slotRawInt(c) - slotRawInt(b) + 1)) + slotRawInt(b));
669 } else {
670 double x, lo, hi;
671 x = slotRawInt(a);
672 err = slotDoubleVal(b, &lo);
673 if (err) return err;
674 err = slotDoubleVal(c, &hi);
675 if (err) return err;
676 SetFloat(a, sc_mod(x - lo, hi - lo) + lo);
678 return errNone;
681 int mathWrapFloat(struct VMGlobals *g, int numArgsPushed)
683 PyrSlot *a, *b, *c;
684 double lo, hi;
685 int err;
687 a = g->sp - 2;
688 b = g->sp - 1;
689 c = g->sp;
691 if (IsSym(b)) {
692 *a = *b;
693 } else if (IsSym(c)) {
694 *a = *c;
695 } else {
696 err = slotDoubleVal(b, &lo);
697 if (err) return err;
698 err = slotDoubleVal(c, &hi);
699 if (err) return err;
700 SetRaw(a, sc_mod(slotRawFloat(a) - lo, hi - lo) + lo);
702 return errNone;
705 int mathWrapSignal(struct VMGlobals *g, int numArgsPushed)
707 PyrSlot *a, *b, *c;
708 float lo, hi;
709 int err;
710 PyrObject *sig;
712 a = g->sp - 2;
713 b = g->sp - 1;
714 c = g->sp;
716 if (IsSym(b)) {
717 *a = *b;
718 } else if (IsSym(c)) {
719 *a = *c;
720 } else if (IsSignal(b) && IsSignal(c)) {
721 sig = signal_wrap_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
722 SetObject(a, sig);
723 } else {
724 err = slotFloatVal(b, &lo);
725 if (err) return err;
726 err = slotFloatVal(c, &hi);
727 if (err) return err;
728 sig = signal_wrap_f(g, slotRawObject(a), lo, hi);
729 SetObject(a, sig);
731 return errNone;
734 int mathFoldInt(struct VMGlobals *g, int numArgsPushed)
736 PyrSlot *a, *b, *c;
737 int err;
739 a = g->sp - 2;
740 b = g->sp - 1;
741 c = g->sp;
743 if (IsSym(b)) {
744 *a = *b;
745 } else if (IsSym(c)) {
746 *a = *c;
747 } else if (IsInt(b) && IsInt(c)) {
748 SetRaw(a, sc_fold(slotRawInt(a), slotRawInt(b), slotRawInt(c)));
749 } else {
750 double x, lo, hi;
751 x = slotRawInt(a);
752 err = slotDoubleVal(b, &lo);
753 if (err) return err;
754 err = slotDoubleVal(c, &hi);
755 if (err) return err;
756 SetFloat(a, sc_fold(x, lo, hi));
758 return errNone;
761 int mathFoldFloat(struct VMGlobals *g, int numArgsPushed)
763 PyrSlot *a, *b, *c;
764 double lo, hi;
765 int err;
767 a = g->sp - 2;
768 b = g->sp - 1;
769 c = g->sp;
771 if (IsSym(b)) {
772 *a = *b;
773 } else if (IsSym(c)) {
774 *a = *c;
775 } else {
776 err = slotDoubleVal(b, &lo);
777 if (err) return err;
778 err = slotDoubleVal(c, &hi);
779 if (err) return err;
780 SetRaw(a, sc_fold(slotRawFloat(a), lo, hi));
782 return errNone;
785 int mathFoldSignal(struct VMGlobals *g, int numArgsPushed)
787 PyrSlot *a, *b, *c;
788 float lo, hi;
789 int err;
790 PyrObject *sig;
792 a = g->sp - 2;
793 b = g->sp - 1;
794 c = g->sp;
796 if (IsSym(b)) {
797 *a = *b;
798 } else if (IsSym(c)) {
799 *a = *c;
800 } else if (IsSignal(b) && IsSignal(c)) {
801 sig = signal_fold_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
802 SetObject(a, sig);
803 } else {
804 err = slotFloatVal(b, &lo);
805 if (err) return err;
806 err = slotFloatVal(c, &hi);
807 if (err) return err;
808 sig = signal_fold_f(g, slotRawObject(a), lo, hi);
809 SetObject(a, sig);
811 return errNone;
814 int prSimpleNumberSeries(struct VMGlobals *g, int numArgsPushed)
816 PyrSlot *a = g->sp - 2;
817 PyrSlot *b = g->sp - 1;
818 PyrSlot *c = g->sp;
820 int err, size;
822 if (IsInt(a) && (IsInt(b) || IsNil(b)) && IsInt(c)) {
823 int first, second, last, step;
824 first = slotRawInt(a);
825 last = slotRawInt(c);
826 second = IsInt(b) ? slotRawInt(b) : (first < last ? first + 1 : first - 1);
827 step = second - first;
829 if ( step == 0 )
830 size = 1;
831 else
832 size = ((last - first) / step) + 1;
833 if(size<1 || size > INT_MAX_BY_PyrSlot){
834 post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot);
835 return errFailed;
838 PyrObject *obj = newPyrArray(g->gc, size, 0, true);
839 obj->size = size;
840 PyrSlot *slots = obj->slots;
841 if(step==1){
842 // Faster iteration for common case
843 if(first==0){
844 for (int i=0; i<size; ++i) {
845 SetInt(slots+i, i);
847 }else{
848 for (int i=0; i<size; ++i) {
849 SetInt(slots+i, first++);
852 }else{
853 int val = first;
854 for (int i=0; i<size; ++i) {
855 SetInt(slots+i, val);
856 val += step;
859 SetObject(a, obj);
860 } else {
861 double first, second, last, step;
862 err = slotDoubleVal(a, &first);
863 if (err) return err;
864 err = slotDoubleVal(c, &last);
865 if (err) return err;
866 err = slotDoubleVal(b, &second);
867 if (err) {
868 if (first < last) second = first + 1.;
869 else second = first - 1.;
872 step = second - first;
873 size = (int)floor((last - first) / step + 0.001) + 1;
874 if(size<1 || size > INT_MAX_BY_PyrSlot){
875 post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot);
876 return errFailed;
878 PyrObject *obj = newPyrArray(g->gc, size, 0, true);
879 obj->size = size;
880 PyrSlot *slots = obj->slots;
881 if(first==0. && step==1.){
882 // Faster iteration for common case
883 for (long i=0; i<size; ++i) {
884 SetFloat(slots+i, i);
886 }else{
887 double val = first;
888 for (long i=0; i<size; ++i) {
889 val = first + step * i;
890 SetFloat(slots+i, val);
893 SetObject(a, obj);
895 return errNone;
901 asFraction {|maxDenominator=100|
902 var mediant, lower, upper, temp;
903 var n,d, k, k1;
904 if (this < 0) {
905 #n, d = this.neg.asFraction(maxDenominator);
906 ^[n.neg, d]
908 if (this < 1.0) {
909 upper = [1.0, this.reciprocal.floor];
910 lower = [1.0, upper[1]+1.0];
912 lower = [this.floor, 1.0];
913 upper = [lower[0]+1.0, 1.0];
915 mediant = [lower[0] + upper[0], lower[1] + upper[1]];
916 loop {
917 mediant = [lower[0] + upper[0], lower[1] + upper[1]];
918 case
919 { (this * mediant[1]) > mediant[0] }
921 if (maxDenominator < mediant[1]) {^upper};
922 d = upper[0] - (this * upper[1]);
923 if (d == 0) {^upper};
924 lower = mediant;
925 k = floor(((this * lower[1]) - lower[0]) / d);
926 k1 = k + 1;
927 temp = [lower[0] + (k1 * upper[0]), lower[1] + (k1 * upper[1])];
928 lower = [lower[0] + (k * upper[0]), lower[1] + (k * upper[1])];
929 upper = temp;
931 { (this * mediant[1]) == mediant[0] }
933 if (maxDenominator >= mediant[1]) {^mediant};
934 if (lower[1] < upper[1]) {^lower};
935 ^upper
938 if (maxDenominator < mediant[1]) {^lower};
939 d = lower[0] - (this * lower[1]);
940 if (d == 0) {^lower};
941 upper = mediant;
942 k = floor(((this * upper[1]) - upper[0]) / d);
943 k1 = k + 1;
944 temp = [(k1 * lower[0]) + upper[0], (k1 * lower[1]) + upper[1]];
945 upper = [(k * lower[0]) + upper[0], (k * lower[1]) + upper[1]];
946 lower = temp;
953 int prAsFraction(struct VMGlobals *g, int numArgsPushed)
955 PyrSlot *a = g->sp - 2;
956 PyrSlot *b = g->sp - 1;
957 PyrSlot *c = g->sp;
959 double mediant_num, lower_num, upper_num, temp_num;
960 double mediant_den, lower_den, upper_den, temp_den;
961 double x, d;
962 int k, k1;
963 int maxDenominator;
964 int err;
965 bool neg = false;
967 err = slotDoubleVal(a, &x);
968 if (err) return err;
970 err = slotIntVal(b, &maxDenominator);
971 if (err) return err;
973 bool faster = IsTrue(c);
975 PyrObject *obj = newPyrArray(g->gc, 2, 0, true);
976 obj->size = 2;
977 PyrSlot *slots = obj->slots;
978 SetObject(a, obj);
980 if (x < 0.0) {
981 x = -x;
982 neg = true;
985 if (x == 0.0) {
986 SetInt(slots+0, 0);
987 SetInt(slots+1, 1);
988 return errNone;
991 if (x < 1.0) {
992 upper_num = 1.0;
993 upper_den = floor(1./x);
994 lower_num = 1.0;
995 lower_den = upper_den + 1.;
996 } else {
997 lower_num = floor(x);
998 lower_den = 1.0;
999 upper_num = lower_num + 1.;
1000 upper_den = 1.0;
1003 while (true) {
1004 mediant_num = lower_num + upper_num;
1005 mediant_den = lower_den + upper_den;
1006 //post(" md %g %g %g %g %g %g\n", mediant_num, mediant_den, lower_num, lower_den, upper_num, upper_den);
1008 if (x * mediant_den > mediant_num) {
1009 d = upper_num - (x * upper_den);
1010 if (maxDenominator < mediant_den || fabs(d) < 1e-5) {
1011 if (neg) upper_num = -upper_num;
1012 SetInt(slots+0, (int)upper_num);
1013 SetInt(slots+1, (int)upper_den);
1014 return errNone;
1016 lower_num = mediant_num;
1017 lower_den = mediant_den;
1018 if (faster) {
1019 k = (int)floor(((x * lower_den) - lower_num) / d);
1020 if (k < 10000) {
1021 k1 = k + 1;
1022 temp_num = lower_num + (k1 * upper_num);
1023 temp_den = lower_den + (k1 * upper_den);
1024 lower_num = lower_num + (k * upper_num);
1025 lower_den = lower_den + (k * upper_den);
1026 upper_num = temp_num;
1027 upper_den = temp_den;
1030 } else if (x * mediant_den == mediant_num) {
1031 if (maxDenominator >= mediant_den) {
1032 if (neg) mediant_num = -mediant_num;
1033 SetInt(slots+0, (int)mediant_num);
1034 SetInt(slots+1, (int)mediant_den);
1035 return errNone;
1036 } else if (lower_den < upper_den) {
1037 if (neg) lower_num = -lower_num;
1038 SetInt(slots+0, (int)lower_num);
1039 SetInt(slots+1, (int)lower_den);
1040 return errNone;
1041 } else {
1042 if (neg) upper_num = -upper_num;
1043 SetInt(slots+0, (int)upper_num);
1044 SetInt(slots+1, (int)upper_den);
1045 return errNone;
1047 } else {
1048 d = lower_num - (x * lower_den);
1049 if (maxDenominator < mediant_den || fabs(d) < 1e-5) {
1050 if (neg) lower_num = -lower_num;
1051 SetInt(slots+0, (int)lower_num);
1052 SetInt(slots+1, (int)lower_den);
1053 return errNone;
1055 upper_num = mediant_num;
1056 upper_den = mediant_den;
1057 if (faster) {
1058 k = (int)floor(((x * upper_den) - upper_num) / d);
1059 if (k < 10000) {
1060 k1 = k + 1;
1061 temp_num = (k1 * lower_num) + upper_num;
1062 temp_den = (k1 * lower_den) + upper_den;
1063 upper_num = (k * lower_num) + upper_num;
1064 upper_den = (k * lower_den) + upper_den;
1065 lower_num = temp_num;
1066 lower_den = temp_den;
1073 void initMathPrimitives()
1075 int base, index;
1077 base = nextPrimitiveIndex();
1078 index = 0;
1079 definePrimitive(base, index++, "_AddInt", prAddInt, 2, 0);
1080 definePrimitive(base, index++, "_SubInt", prSubInt, 2, 0);
1081 definePrimitive(base, index++, "_MulInt", prMulInt, 2, 0);
1082 definePrimitive(base, index++, "_AddFloat", prAddFloat, 2, 0);
1083 definePrimitive(base, index++, "_SubFloat", prSubFloat, 2, 0);
1084 definePrimitive(base, index++, "_MulFloat", prMulFloat, 2, 0);
1085 definePrimitive(base, index++, "_NthPrime", prNthPrime, 1, 0);
1086 definePrimitive(base, index++, "_PrevPrime", prPrevPrime, 1, 0);
1087 definePrimitive(base, index++, "_NextPrime", prNextPrime, 1, 0);
1088 definePrimitive(base, index++, "_IsPrime", prIsPrime, 1, 0);
1089 definePrimitive(base, index++, "_IndexOfPrime", prIndexOfPrime, 1, 0);
1090 definePrimitive(base, index++, "_As32Bits", prAs32Bits, 1, 0);
1091 definePrimitive(base, index++, "_High32Bits", prHigh32Bits, 1, 0);
1092 definePrimitive(base, index++, "_Low32Bits", prLow32Bits, 1, 0);
1093 definePrimitive(base, index++, "_From32Bits", prFrom32Bits, 2, 0);
1094 definePrimitive(base, index++, "_From64Bits", prFrom64Bits, 3, 0);
1096 definePrimitive(base, index++, "_ClipInt", mathClipInt, 3, 0);
1097 definePrimitive(base, index++, "_ClipFloat", mathClipFloat, 3, 0);
1098 definePrimitive(base, index++, "_ClipSignal", mathClipSignal, 3, 0);
1099 definePrimitive(base, index++, "_WrapInt", mathWrapInt, 3, 0);
1100 definePrimitive(base, index++, "_WrapFloat", mathWrapFloat, 3, 0);
1101 definePrimitive(base, index++, "_WrapSignal", mathWrapSignal, 3, 0);
1102 definePrimitive(base, index++, "_FoldInt", mathFoldInt, 3, 0);
1103 definePrimitive(base, index++, "_FoldFloat", mathFoldFloat, 3, 0);
1104 definePrimitive(base, index++, "_FoldSignal", mathFoldSignal, 3, 0);
1106 definePrimitive(base, index++, "_SimpleNumberSeries", prSimpleNumberSeries, 3, 0);
1107 definePrimitive(base, index++, "_AsFraction", prAsFraction, 3, 0);