]> gitweb.factorcode.org Git - factor.git/blob - vm/math.cpp
removed a bunch of superflous blank lines
[factor.git] / vm / math.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 inline void factorvm::primitive_bignum_to_fixnum()
7 {
8         drepl(tag_fixnum(bignum_to_fixnum(untag<bignum>(dpeek()))));
9 }
10
11 PRIMITIVE(bignum_to_fixnum)
12 {
13         PRIMITIVE_GETVM()->primitive_bignum_to_fixnum();
14 }
15
16 inline void factorvm::primitive_float_to_fixnum()
17 {
18         drepl(tag_fixnum(float_to_fixnum(dpeek())));
19 }
20
21 PRIMITIVE(float_to_fixnum)
22 {
23         PRIMITIVE_GETVM()->primitive_float_to_fixnum();
24 }
25
26 /* Division can only overflow when we are dividing the most negative fixnum
27 by -1. */
28 inline void factorvm::primitive_fixnum_divint()
29 {
30         fixnum y = untag_fixnum(dpop()); \
31         fixnum x = untag_fixnum(dpeek());
32         fixnum result = x / y;
33         if(result == -fixnum_min)
34                 drepl(allot_integer(-fixnum_min));
35         else
36                 drepl(tag_fixnum(result));
37 }
38
39 PRIMITIVE(fixnum_divint)
40 {
41         PRIMITIVE_GETVM()->primitive_fixnum_divint();
42 }
43
44 inline void factorvm::primitive_fixnum_divmod()
45 {
46         cell y = ((cell *)ds)[0];
47         cell x = ((cell *)ds)[-1];
48         if(y == tag_fixnum(-1) && x == tag_fixnum(fixnum_min))
49         {
50                 ((cell *)ds)[-1] = allot_integer(-fixnum_min);
51                 ((cell *)ds)[0] = tag_fixnum(0);
52         }
53         else
54         {
55                 ((cell *)ds)[-1] = tag_fixnum(untag_fixnum(x) / untag_fixnum(y));
56                 ((cell *)ds)[0] = (fixnum)x % (fixnum)y;
57         }
58 }
59
60 PRIMITIVE(fixnum_divmod)
61 {
62         PRIMITIVE_GETVM()->primitive_fixnum_divmod();
63 }
64
65 /*
66  * If we're shifting right by n bits, we won't overflow as long as none of the
67  * high WORD_SIZE-TAG_BITS-n bits are set.
68  */
69 inline fixnum factorvm::sign_mask(fixnum x)
70 {
71         return x >> (WORD_SIZE - 1);
72 }
73
74 inline fixnum factorvm::branchless_max(fixnum x, fixnum y)
75 {
76         return (x - ((x - y) & sign_mask(x - y)));
77 }
78
79 inline fixnum factorvm::branchless_abs(fixnum x)
80 {
81         return (x ^ sign_mask(x)) - sign_mask(x);
82 }
83
84 inline void factorvm::primitive_fixnum_shift()
85 {
86         fixnum y = untag_fixnum(dpop());
87         fixnum x = untag_fixnum(dpeek());
88
89         if(x == 0)
90                 return;
91         else if(y < 0)
92         {
93                 y = branchless_max(y,-WORD_SIZE + 1);
94                 drepl(tag_fixnum(x >> -y));
95                 return;
96         }
97         else if(y < WORD_SIZE - TAG_BITS)
98         {
99                 fixnum mask = -((fixnum)1 << (WORD_SIZE - 1 - TAG_BITS - y));
100                 if(!(branchless_abs(x) & mask))
101                 {
102                         drepl(tag_fixnum(x << y));
103                         return;
104                 }
105         }
106
107         drepl(tag<bignum>(bignum_arithmetic_shift(
108                 fixnum_to_bignum(x),y)));
109 }
110
111 PRIMITIVE(fixnum_shift)
112 {
113         PRIMITIVE_GETVM()->primitive_fixnum_shift();
114 }
115
116 inline void factorvm::primitive_fixnum_to_bignum()
117 {
118         drepl(tag<bignum>(fixnum_to_bignum(untag_fixnum(dpeek()))));
119 }
120
121 PRIMITIVE(fixnum_to_bignum)
122 {
123         PRIMITIVE_GETVM()->primitive_fixnum_to_bignum();
124 }
125
126 inline void factorvm::primitive_float_to_bignum()
127 {
128         drepl(tag<bignum>(float_to_bignum(dpeek())));
129 }
130
131 PRIMITIVE(float_to_bignum)
132 {
133         PRIMITIVE_GETVM()->primitive_float_to_bignum();
134 }
135
136 #define POP_BIGNUMS(x,y) \
137         bignum * y = untag<bignum>(dpop()); \
138         bignum * x = untag<bignum>(dpop());
139
140 inline void factorvm::primitive_bignum_eq()
141 {
142         POP_BIGNUMS(x,y);
143         box_boolean(bignum_equal_p(x,y));
144 }
145
146 PRIMITIVE(bignum_eq)
147 {
148         PRIMITIVE_GETVM()->primitive_bignum_eq();
149 }
150
151 inline void factorvm::primitive_bignum_add()
152 {
153         POP_BIGNUMS(x,y);
154         dpush(tag<bignum>(bignum_add(x,y)));
155 }
156
157 PRIMITIVE(bignum_add)
158 {
159         PRIMITIVE_GETVM()->primitive_bignum_add();
160 }
161
162 inline void factorvm::primitive_bignum_subtract()
163 {
164         POP_BIGNUMS(x,y);
165         dpush(tag<bignum>(bignum_subtract(x,y)));
166 }
167
168 PRIMITIVE(bignum_subtract)
169 {
170         PRIMITIVE_GETVM()->primitive_bignum_subtract();
171 }
172
173 inline void factorvm::primitive_bignum_multiply()
174 {
175         POP_BIGNUMS(x,y);
176         dpush(tag<bignum>(bignum_multiply(x,y)));
177 }
178
179 PRIMITIVE(bignum_multiply)
180 {
181         PRIMITIVE_GETVM()->primitive_bignum_multiply();
182 }
183
184 inline void factorvm::primitive_bignum_divint()
185 {
186         POP_BIGNUMS(x,y);
187         dpush(tag<bignum>(bignum_quotient(x,y)));
188 }
189
190 PRIMITIVE(bignum_divint)
191 {
192         PRIMITIVE_GETVM()->primitive_bignum_divint();
193 }
194
195 inline void factorvm::primitive_bignum_divmod()
196 {
197         bignum *q, *r;
198         POP_BIGNUMS(x,y);
199         bignum_divide(x,y,&q,&r);
200         dpush(tag<bignum>(q));
201         dpush(tag<bignum>(r));
202 }
203
204 PRIMITIVE(bignum_divmod)
205 {
206         PRIMITIVE_GETVM()->primitive_bignum_divmod();
207 }
208
209 inline void factorvm::primitive_bignum_mod()
210 {
211         POP_BIGNUMS(x,y);
212         dpush(tag<bignum>(bignum_remainder(x,y)));
213 }
214
215 PRIMITIVE(bignum_mod)
216 {
217         PRIMITIVE_GETVM()->primitive_bignum_mod();
218 }
219
220 inline void factorvm::primitive_bignum_and()
221 {
222         POP_BIGNUMS(x,y);
223         dpush(tag<bignum>(bignum_bitwise_and(x,y)));
224 }
225
226 PRIMITIVE(bignum_and)
227 {
228         PRIMITIVE_GETVM()->primitive_bignum_and();
229 }
230
231 inline void factorvm::primitive_bignum_or()
232 {
233         POP_BIGNUMS(x,y);
234         dpush(tag<bignum>(bignum_bitwise_ior(x,y)));
235 }
236
237 PRIMITIVE(bignum_or)
238 {
239         PRIMITIVE_GETVM()->primitive_bignum_or();
240 }
241
242 inline void factorvm::primitive_bignum_xor()
243 {
244         POP_BIGNUMS(x,y);
245         dpush(tag<bignum>(bignum_bitwise_xor(x,y)));
246 }
247
248 PRIMITIVE(bignum_xor)
249 {
250         PRIMITIVE_GETVM()->primitive_bignum_xor();
251 }
252
253 inline void factorvm::primitive_bignum_shift()
254 {
255         fixnum y = untag_fixnum(dpop());
256         bignum* x = untag<bignum>(dpop());
257         dpush(tag<bignum>(bignum_arithmetic_shift(x,y)));
258 }
259
260 PRIMITIVE(bignum_shift)
261 {
262         PRIMITIVE_GETVM()->primitive_bignum_shift();
263 }
264
265 inline void factorvm::primitive_bignum_less()
266 {
267         POP_BIGNUMS(x,y);
268         box_boolean(bignum_compare(x,y) == bignum_comparison_less);
269 }
270
271 PRIMITIVE(bignum_less)
272 {
273         PRIMITIVE_GETVM()->primitive_bignum_less();
274 }
275
276 inline void factorvm::primitive_bignum_lesseq()
277 {
278         POP_BIGNUMS(x,y);
279         box_boolean(bignum_compare(x,y) != bignum_comparison_greater);
280 }
281
282 PRIMITIVE(bignum_lesseq)
283 {
284         PRIMITIVE_GETVM()->primitive_bignum_lesseq();
285 }
286
287 inline void factorvm::primitive_bignum_greater()
288 {
289         POP_BIGNUMS(x,y);
290         box_boolean(bignum_compare(x,y) == bignum_comparison_greater);
291 }
292
293 PRIMITIVE(bignum_greater)
294 {
295         PRIMITIVE_GETVM()->primitive_bignum_greater();
296 }
297
298 inline void factorvm::primitive_bignum_greatereq()
299 {
300         POP_BIGNUMS(x,y);
301         box_boolean(bignum_compare(x,y) != bignum_comparison_less);
302 }
303
304 PRIMITIVE(bignum_greatereq)
305 {
306         PRIMITIVE_GETVM()->primitive_bignum_greatereq();
307 }
308
309 inline void factorvm::primitive_bignum_not()
310 {
311         drepl(tag<bignum>(bignum_bitwise_not(untag<bignum>(dpeek()))));
312 }
313
314 PRIMITIVE(bignum_not)
315 {
316         PRIMITIVE_GETVM()->primitive_bignum_not();
317 }
318
319 inline void factorvm::primitive_bignum_bitp()
320 {
321         fixnum bit = to_fixnum(dpop());
322         bignum *x = untag<bignum>(dpop());
323         box_boolean(bignum_logbitp(bit,x));
324 }
325
326 PRIMITIVE(bignum_bitp)
327 {
328         PRIMITIVE_GETVM()->primitive_bignum_bitp();
329 }
330
331 inline void factorvm::primitive_bignum_log2()
332 {
333         drepl(tag<bignum>(bignum_integer_length(untag<bignum>(dpeek()))));
334 }
335
336 PRIMITIVE(bignum_log2)
337 {
338         PRIMITIVE_GETVM()->primitive_bignum_log2();
339 }
340
341 unsigned int factorvm::bignum_producer(unsigned int digit)
342 {
343         unsigned char *ptr = (unsigned char *)alien_offset(dpeek());
344         return *(ptr + digit);
345 }
346
347 unsigned int bignum_producer(unsigned int digit, factorvm *myvm)
348 {
349         return myvm->bignum_producer(digit);
350 }
351
352 inline void factorvm::primitive_byte_array_to_bignum()
353 {
354         cell n_digits = array_capacity(untag_check<byte_array>(dpeek()));
355         bignum * result = digit_stream_to_bignum(n_digits,factor::bignum_producer,0x100,0);
356         drepl(tag<bignum>(result));
357 }
358
359 PRIMITIVE(byte_array_to_bignum)
360 {
361         PRIMITIVE_GETVM()->primitive_byte_array_to_bignum();
362 }
363
364 cell factorvm::unbox_array_size()
365 {
366         switch(tagged<object>(dpeek()).type())
367         {
368         case FIXNUM_TYPE:
369                 {
370                         fixnum n = untag_fixnum(dpeek());
371                         if(n >= 0 && n < (fixnum)array_size_max)
372                         {
373                                 dpop();
374                                 return n;
375                         }
376                         break;
377                 }
378         case BIGNUM_TYPE:
379                 {
380                         bignum * zero = untag<bignum>(bignum_zero);
381                         bignum * max = cell_to_bignum(array_size_max);
382                         bignum * n = untag<bignum>(dpeek());
383                         if(bignum_compare(n,zero) != bignum_comparison_less
384                                 && bignum_compare(n,max) == bignum_comparison_less)
385                         {
386                                 dpop();
387                                 return bignum_to_cell(n);
388                         }
389                         break;
390                 }
391         }
392
393         general_error(ERROR_ARRAY_SIZE,dpop(),tag_fixnum(array_size_max),NULL);
394         return 0; /* can't happen */
395 }
396
397 inline void factorvm::primitive_fixnum_to_float()
398 {
399         drepl(allot_float(fixnum_to_float(dpeek())));
400 }
401
402 PRIMITIVE(fixnum_to_float)
403 {
404         PRIMITIVE_GETVM()->primitive_fixnum_to_float();
405 }
406
407 inline void factorvm::primitive_bignum_to_float()
408 {
409         drepl(allot_float(bignum_to_float(dpeek())));
410 }
411
412 PRIMITIVE(bignum_to_float)
413 {
414         PRIMITIVE_GETVM()->primitive_bignum_to_float();
415 }
416
417 inline void factorvm::primitive_str_to_float()
418 {
419         byte_array *bytes = untag_check<byte_array>(dpeek());
420         cell capacity = array_capacity(bytes);
421
422         char *c_str = (char *)(bytes + 1);
423         char *end = c_str;
424         double f = strtod(c_str,&end);
425         if(end == c_str + capacity - 1)
426                 drepl(allot_float(f));
427         else
428                 drepl(F);
429 }
430
431 PRIMITIVE(str_to_float)
432 {
433         PRIMITIVE_GETVM()->primitive_str_to_float();
434 }
435
436 inline void factorvm::primitive_float_to_str()
437 {
438         byte_array *array = allot_byte_array(33);
439         snprintf((char *)(array + 1),32,"%.16g",untag_float_check(dpop()));
440         dpush(tag<byte_array>(array));
441 }
442
443 PRIMITIVE(float_to_str)
444 {
445         PRIMITIVE_GETVM()->primitive_float_to_str();
446 }
447
448 #define POP_FLOATS(x,y) \
449         double y = untag_float(dpop()); \
450         double x = untag_float(dpop());
451
452 inline void factorvm::primitive_float_eq()
453 {
454         POP_FLOATS(x,y);
455         box_boolean(x == y);
456 }
457
458 PRIMITIVE(float_eq)
459 {
460         PRIMITIVE_GETVM()->primitive_float_eq();
461 }
462
463 inline void factorvm::primitive_float_add()
464 {
465         POP_FLOATS(x,y);
466         box_double(x + y);
467 }
468
469 PRIMITIVE(float_add)
470 {
471         PRIMITIVE_GETVM()->primitive_float_add();
472 }
473
474 inline void factorvm::primitive_float_subtract()
475 {
476         POP_FLOATS(x,y);
477         box_double(x - y);
478 }
479
480 PRIMITIVE(float_subtract)
481 {
482         PRIMITIVE_GETVM()->primitive_float_subtract();
483 }
484
485 inline void factorvm::primitive_float_multiply()
486 {
487         POP_FLOATS(x,y);
488         box_double(x * y);
489 }
490
491 PRIMITIVE(float_multiply)
492 {
493         PRIMITIVE_GETVM()->primitive_float_multiply();
494 }
495
496 inline void factorvm::primitive_float_divfloat()
497 {
498         POP_FLOATS(x,y);
499         box_double(x / y);
500 }
501
502 PRIMITIVE(float_divfloat)
503 {
504         PRIMITIVE_GETVM()->primitive_float_divfloat();
505 }
506
507 inline void factorvm::primitive_float_mod()
508 {
509         POP_FLOATS(x,y);
510         box_double(fmod(x,y));
511 }
512
513 PRIMITIVE(float_mod)
514 {
515         PRIMITIVE_GETVM()->primitive_float_mod();
516 }
517
518 inline void factorvm::primitive_float_less()
519 {
520         POP_FLOATS(x,y);
521         box_boolean(x < y);
522 }
523
524 PRIMITIVE(float_less)
525 {
526         PRIMITIVE_GETVM()->primitive_float_less();
527 }
528
529 inline void factorvm::primitive_float_lesseq()
530 {
531         POP_FLOATS(x,y);
532         box_boolean(x <= y);
533 }
534
535 PRIMITIVE(float_lesseq)
536 {
537         PRIMITIVE_GETVM()->primitive_float_lesseq();
538 }
539
540 inline void factorvm::primitive_float_greater()
541 {
542         POP_FLOATS(x,y);
543         box_boolean(x > y);
544 }
545
546 PRIMITIVE(float_greater)
547 {
548         PRIMITIVE_GETVM()->primitive_float_greater();
549 }
550
551 inline void factorvm::primitive_float_greatereq()
552 {
553         POP_FLOATS(x,y);
554         box_boolean(x >= y);
555 }
556
557 PRIMITIVE(float_greatereq)
558 {
559         PRIMITIVE_GETVM()->primitive_float_greatereq();
560 }
561
562 inline void factorvm::primitive_float_bits()
563 {
564         box_unsigned_4(float_bits(untag_float_check(dpop())));
565 }
566
567 PRIMITIVE(float_bits)
568 {
569         PRIMITIVE_GETVM()->primitive_float_bits();
570 }
571
572 inline void factorvm::primitive_bits_float()
573 {
574         box_float(bits_float(to_cell(dpop())));
575 }
576
577 PRIMITIVE(bits_float)
578 {
579         PRIMITIVE_GETVM()->primitive_bits_float();
580 }
581
582 inline void factorvm::primitive_double_bits()
583 {
584         box_unsigned_8(double_bits(untag_float_check(dpop())));
585 }
586
587 PRIMITIVE(double_bits)
588 {
589         PRIMITIVE_GETVM()->primitive_double_bits();
590 }
591
592 inline void factorvm::primitive_bits_double()
593 {
594         box_double(bits_double(to_unsigned_8(dpop())));
595 }
596
597 PRIMITIVE(bits_double)
598 {
599         PRIMITIVE_GETVM()->primitive_bits_double();
600 }
601
602 fixnum factorvm::to_fixnum(cell tagged)
603 {
604         switch(TAG(tagged))
605         {
606         case FIXNUM_TYPE:
607                 return untag_fixnum(tagged);
608         case BIGNUM_TYPE:
609                 return bignum_to_fixnum(untag<bignum>(tagged));
610         default:
611                 type_error(FIXNUM_TYPE,tagged);
612                 return 0; /* can't happen */
613         }
614 }
615
616 VM_C_API fixnum to_fixnum(cell tagged,factorvm *myvm)
617 {
618         ASSERTVM();
619         return VM_PTR->to_fixnum(tagged);
620 }
621
622 cell factorvm::to_cell(cell tagged)
623 {
624         return (cell)to_fixnum(tagged);
625 }
626
627 VM_C_API cell to_cell(cell tagged, factorvm *myvm)
628 {
629         ASSERTVM();
630         return VM_PTR->to_cell(tagged);
631 }
632
633 void factorvm::box_signed_1(s8 n)
634 {
635         dpush(tag_fixnum(n));
636 }
637
638 VM_C_API void box_signed_1(s8 n,factorvm *myvm)
639 {
640         ASSERTVM();
641         return VM_PTR->box_signed_1(n);
642 }
643
644 void factorvm::box_unsigned_1(u8 n)
645 {
646         dpush(tag_fixnum(n));
647 }
648
649 VM_C_API void box_unsigned_1(u8 n,factorvm *myvm)
650 {
651         ASSERTVM();
652         return VM_PTR->box_unsigned_1(n);
653 }
654
655 void factorvm::box_signed_2(s16 n)
656 {
657         dpush(tag_fixnum(n));
658 }
659
660 VM_C_API void box_signed_2(s16 n,factorvm *myvm)
661 {
662         ASSERTVM();
663         return VM_PTR->box_signed_2(n);
664 }
665
666 void factorvm::box_unsigned_2(u16 n)
667 {
668         dpush(tag_fixnum(n));
669 }
670
671 VM_C_API void box_unsigned_2(u16 n,factorvm *myvm)
672 {
673         ASSERTVM();
674         return VM_PTR->box_unsigned_2(n);
675 }
676
677 void factorvm::box_signed_4(s32 n)
678 {
679         dpush(allot_integer(n));
680 }
681
682 VM_C_API void box_signed_4(s32 n,factorvm *myvm)
683 {
684         ASSERTVM();
685         return VM_PTR->box_signed_4(n);
686 }
687
688 void factorvm::box_unsigned_4(u32 n)
689 {
690         dpush(allot_cell(n));
691 }
692
693 VM_C_API void box_unsigned_4(u32 n,factorvm *myvm)
694 {
695         ASSERTVM();
696         return VM_PTR->box_unsigned_4(n);
697 }
698
699 void factorvm::box_signed_cell(fixnum integer)
700 {
701         dpush(allot_integer(integer));
702 }
703
704 VM_C_API void box_signed_cell(fixnum integer,factorvm *myvm)
705 {
706         ASSERTVM();
707         return VM_PTR->box_signed_cell(integer);
708 }
709
710 void factorvm::box_unsigned_cell(cell cell)
711 {
712         dpush(allot_cell(cell));
713 }
714
715 VM_C_API void box_unsigned_cell(cell cell,factorvm *myvm)
716 {
717         ASSERTVM();
718         return VM_PTR->box_unsigned_cell(cell);
719 }
720
721 void factorvm::box_signed_8(s64 n)
722 {
723         if(n < fixnum_min || n > fixnum_max)
724                 dpush(tag<bignum>(long_long_to_bignum(n)));
725         else
726                 dpush(tag_fixnum(n));
727 }
728
729 VM_C_API void box_signed_8(s64 n,factorvm *myvm)
730 {
731         ASSERTVM();
732         return VM_PTR->box_signed_8(n);
733 }
734
735 s64 factorvm::to_signed_8(cell obj)
736 {
737         switch(tagged<object>(obj).type())
738         {
739         case FIXNUM_TYPE:
740                 return untag_fixnum(obj);
741         case BIGNUM_TYPE:
742                 return bignum_to_long_long(untag<bignum>(obj));
743         default:
744                 type_error(BIGNUM_TYPE,obj);
745                 return 0;
746         }
747 }
748
749 VM_C_API s64 to_signed_8(cell obj,factorvm *myvm)
750 {
751         ASSERTVM();
752         return VM_PTR->to_signed_8(obj);
753 }
754
755 void factorvm::box_unsigned_8(u64 n)
756 {
757         if(n > (u64)fixnum_max)
758                 dpush(tag<bignum>(ulong_long_to_bignum(n)));
759         else
760                 dpush(tag_fixnum(n));
761 }
762
763 VM_C_API void box_unsigned_8(u64 n,factorvm *myvm)
764 {
765         ASSERTVM();
766         return VM_PTR->box_unsigned_8(n);
767 }
768
769 u64 factorvm::to_unsigned_8(cell obj)
770 {
771         switch(tagged<object>(obj).type())
772         {
773         case FIXNUM_TYPE:
774                 return untag_fixnum(obj);
775         case BIGNUM_TYPE:
776                 return bignum_to_ulong_long(untag<bignum>(obj));
777         default:
778                 type_error(BIGNUM_TYPE,obj);
779                 return 0;
780         }
781 }
782
783 VM_C_API u64 to_unsigned_8(cell obj,factorvm *myvm)
784 {
785         ASSERTVM();
786         return VM_PTR->to_unsigned_8(obj);
787 }
788  
789 void factorvm::box_float(float flo)
790 {
791         dpush(allot_float(flo));
792 }
793
794 VM_C_API void box_float(float flo, factorvm *myvm)
795 {
796         ASSERTVM();
797         return VM_PTR->box_float(flo);
798 }
799
800 float factorvm::to_float(cell value)
801 {
802         return untag_float_check(value);
803 }
804
805 VM_C_API float to_float(cell value,factorvm *myvm)
806 {
807         ASSERTVM();
808         return VM_PTR->to_float(value);
809 }
810
811 void factorvm::box_double(double flo)
812 {
813         dpush(allot_float(flo));
814 }
815
816 VM_C_API void box_double(double flo,factorvm *myvm)
817 {
818         ASSERTVM();
819         return VM_PTR->box_double(flo);
820 }
821
822 double factorvm::to_double(cell value)
823 {
824         return untag_float_check(value);
825 }
826
827 VM_C_API double to_double(cell value,factorvm *myvm)
828 {
829         ASSERTVM();
830         return VM_PTR->to_double(value);
831 }
832
833 /* The fixnum+, fixnum- and fixnum* primitives are defined in cpu_*.S. On
834 overflow, they call these functions. */
835 inline void factorvm::overflow_fixnum_add(fixnum x, fixnum y)
836 {
837         drepl(tag<bignum>(fixnum_to_bignum(
838                 untag_fixnum(x) + untag_fixnum(y))));
839 }
840
841 VM_ASM_API_OVERFLOW void overflow_fixnum_add(fixnum x, fixnum y, factorvm *myvm)
842 {
843         PRIMITIVE_OVERFLOW_GETVM()->overflow_fixnum_add(x,y);
844 }
845
846 inline void factorvm::overflow_fixnum_subtract(fixnum x, fixnum y)
847 {
848         drepl(tag<bignum>(fixnum_to_bignum(
849                 untag_fixnum(x) - untag_fixnum(y))));
850 }
851
852 VM_ASM_API_OVERFLOW void overflow_fixnum_subtract(fixnum x, fixnum y, factorvm *myvm)
853 {
854         PRIMITIVE_OVERFLOW_GETVM()->overflow_fixnum_subtract(x,y);
855 }
856
857 inline void factorvm::overflow_fixnum_multiply(fixnum x, fixnum y)
858 {
859         bignum *bx = fixnum_to_bignum(x);
860         GC_BIGNUM(bx,this);
861         bignum *by = fixnum_to_bignum(y);
862         GC_BIGNUM(by,this);
863         drepl(tag<bignum>(bignum_multiply(bx,by)));
864 }
865
866 VM_ASM_API_OVERFLOW void overflow_fixnum_multiply(fixnum x, fixnum y, factorvm *myvm)
867 {
868         PRIMITIVE_OVERFLOW_GETVM()->overflow_fixnum_multiply(x,y);
869 }
870
871 }