Examples under Synth:new should not use SynthDef:play to make nodes
[supercollider.git] / lang / LangPrimSource / PyrMathPrim.cpp
blobcf3f5f8a783b201715589b6cc5d3691414e315df
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 const int INT_MAX_BY_PyrSlot = INT_MAX / sizeof(PyrSlot);
39 inline bool IsSignal(PyrSlot* slot) { return (IsObj(slot) && slotRawObject(slot)->classptr == class_signal); }
40 inline bool NotSignal(PyrSlot* slot) { return (NotObj(slot) || slotRawObject(slot)->classptr != class_signal); }
43 /* functors for dispatching template code */
45 struct addNum
47 static inline double run(double lhs, double rhs)
49 return lhs + rhs;
51 static inline int run(int lhs, int rhs)
53 return lhs + rhs;
55 static inline PyrObject* signal_xf(VMGlobals *g, PyrObject* ina, float inb)
57 return signal_add_xf(g, ina, inb);
59 static inline PyrObject* signal_fx(VMGlobals *g, float ina, PyrObject* inb)
61 return signal_xf(g, inb, ina);
63 static inline PyrObject* signal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
65 return signal_add_xx(g, ina, inb);
69 struct mulNum
71 static inline double run(double lhs, double rhs)
73 return lhs * rhs;
75 static inline int run(int lhs, int rhs)
77 return lhs * rhs;
79 static inline PyrObject* signal_xf(VMGlobals *g, PyrObject* ina, float inb)
81 return signal_mul_xf(g, ina, inb);
83 static inline PyrObject* signal_fx(VMGlobals *g, float ina, PyrObject* inb)
85 return signal_xf(g, inb, ina);
87 static inline PyrObject* signal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
89 return signal_mul_xx(g, ina, inb);
93 struct subNum
95 static inline double run(double lhs, double rhs)
97 return lhs - rhs;
99 static inline int run(int lhs, int rhs)
101 return lhs - rhs;
103 static inline PyrObject* signal_xf(VMGlobals *g, PyrObject* ina, float inb)
105 return signal_sub_xf(g, ina, inb);
107 static inline PyrObject* signal_fx(VMGlobals *g, float ina, PyrObject* inb)
109 return signal_sub_fx(g, ina, inb);
111 static inline PyrObject* signal_xx(VMGlobals *g, PyrObject* ina, PyrObject* inb)
113 return signal_sub_xx(g, ina, inb);
117 template <typename Functor>
118 inline int prOpNum(VMGlobals *g, int numArgsPushed)
120 PyrSlot *a, *b;
121 PyrSymbol *msg;
123 a = g->sp - 1;
124 b = g->sp;
126 switch (GetTag(a)) {
127 case tagInt :
128 switch (GetTag(b)) {
129 case tagInt :
130 SetRaw(a, Functor::run(slotRawInt(a), slotRawInt(b)));
131 break;
132 case tagChar :
133 case tagPtr :
134 case tagNil :
135 case tagFalse :
136 case tagTrue :
137 goto send_normal_2;
138 case tagSym :
139 SetSymbol(a, slotRawSymbol(b));
140 break;
141 case tagObj :
142 if (isKindOf(slotRawObject(b), class_signal))
143 SetObject(a, Functor::signal_fx(g, slotRawInt(a), slotRawObject(b)));
144 else
145 goto send_normal_2;
146 break;
147 default :
148 SetFloat(a, slotRawInt(a) + slotRawFloat(b));
149 break;
151 break;
152 case tagChar :
153 case tagPtr :
154 case tagNil :
155 case tagFalse :
156 case tagTrue :
157 goto send_normal_2;
158 case tagSym :
159 // leave self in 'a'
160 break;
161 case tagObj :
162 if (isKindOf(slotRawObject(a), class_signal)) {
163 switch (GetTag(b)) {
164 case tagInt :
165 SetRaw(a, Functor::signal_xf(g, slotRawObject(a), slotRawInt(b)));
166 break;
167 case tagChar :
168 case tagPtr :
169 case tagNil :
170 case tagFalse :
171 case tagTrue :
172 goto send_normal_2;
173 case tagSym :
174 SetSymbol(a, slotRawSymbol(b));
175 break;
176 case tagObj :
177 if (isKindOf(slotRawObject(b), class_signal)) {
178 SetRaw(a, Functor::signal_xx(g, slotRawObject(a), slotRawObject(b)));
179 } else
180 goto send_normal_2;
181 break;
182 default : // double
183 SetRaw(a, Functor::signal_xf(g, slotRawObject(a), slotRawFloat(b)));
184 break;
186 } else
187 goto send_normal_2;
188 break;
189 default : // double
190 switch (GetTag(b)) {
191 case tagInt :
192 SetRaw(a, Functor::run(slotRawFloat(a), (double)slotRawInt(b)));
193 break;
194 case tagChar :
195 case tagPtr :
196 case tagNil :
197 case tagFalse :
198 case tagTrue :
199 goto send_normal_2;
200 case tagSym :
201 SetSymbol(a, slotRawSymbol(b));
202 break;
203 case tagObj :
204 if (isKindOf(slotRawObject(b), class_signal))
205 SetObject(a, Functor::signal_fx(g, slotRawFloat(a), slotRawObject(b)));
206 else
207 goto send_normal_2;
208 break;
209 default : // double
210 SetRaw(a, Functor::run(slotRawFloat(a), slotRawFloat(b)));
211 break;
213 break;
215 g->sp-- ; // drop
216 g->numpop = 0;
217 #if TAILCALLOPTIMIZE
218 g->tailCall = 0;
219 #endif
220 return errNone;
222 send_normal_2:
223 if (numArgsPushed != -1) // special case flag meaning it is a primitive
224 return errFailed; // arguments remain on the stack
226 msg = gSpecialBinarySelectors[g->primitiveIndex];
227 sendMessage(g, msg, 2);
228 return errNone;
231 template <typename Functor>
232 inline int prOpInt(VMGlobals *g, int numArgsPushed)
234 PyrSlot *a, *b;
235 PyrSymbol *msg;
237 a = g->sp - 1;
238 b = g->sp;
240 switch (GetTag(b)) {
241 case tagInt :
242 SetRaw(a, Functor::run(slotRawInt(a), slotRawInt(b)));
243 break;
244 case tagChar :
245 case tagPtr :
246 case tagNil :
247 case tagFalse :
248 case tagTrue :
249 goto send_normal_2;
250 case tagSym :
251 SetSymbol(a, slotRawSymbol(b));
252 break;
253 case tagObj :
254 if (isKindOf(slotRawObject(b), class_signal))
255 SetObject(a, Functor::signal_fx(g, slotRawInt(a), slotRawObject(b)));
256 else
257 goto send_normal_2;
258 break;
259 default :
260 SetFloat(a, Functor::run((double)slotRawInt(a), slotRawFloat(b)));
261 break;
263 g->sp-- ; // drop
264 g->numpop = 0;
265 #if TAILCALLOPTIMIZE
266 g->tailCall = 0;
267 #endif
268 return errNone;
270 send_normal_2:
271 if (numArgsPushed != -1) // special case flag meaning it is a primitive
272 return errFailed; // arguments remain on the stack
274 msg = gSpecialBinarySelectors[g->primitiveIndex];
275 sendMessage(g, msg, 2);
276 return errNone;
279 template <typename Functor>
280 inline int prOpFloat(VMGlobals *g, int numArgsPushed)
282 PyrSlot *a, *b;
283 PyrSymbol *msg;
285 a = g->sp - 1;
286 b = g->sp;
288 switch (GetTag(b)) {
289 case tagInt :
290 SetRaw(a, Functor::run(slotRawFloat(a), (double)slotRawInt(b)));
291 break;
292 case tagChar :
293 case tagPtr :
294 case tagNil :
295 case tagFalse :
296 case tagTrue :
297 goto send_normal_2;
298 case tagSym :
299 SetSymbol(a, slotRawSymbol(b));
300 break;
301 case tagObj :
302 if (isKindOf(slotRawObject(b), class_signal))
303 SetObject(a, Functor::signal_fx(g, slotRawFloat(a), slotRawObject(b)));
304 else
305 goto send_normal_2;
306 break;
307 default :
308 SetRaw(a, Functor::run(slotRawFloat(a), slotRawFloat(b)));
309 break;
311 g->sp-- ; // drop
312 g->numpop = 0;
313 #if TAILCALLOPTIMIZE
314 g->tailCall = 0;
315 #endif
316 return errNone;
318 send_normal_2:
319 if (numArgsPushed != -1) // special case flag meaning it is a primitive
320 return errFailed; // arguments remain on the stack
322 msg = gSpecialBinarySelectors[g->primitiveIndex];
323 sendMessage(g, msg, 2);
324 return errNone;
327 int prAddNum(VMGlobals *g, int numArgsPushed)
329 return prOpNum<addNum>(g, numArgsPushed);
332 int prSubNum(VMGlobals *g, int numArgsPushed)
334 return prOpNum<subNum>(g, numArgsPushed);
337 int prMulNum(VMGlobals *g, int numArgsPushed)
339 return prOpNum<mulNum>(g, numArgsPushed);
343 int prAddFloat(VMGlobals *g, int numArgsPushed)
345 return prOpFloat<addNum>(g, numArgsPushed);
348 int prSubFloat(VMGlobals *g, int numArgsPushed)
350 return prOpFloat<subNum>(g, numArgsPushed);
353 int prMulFloat(VMGlobals *g, int numArgsPushed)
355 return prOpFloat<mulNum>(g, numArgsPushed);
358 int prAddInt(VMGlobals *g, int numArgsPushed)
360 return prOpInt<addNum>(g, numArgsPushed);
363 int prSubInt(VMGlobals *g, int numArgsPushed)
365 return prOpInt<subNum>(g, numArgsPushed);
368 int prMulInt(VMGlobals *g, int numArgsPushed)
370 return prOpInt<mulNum>(g, numArgsPushed);
376 int prNthPrime(VMGlobals *g, int numArgsPushed);
377 int prNthPrime(VMGlobals *g, int numArgsPushed)
379 PyrSlot *a;
380 int n, p;
382 a = g->sp;
383 n = slotRawInt(a);
384 p = nthPrime(n);
385 if (p == 0) {
386 SetNil(a);
387 } else {
388 SetInt(a, p);
390 return errNone;
393 int prPrevPrime(VMGlobals *g, int numArgsPushed);
394 int prPrevPrime(VMGlobals *g, int numArgsPushed)
396 PyrSlot *a;
397 int n, p, i;
399 a = g->sp;
400 n = slotRawInt(a);
401 i = prevPrime(n);
402 p = nthPrime(i);
403 if (p == 0) {
404 SetNil(a);
405 } else {
406 SetInt(a, p);
408 return errNone;
411 int prNextPrime(VMGlobals *g, int numArgsPushed);
412 int prNextPrime(VMGlobals *g, int numArgsPushed)
414 PyrSlot *a;
415 int n, p, i;
417 a = g->sp;
418 n = slotRawInt(a);
419 i = nextPrime(n);
420 p = nthPrime(i);
421 if (p == 0) {
422 SetNil(a);
423 } else {
424 SetInt(a, p);
426 return errNone;
430 int prIsPrime(VMGlobals *g, int numArgsPushed);
431 int prIsPrime(VMGlobals *g, int numArgsPushed)
433 PyrSlot *a;
434 int n, p, sqrtn, i;
436 a = g->sp;
437 n = slotRawInt(a);
438 SetNil(a);
439 if (n <= 2) {
440 if (n == 2) { SetTrue(a); }
441 else { SetFalse(a); }
442 } else if (n <= nthPrime(NUMPRIMES-1)) {
443 // do a search of the primes table
444 i = findPrime(n);
445 if (i >= 0) { SetTrue(a); }
446 else { SetFalse(a); }
447 } else {
448 #ifdef SC_WIN32
449 sqrtn = (int)sqrt(static_cast<double>(n));
450 #else
451 sqrtn = (int)sqrt(n);
452 #endif
453 for (i=0; i<NUMPRIMES; ++i) {
454 p = nthPrime(i);
455 if (n % p == 0) { SetFalse(a); break; }
456 if (p >= sqrtn) { SetTrue(a); break; }
459 return errNone;
462 int prIndexOfPrime(VMGlobals *g, int numArgsPushed);
463 int prIndexOfPrime(VMGlobals *g, int numArgsPushed)
465 PyrSlot *a;
466 int n, p;
468 a = g->sp;
469 n = slotRawInt(a);
470 if (n <= 2) {
471 if (n == 2) { SetInt(a, 0); }
472 else { SetNil(a); }
473 } else if (n <= nthPrime(NUMPRIMES-1)) {
474 p = findPrime(n);
475 if (p < 0) {
476 SetNil(a);
477 } else {
478 SetInt(a, p);
480 } else {
481 SetNil(a);
483 return errNone;
487 int prAs32Bits(VMGlobals *g, int numArgsPushed);
488 int prAs32Bits(VMGlobals *g, int numArgsPushed)
490 PyrSlot *a = g->sp;
491 // return an integer that is a bit pattern for the 32 bit float representation
492 union { float f; int32 i; } u;
493 u.f = slotRawFloat(a);
494 SetInt(a, u.i);
495 return errNone;
498 int prHigh32Bits(VMGlobals *g, int numArgsPushed);
499 int prHigh32Bits(VMGlobals *g, int numArgsPushed)
501 PyrSlot *a = g->sp;
503 #if BYTE_ORDER == BIG_ENDIAN
504 union { struct { uint32 hi, lo; } i; double f; } du;
505 #else
506 union { struct { uint32 lo, hi; } i; double f; } du;
507 #endif
509 du.f = slotRawFloat(a);
510 SetInt(a, du.i.hi);
511 return errNone;
514 int prLow32Bits(VMGlobals *g, int numArgsPushed);
515 int prLow32Bits(VMGlobals *g, int numArgsPushed)
517 PyrSlot *a = g->sp;
519 #if BYTE_ORDER == BIG_ENDIAN
520 union { struct { uint32 hi, lo; } i; double f; } du;
521 #else
522 union { struct { uint32 lo, hi; } i; double f; } du;
523 #endif
525 du.f = slotRawFloat(a);
526 SetInt(a, du.i.lo);
527 return errNone;
530 int prFrom32Bits(VMGlobals *g, int numArgsPushed);
531 int prFrom32Bits(VMGlobals *g, int numArgsPushed)
533 PyrSlot *a = g->sp - 1;
534 PyrSlot *b = g->sp;
535 int err, word;
537 err = slotIntVal(b, &word);
538 if (err) return err;
540 union { float f; int32 i; } u;
541 u.i = word;
542 SetFloat(a, u.f);
544 return errNone;
547 int prFrom64Bits(VMGlobals *g, int numArgsPushed);
548 int prFrom64Bits(VMGlobals *g, int numArgsPushed)
550 PyrSlot *a = g->sp - 2;
551 PyrSlot *b = g->sp - 1;
552 PyrSlot *c = g->sp;
553 int err, hi, lo;
555 err = slotIntVal(b, &hi);
556 if (err) return err;
558 err = slotIntVal(c, &lo);
559 if (err) return err;
561 #if BYTE_ORDER == BIG_ENDIAN
562 union { struct { uint32 hi, lo; } i; double f; } du;
563 #else
564 union { struct { uint32 lo, hi; } i; double f; } du;
565 #endif
566 du.i.hi = hi;
567 du.i.lo = lo;
568 SetFloat(a, du.f);
570 return errNone;
573 int mathClipInt(struct VMGlobals *g, int numArgsPushed)
575 PyrSlot *a, *b, *c;
576 double lo, hi;
577 int err;
579 a = g->sp - 2;
580 b = g->sp - 1;
581 c = g->sp;
583 if (IsSym(b)) {
584 *a = *b;
585 } else if (IsSym(c)) {
586 *a = *c;
587 } else if (IsInt(b) && IsInt(c)) {
588 SetRaw(a, sc_clip(slotRawInt(a), slotRawInt(b), slotRawInt(c)));
589 } else {
590 err = slotDoubleVal(b, &lo);
591 if (err) return err;
592 err = slotDoubleVal(c, &hi);
593 if (err) return err;
594 SetFloat(a, sc_clip((double)slotRawInt(a), lo, hi));
596 return errNone;
599 int mathClipFloat(struct VMGlobals *g, int numArgsPushed)
601 PyrSlot *a, *b, *c;
602 double lo, hi;
603 int err;
605 a = g->sp - 2;
606 b = g->sp - 1;
607 c = g->sp;
609 if (IsSym(b)) {
610 *a = *b;
611 } else if (IsSym(c)) {
612 *a = *c;
613 } else {
614 err = slotDoubleVal(b, &lo);
615 if (err) return err;
616 err = slotDoubleVal(c, &hi);
617 if (err) return err;
618 SetRaw(a, sc_clip(slotRawFloat(a), lo, hi));
620 return errNone;
623 int mathClipSignal(struct VMGlobals *g, int numArgsPushed)
625 PyrSlot *a, *b, *c;
626 float lo, hi;
627 int err;
628 PyrObject *sig;
630 a = g->sp - 2;
631 b = g->sp - 1;
632 c = g->sp;
634 if (IsSym(b)) {
635 *a = *b;
636 } else if (IsSym(c)) {
637 *a = *c;
638 } else if (IsSignal(b) && IsSignal(c)) {
639 sig = signal_clip_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
640 SetObject(a, sig);
641 } else {
642 err = slotFloatVal(b, &lo);
643 if (err) return err;
644 err = slotFloatVal(c, &hi);
645 if (err) return err;
646 sig = signal_clip_f(g, slotRawObject(a), lo, hi);
647 SetObject(a, sig);
649 return errNone;
652 int mathWrapInt(struct VMGlobals *g, int numArgsPushed)
654 PyrSlot *a, *b, *c;
655 int err;
657 a = g->sp - 2;
658 b = g->sp - 1;
659 c = g->sp;
661 if (IsSym(b)) {
662 *a = *b;
663 } else if (IsSym(c)) {
664 *a = *c;
665 } else if (IsInt(b) && IsInt(c)) {
666 SetRaw(a, sc_mod((int)(slotRawInt(a) - slotRawInt(b)), (int)(slotRawInt(c) - slotRawInt(b) + 1)) + slotRawInt(b));
667 } else {
668 double x, lo, hi;
669 x = slotRawInt(a);
670 err = slotDoubleVal(b, &lo);
671 if (err) return err;
672 err = slotDoubleVal(c, &hi);
673 if (err) return err;
674 SetFloat(a, sc_mod(x - lo, hi - lo) + lo);
676 return errNone;
679 int mathWrapFloat(struct VMGlobals *g, int numArgsPushed)
681 PyrSlot *a, *b, *c;
682 double lo, hi;
683 int err;
685 a = g->sp - 2;
686 b = g->sp - 1;
687 c = g->sp;
689 if (IsSym(b)) {
690 *a = *b;
691 } else if (IsSym(c)) {
692 *a = *c;
693 } else {
694 err = slotDoubleVal(b, &lo);
695 if (err) return err;
696 err = slotDoubleVal(c, &hi);
697 if (err) return err;
698 SetRaw(a, sc_mod(slotRawFloat(a) - lo, hi - lo) + lo);
700 return errNone;
703 int mathWrapSignal(struct VMGlobals *g, int numArgsPushed)
705 PyrSlot *a, *b, *c;
706 float lo, hi;
707 int err;
708 PyrObject *sig;
710 a = g->sp - 2;
711 b = g->sp - 1;
712 c = g->sp;
714 if (IsSym(b)) {
715 *a = *b;
716 } else if (IsSym(c)) {
717 *a = *c;
718 } else if (IsSignal(b) && IsSignal(c)) {
719 sig = signal_wrap_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
720 SetObject(a, sig);
721 } else {
722 err = slotFloatVal(b, &lo);
723 if (err) return err;
724 err = slotFloatVal(c, &hi);
725 if (err) return err;
726 sig = signal_wrap_f(g, slotRawObject(a), lo, hi);
727 SetObject(a, sig);
729 return errNone;
732 int mathFoldInt(struct VMGlobals *g, int numArgsPushed)
734 PyrSlot *a, *b, *c;
735 int err;
737 a = g->sp - 2;
738 b = g->sp - 1;
739 c = g->sp;
741 if (IsSym(b)) {
742 *a = *b;
743 } else if (IsSym(c)) {
744 *a = *c;
745 } else if (IsInt(b) && IsInt(c)) {
746 SetRaw(a, sc_fold(slotRawInt(a), slotRawInt(b), slotRawInt(c)));
747 } else {
748 double x, lo, hi;
749 x = slotRawInt(a);
750 err = slotDoubleVal(b, &lo);
751 if (err) return err;
752 err = slotDoubleVal(c, &hi);
753 if (err) return err;
754 SetFloat(a, sc_fold(x, lo, hi));
756 return errNone;
759 int mathFoldFloat(struct VMGlobals *g, int numArgsPushed)
761 PyrSlot *a, *b, *c;
762 double lo, hi;
763 int err;
765 a = g->sp - 2;
766 b = g->sp - 1;
767 c = g->sp;
769 if (IsSym(b)) {
770 *a = *b;
771 } else if (IsSym(c)) {
772 *a = *c;
773 } else {
774 err = slotDoubleVal(b, &lo);
775 if (err) return err;
776 err = slotDoubleVal(c, &hi);
777 if (err) return err;
778 SetRaw(a, sc_fold(slotRawFloat(a), lo, hi));
780 return errNone;
783 int mathFoldSignal(struct VMGlobals *g, int numArgsPushed)
785 PyrSlot *a, *b, *c;
786 float lo, hi;
787 int err;
788 PyrObject *sig;
790 a = g->sp - 2;
791 b = g->sp - 1;
792 c = g->sp;
794 if (IsSym(b)) {
795 *a = *b;
796 } else if (IsSym(c)) {
797 *a = *c;
798 } else if (IsSignal(b) && IsSignal(c)) {
799 sig = signal_fold_x(g, slotRawObject(a), slotRawObject(b), slotRawObject(c));
800 SetObject(a, sig);
801 } else {
802 err = slotFloatVal(b, &lo);
803 if (err) return err;
804 err = slotFloatVal(c, &hi);
805 if (err) return err;
806 sig = signal_fold_f(g, slotRawObject(a), lo, hi);
807 SetObject(a, sig);
809 return errNone;
812 int prSimpleNumberSeries(struct VMGlobals *g, int numArgsPushed)
814 PyrSlot *a = g->sp - 2;
815 PyrSlot *b = g->sp - 1;
816 PyrSlot *c = g->sp;
818 int err, size;
820 if (IsInt(a) && (IsInt(b) || IsNil(b)) && IsInt(c)) {
821 int first, second, last, step;
822 first = slotRawInt(a);
823 last = slotRawInt(c);
824 second = IsInt(b) ? slotRawInt(b) : (first < last ? first + 1 : first - 1);
825 step = second - first;
827 if ( step == 0 )
828 size = 1;
829 else
830 size = ((last - first) / step) + 1;
831 if(size<1 || size > INT_MAX_BY_PyrSlot){
832 post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot);
833 return errFailed;
836 PyrObject *obj = newPyrArray(g->gc, size, 0, true);
837 obj->size = size;
838 PyrSlot *slots = obj->slots;
839 if(step==1){
840 // Faster iteration for common case
841 if(first==0){
842 for (int i=0; i<size; ++i) {
843 SetInt(slots+i, i);
845 }else{
846 for (int i=0; i<size; ++i) {
847 SetInt(slots+i, first++);
850 }else{
851 int val = first;
852 for (int i=0; i<size; ++i) {
853 SetInt(slots+i, val);
854 val += step;
857 SetObject(a, obj);
858 } else {
859 double first, second, last, step;
860 err = slotDoubleVal(a, &first);
861 if (err) return err;
862 err = slotDoubleVal(c, &last);
863 if (err) return err;
864 err = slotDoubleVal(b, &second);
865 if (err) {
866 if (first < last) second = first + 1.;
867 else second = first - 1.;
870 step = second - first;
871 size = (int)floor((last - first) / step + 0.001) + 1;
872 if(size<1 || size > INT_MAX_BY_PyrSlot){
873 post("prSimpleNumberSeries: array size %i exceeds limit (%i)\n", size, INT_MAX_BY_PyrSlot);
874 return errFailed;
876 PyrObject *obj = newPyrArray(g->gc, size, 0, true);
877 obj->size = size;
878 PyrSlot *slots = obj->slots;
879 if(first==0. && step==1.){
880 // Faster iteration for common case
881 for (long i=0; i<size; ++i) {
882 SetFloat(slots+i, i);
884 }else{
885 double val = first;
886 for (long i=0; i<size; ++i) {
887 val = first + step * i;
888 SetFloat(slots+i, val);
891 SetObject(a, obj);
893 return errNone;
899 asFraction {|maxDenominator=100|
900 var mediant, lower, upper, temp;
901 var n,d, k, k1;
902 if (this < 0) {
903 #n, d = this.neg.asFraction(maxDenominator);
904 ^[n.neg, d]
906 if (this < 1.0) {
907 upper = [1.0, this.reciprocal.floor];
908 lower = [1.0, upper[1]+1.0];
910 lower = [this.floor, 1.0];
911 upper = [lower[0]+1.0, 1.0];
913 mediant = [lower[0] + upper[0], lower[1] + upper[1]];
914 loop {
915 mediant = [lower[0] + upper[0], lower[1] + upper[1]];
916 case
917 { (this * mediant[1]) > mediant[0] }
919 if (maxDenominator < mediant[1]) {^upper};
920 d = upper[0] - (this * upper[1]);
921 if (d == 0) {^upper};
922 lower = mediant;
923 k = floor(((this * lower[1]) - lower[0]) / d);
924 k1 = k + 1;
925 temp = [lower[0] + (k1 * upper[0]), lower[1] + (k1 * upper[1])];
926 lower = [lower[0] + (k * upper[0]), lower[1] + (k * upper[1])];
927 upper = temp;
929 { (this * mediant[1]) == mediant[0] }
931 if (maxDenominator >= mediant[1]) {^mediant};
932 if (lower[1] < upper[1]) {^lower};
933 ^upper
936 if (maxDenominator < mediant[1]) {^lower};
937 d = lower[0] - (this * lower[1]);
938 if (d == 0) {^lower};
939 upper = mediant;
940 k = floor(((this * upper[1]) - upper[0]) / d);
941 k1 = k + 1;
942 temp = [(k1 * lower[0]) + upper[0], (k1 * lower[1]) + upper[1]];
943 upper = [(k * lower[0]) + upper[0], (k * lower[1]) + upper[1]];
944 lower = temp;
951 int prAsFraction(struct VMGlobals *g, int numArgsPushed)
953 PyrSlot *a = g->sp - 2;
954 PyrSlot *b = g->sp - 1;
955 PyrSlot *c = g->sp;
957 double mediant_num, lower_num, upper_num, temp_num;
958 double mediant_den, lower_den, upper_den, temp_den;
959 double x, d;
960 int k, k1;
961 int maxDenominator;
962 int err;
963 bool neg = false;
965 err = slotDoubleVal(a, &x);
966 if (err) return err;
968 err = slotIntVal(b, &maxDenominator);
969 if (err) return err;
971 bool faster = IsTrue(c);
973 PyrObject *obj = newPyrArray(g->gc, 2, 0, true);
974 obj->size = 2;
975 PyrSlot *slots = obj->slots;
976 SetObject(a, obj);
978 if (x < 0.0) {
979 x = -x;
980 neg = true;
983 if (x == 0.0) {
984 SetInt(slots+0, 0);
985 SetInt(slots+1, 1);
986 return errNone;
989 if (x < 1.0) {
990 upper_num = 1.0;
991 upper_den = floor(1./x);
992 lower_num = 1.0;
993 lower_den = upper_den + 1.;
994 } else {
995 lower_num = floor(x);
996 lower_den = 1.0;
997 upper_num = lower_num + 1.;
998 upper_den = 1.0;
1001 while (true) {
1002 mediant_num = lower_num + upper_num;
1003 mediant_den = lower_den + upper_den;
1004 //post(" md %g %g %g %g %g %g\n", mediant_num, mediant_den, lower_num, lower_den, upper_num, upper_den);
1006 if (x * mediant_den > mediant_num) {
1007 d = upper_num - (x * upper_den);
1008 if (maxDenominator < mediant_den || fabs(d) < 1e-5) {
1009 if (neg) upper_num = -upper_num;
1010 SetInt(slots+0, (int)upper_num);
1011 SetInt(slots+1, (int)upper_den);
1012 return errNone;
1014 lower_num = mediant_num;
1015 lower_den = mediant_den;
1016 if (faster) {
1017 k = (int)floor(((x * lower_den) - lower_num) / d);
1018 if (k < 10000) {
1019 k1 = k + 1;
1020 temp_num = lower_num + (k1 * upper_num);
1021 temp_den = lower_den + (k1 * upper_den);
1022 lower_num = lower_num + (k * upper_num);
1023 lower_den = lower_den + (k * upper_den);
1024 upper_num = temp_num;
1025 upper_den = temp_den;
1028 } else if (x * mediant_den == mediant_num) {
1029 if (maxDenominator >= mediant_den) {
1030 if (neg) mediant_num = -mediant_num;
1031 SetInt(slots+0, (int)mediant_num);
1032 SetInt(slots+1, (int)mediant_den);
1033 return errNone;
1034 } else if (lower_den < upper_den) {
1035 if (neg) lower_num = -lower_num;
1036 SetInt(slots+0, (int)lower_num);
1037 SetInt(slots+1, (int)lower_den);
1038 return errNone;
1039 } else {
1040 if (neg) upper_num = -upper_num;
1041 SetInt(slots+0, (int)upper_num);
1042 SetInt(slots+1, (int)upper_den);
1043 return errNone;
1045 } else {
1046 d = lower_num - (x * lower_den);
1047 if (maxDenominator < mediant_den || fabs(d) < 1e-5) {
1048 if (neg) lower_num = -lower_num;
1049 SetInt(slots+0, (int)lower_num);
1050 SetInt(slots+1, (int)lower_den);
1051 return errNone;
1053 upper_num = mediant_num;
1054 upper_den = mediant_den;
1055 if (faster) {
1056 k = (int)floor(((x * upper_den) - upper_num) / d);
1057 if (k < 10000) {
1058 k1 = k + 1;
1059 temp_num = (k1 * lower_num) + upper_num;
1060 temp_den = (k1 * lower_den) + upper_den;
1061 upper_num = (k * lower_num) + upper_num;
1062 upper_den = (k * lower_den) + upper_den;
1063 lower_num = temp_num;
1064 lower_den = temp_den;
1071 void initMathPrimitives()
1073 int base, index;
1075 base = nextPrimitiveIndex();
1076 index = 0;
1077 definePrimitive(base, index++, "_AddInt", prAddInt, 2, 0);
1078 definePrimitive(base, index++, "_SubInt", prSubInt, 2, 0);
1079 definePrimitive(base, index++, "_MulInt", prMulInt, 2, 0);
1080 definePrimitive(base, index++, "_AddFloat", prAddFloat, 2, 0);
1081 definePrimitive(base, index++, "_SubFloat", prSubFloat, 2, 0);
1082 definePrimitive(base, index++, "_MulFloat", prMulFloat, 2, 0);
1083 definePrimitive(base, index++, "_NthPrime", prNthPrime, 1, 0);
1084 definePrimitive(base, index++, "_PrevPrime", prPrevPrime, 1, 0);
1085 definePrimitive(base, index++, "_NextPrime", prNextPrime, 1, 0);
1086 definePrimitive(base, index++, "_IsPrime", prIsPrime, 1, 0);
1087 definePrimitive(base, index++, "_IndexOfPrime", prIndexOfPrime, 1, 0);
1088 definePrimitive(base, index++, "_As32Bits", prAs32Bits, 1, 0);
1089 definePrimitive(base, index++, "_High32Bits", prHigh32Bits, 1, 0);
1090 definePrimitive(base, index++, "_Low32Bits", prLow32Bits, 1, 0);
1091 definePrimitive(base, index++, "_From32Bits", prFrom32Bits, 2, 0);
1092 definePrimitive(base, index++, "_From64Bits", prFrom64Bits, 3, 0);
1094 definePrimitive(base, index++, "_ClipInt", mathClipInt, 3, 0);
1095 definePrimitive(base, index++, "_ClipFloat", mathClipFloat, 3, 0);
1096 definePrimitive(base, index++, "_ClipSignal", mathClipSignal, 3, 0);
1097 definePrimitive(base, index++, "_WrapInt", mathWrapInt, 3, 0);
1098 definePrimitive(base, index++, "_WrapFloat", mathWrapFloat, 3, 0);
1099 definePrimitive(base, index++, "_WrapSignal", mathWrapSignal, 3, 0);
1100 definePrimitive(base, index++, "_FoldInt", mathFoldInt, 3, 0);
1101 definePrimitive(base, index++, "_FoldFloat", mathFoldFloat, 3, 0);
1102 definePrimitive(base, index++, "_FoldSignal", mathFoldSignal, 3, 0);
1104 definePrimitive(base, index++, "_SimpleNumberSeries", prSimpleNumberSeries, 3, 0);
1105 definePrimitive(base, index++, "_AsFraction", prAsFraction, 3, 0);