2 Copyright (C) 1989-94 Massachusetts Institute of Technology
3 Portions copyright (C) 2004-2008 Slava Pestov
5 This material was developed by the Scheme project at the Massachusetts
6 Institute of Technology, Department of Electrical Engineering and
7 Computer Science. Permission to copy and modify this software, to
8 redistribute either the original software or a modified version, and
9 to use this software for any purpose is granted, subject to the
10 following restrictions and understandings.
12 1. Any copy made of this software must include this copyright notice
15 2. Users of this software agree to make their best efforts (a) to
16 return to the MIT Scheme project any improvements or extensions that
17 they make, so that these may be included in future releases; and (b)
18 to inform MIT of noteworthy uses of this software.
20 3. All materials developed as a consequence of the use of this
21 software shall duly acknowledge such use, in accordance with the usual
22 standards of acknowledging credit in academic research.
24 4. MIT has made no warrantee or representation that the operation of
25 this software will be error-free, and MIT is under no obligation to
26 provide any services, by way of maintenance, update, or otherwise.
28 5. In conjunction with products arising from the use of this material,
29 there shall be no use of the name of the Massachusetts Institute of
30 Technology nor of any adaptation thereof in any advertising,
31 promotional, or sales literature without prior written consent from
34 /* Changes for Scheme 48:
35 * - Converted to ANSI.
36 * - Added bitwise operations.
37 * - Added s48 to the beginning of all externally visible names.
38 * - Cached the bignum representations of -1, 0, and 1.
41 /* Changes for Factor:
42 * - Adapt bignumint.h for Factor memory manager
43 * - Add more bignum <-> C type conversions
44 * - Remove unused functions
45 * - Add local variable GC root recording
46 * - Remove s48 prefix from function names
47 * - Various fixes for Win64
58 int factor_vm::bignum_equal_p(bignum * x, bignum * y)
63 : ((! (BIGNUM_ZERO_P (y)))
64 && ((BIGNUM_NEGATIVE_P (x))
65 ? (BIGNUM_NEGATIVE_P (y))
66 : (! (BIGNUM_NEGATIVE_P (y))))
67 && (bignum_equal_p_unsigned (x, y))));
70 enum bignum_comparison factor_vm::bignum_compare(bignum * x, bignum * y)
74 ? ((BIGNUM_ZERO_P (y))
75 ? bignum_comparison_equal
76 : (BIGNUM_NEGATIVE_P (y))
77 ? bignum_comparison_greater
78 : bignum_comparison_less)
80 ? ((BIGNUM_NEGATIVE_P (x))
81 ? bignum_comparison_less
82 : bignum_comparison_greater)
83 : (BIGNUM_NEGATIVE_P (x))
84 ? ((BIGNUM_NEGATIVE_P (y))
85 ? (bignum_compare_unsigned (y, x))
86 : (bignum_comparison_less))
87 : ((BIGNUM_NEGATIVE_P (y))
88 ? (bignum_comparison_greater)
89 : (bignum_compare_unsigned (x, y))));
92 /* allocates memory */
93 bignum *factor_vm::bignum_add(bignum * x, bignum * y)
100 : ((BIGNUM_NEGATIVE_P (x))
101 ? ((BIGNUM_NEGATIVE_P (y))
102 ? (bignum_add_unsigned (x, y, 1))
103 : (bignum_subtract_unsigned (y, x)))
104 : ((BIGNUM_NEGATIVE_P (y))
105 ? (bignum_subtract_unsigned (x, y))
106 : (bignum_add_unsigned (x, y, 0)))));
109 /* allocates memory */
110 bignum *factor_vm::bignum_subtract(bignum * x, bignum * y)
114 ? ((BIGNUM_ZERO_P (y))
116 : (bignum_new_sign (y, (! (BIGNUM_NEGATIVE_P (y))))))
117 : ((BIGNUM_ZERO_P (y))
119 : ((BIGNUM_NEGATIVE_P (x))
120 ? ((BIGNUM_NEGATIVE_P (y))
121 ? (bignum_subtract_unsigned (y, x))
122 : (bignum_add_unsigned (x, y, 1)))
123 : ((BIGNUM_NEGATIVE_P (y))
124 ? (bignum_add_unsigned (x, y, 0))
125 : (bignum_subtract_unsigned (x, y))))));
128 /* allocates memory */
129 bignum *factor_vm::bignum_multiply(bignum * x, bignum * y)
131 bignum_length_type x_length = (BIGNUM_LENGTH (x));
132 bignum_length_type y_length = (BIGNUM_LENGTH (y));
134 ((BIGNUM_NEGATIVE_P (x))
135 ? (! (BIGNUM_NEGATIVE_P (y)))
136 : (BIGNUM_NEGATIVE_P (y)));
137 if (BIGNUM_ZERO_P (x))
139 if (BIGNUM_ZERO_P (y))
143 bignum_digit_type digit = (BIGNUM_REF (x, 0));
145 return (bignum_maybe_new_sign (y, negative_p));
146 if (digit < BIGNUM_RADIX_ROOT)
147 return (bignum_multiply_unsigned_small_factor (y, digit, negative_p));
151 bignum_digit_type digit = (BIGNUM_REF (y, 0));
153 return (bignum_maybe_new_sign (x, negative_p));
154 if (digit < BIGNUM_RADIX_ROOT)
155 return (bignum_multiply_unsigned_small_factor (x, digit, negative_p));
157 return (bignum_multiply_unsigned (x, y, negative_p));
160 /* allocates memory */
161 void factor_vm::bignum_divide(bignum * numerator, bignum * denominator, bignum * * quotient, bignum * * remainder)
163 if (BIGNUM_ZERO_P (denominator))
165 divide_by_zero_error();
168 if (BIGNUM_ZERO_P (numerator))
170 (*quotient) = numerator;
171 (*remainder) = numerator;
175 int r_negative_p = (BIGNUM_NEGATIVE_P (numerator));
177 ((BIGNUM_NEGATIVE_P (denominator)) ? (! r_negative_p) : r_negative_p);
178 switch (bignum_compare_unsigned (numerator, denominator))
180 case bignum_comparison_equal:
182 (*quotient) = (BIGNUM_ONE (q_negative_p));
183 (*remainder) = (BIGNUM_ZERO ());
186 case bignum_comparison_less:
188 (*quotient) = (BIGNUM_ZERO ());
189 (*remainder) = numerator;
192 case bignum_comparison_greater:
194 if ((BIGNUM_LENGTH (denominator)) == 1)
196 bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
200 (bignum_maybe_new_sign (numerator, q_negative_p));
201 (*remainder) = (BIGNUM_ZERO ());
204 else if (digit < BIGNUM_RADIX_ROOT)
206 bignum_divide_unsigned_small_denominator
209 q_negative_p, r_negative_p);
214 bignum_divide_unsigned_medium_denominator
217 q_negative_p, r_negative_p);
221 bignum_divide_unsigned_large_denominator
222 (numerator, denominator,
224 q_negative_p, r_negative_p);
231 /* allocates memory */
232 bignum *factor_vm::bignum_quotient(bignum * numerator, bignum * denominator)
234 if (BIGNUM_ZERO_P (denominator))
236 divide_by_zero_error();
237 return (BIGNUM_OUT_OF_BAND);
239 if (BIGNUM_ZERO_P (numerator))
243 ((BIGNUM_NEGATIVE_P (denominator))
244 ? (! (BIGNUM_NEGATIVE_P (numerator)))
245 : (BIGNUM_NEGATIVE_P (numerator)));
246 switch (bignum_compare_unsigned (numerator, denominator))
248 case bignum_comparison_equal:
249 return (BIGNUM_ONE (q_negative_p));
250 case bignum_comparison_less:
251 return (BIGNUM_ZERO ());
252 case bignum_comparison_greater:
253 default: /* to appease gcc -Wall */
256 if ((BIGNUM_LENGTH (denominator)) == 1)
258 bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
260 return (bignum_maybe_new_sign (numerator, q_negative_p));
261 if (digit < BIGNUM_RADIX_ROOT)
262 bignum_divide_unsigned_small_denominator
264 ("ient), ((bignum * *) 0),
267 bignum_divide_unsigned_medium_denominator
269 ("ient), ((bignum * *) 0),
273 bignum_divide_unsigned_large_denominator
274 (numerator, denominator,
275 ("ient), ((bignum * *) 0),
283 /* allocates memory */
284 bignum *factor_vm::bignum_remainder(bignum * numerator, bignum * denominator)
286 if (BIGNUM_ZERO_P (denominator))
288 divide_by_zero_error();
289 return (BIGNUM_OUT_OF_BAND);
291 if (BIGNUM_ZERO_P (numerator))
293 switch (bignum_compare_unsigned (numerator, denominator))
295 case bignum_comparison_equal:
296 return (BIGNUM_ZERO ());
297 case bignum_comparison_less:
299 case bignum_comparison_greater:
300 default: /* to appease gcc -Wall */
303 if ((BIGNUM_LENGTH (denominator)) == 1)
305 bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
307 return (BIGNUM_ZERO ());
308 if (digit < BIGNUM_RADIX_ROOT)
310 (bignum_remainder_unsigned_small_denominator
311 (numerator, digit, (BIGNUM_NEGATIVE_P (numerator))));
312 bignum_divide_unsigned_medium_denominator
314 ((bignum * *) 0), (&remainder),
315 0, (BIGNUM_NEGATIVE_P (numerator)));
318 bignum_divide_unsigned_large_denominator
319 (numerator, denominator,
320 ((bignum * *) 0), (&remainder),
321 0, (BIGNUM_NEGATIVE_P (numerator)));
327 /* allocates memory */
328 #define FOO_TO_BIGNUM(name,type,stype,utype) \
329 bignum * factor_vm::name##_to_bignum(type n) \
332 bignum_digit_type result_digits [BIGNUM_DIGITS_FOR(type)]; \
333 bignum_digit_type * end_digits = result_digits; \
334 /* Special cases win when these small constants are cached. */ \
335 if (n == 0) return (BIGNUM_ZERO ()); \
336 if (n == 1) return (BIGNUM_ONE (0)); \
337 if (n < (type)0 && n == (type)-1) return (BIGNUM_ONE (1)); \
339 utype accumulator = ((negative_p = (n < (type)0)) ? ((type)(-(stype)n)) : n); \
342 (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK); \
343 accumulator >>= BIGNUM_DIGIT_LENGTH; \
345 while (accumulator != 0); \
349 (allot_bignum ((end_digits - result_digits), negative_p)); \
350 bignum_digit_type * scan_digits = result_digits; \
351 bignum_digit_type * scan_result = (BIGNUM_START_PTR (result)); \
352 while (scan_digits < end_digits) \
353 (*scan_result++) = (*scan_digits++); \
358 FOO_TO_BIGNUM(cell,cell,fixnum,cell)
359 FOO_TO_BIGNUM(fixnum,fixnum,fixnum,cell)
360 FOO_TO_BIGNUM(long_long,s64,s64,u64)
361 FOO_TO_BIGNUM(ulong_long,u64,s64,u64)
363 /* cannot allocate memory */
364 #define BIGNUM_TO_FOO(name,type,stype,utype) \
365 type factor_vm::bignum_to_##name(bignum * bignum) \
367 if (BIGNUM_ZERO_P (bignum)) \
370 utype accumulator = 0; \
371 bignum_digit_type * start = (BIGNUM_START_PTR (bignum)); \
372 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum))); \
373 while (start < scan) \
374 accumulator = ((accumulator << BIGNUM_DIGIT_LENGTH) + (*--scan)); \
375 return ((BIGNUM_NEGATIVE_P (bignum)) ? ((type)(-(stype)accumulator)) : accumulator); \
379 BIGNUM_TO_FOO(cell,cell,fixnum,cell)
380 BIGNUM_TO_FOO(fixnum,fixnum,fixnum,cell)
381 BIGNUM_TO_FOO(long_long,s64,s64,u64)
382 BIGNUM_TO_FOO(ulong_long,u64,s64,u64)
384 #define DTB_WRITE_DIGIT(factor) \
386 significand *= (factor); \
387 digit = ((bignum_digit_type) significand); \
389 significand -= ((double) digit); \
392 /* allocates memory */
393 #define inf std::numeric_limits<double>::infinity()
395 bignum *factor_vm::double_to_bignum(double x)
397 if (x == inf || x == -inf || x != x) return (BIGNUM_ZERO ());
399 double significand = (frexp (x, (&exponent)));
400 if (exponent <= 0) return (BIGNUM_ZERO ());
401 if (exponent == 1) return (BIGNUM_ONE (x < 0));
402 if (significand < 0) significand = (-significand);
404 bignum_length_type length = (BIGNUM_BITS_TO_DIGITS (exponent));
405 bignum * result = (allot_bignum (length, (x < 0)));
406 bignum_digit_type * start = (BIGNUM_START_PTR (result));
407 bignum_digit_type * scan = (start + length);
408 bignum_digit_type digit;
409 int odd_bits = (exponent % BIGNUM_DIGIT_LENGTH);
411 DTB_WRITE_DIGIT ((fixnum)1 << odd_bits);
414 if (significand == 0)
420 DTB_WRITE_DIGIT (BIGNUM_RADIX);
426 #undef DTB_WRITE_DIGIT
430 int factor_vm::bignum_equal_p_unsigned(bignum * x, bignum * y)
432 bignum_length_type length = (BIGNUM_LENGTH (x));
433 if (length != (BIGNUM_LENGTH (y)))
437 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
438 bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
439 bignum_digit_type * end_x = (scan_x + length);
440 while (scan_x < end_x)
441 if ((*scan_x++) != (*scan_y++))
447 enum bignum_comparison factor_vm::bignum_compare_unsigned(bignum * x, bignum * y)
449 bignum_length_type x_length = (BIGNUM_LENGTH (x));
450 bignum_length_type y_length = (BIGNUM_LENGTH (y));
451 if (x_length < y_length)
452 return (bignum_comparison_less);
453 if (x_length > y_length)
454 return (bignum_comparison_greater);
456 bignum_digit_type * start_x = (BIGNUM_START_PTR (x));
457 bignum_digit_type * scan_x = (start_x + x_length);
458 bignum_digit_type * scan_y = ((BIGNUM_START_PTR (y)) + y_length);
459 while (start_x < scan_x)
461 bignum_digit_type digit_x = (*--scan_x);
462 bignum_digit_type digit_y = (*--scan_y);
463 if (digit_x < digit_y)
464 return (bignum_comparison_less);
465 if (digit_x > digit_y)
466 return (bignum_comparison_greater);
469 return (bignum_comparison_equal);
474 /* allocates memory */
475 bignum *factor_vm::bignum_add_unsigned(bignum * x, bignum * y, int negative_p)
477 GC_BIGNUM(x); GC_BIGNUM(y);
479 if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
486 bignum_length_type x_length = (BIGNUM_LENGTH (x));
488 bignum * r = (allot_bignum ((x_length + 1), negative_p));
490 bignum_digit_type sum;
491 bignum_digit_type carry = 0;
492 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
493 bignum_digit_type * scan_r = (BIGNUM_START_PTR (r));
495 bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
496 bignum_digit_type * end_y = (scan_y + (BIGNUM_LENGTH (y)));
497 while (scan_y < end_y)
499 sum = ((*scan_x++) + (*scan_y++) + carry);
500 if (sum < BIGNUM_RADIX)
507 (*scan_r++) = (sum - BIGNUM_RADIX);
513 bignum_digit_type * end_x = ((BIGNUM_START_PTR (x)) + x_length);
515 while (scan_x < end_x)
517 sum = ((*scan_x++) + 1);
518 if (sum < BIGNUM_RADIX)
525 (*scan_r++) = (sum - BIGNUM_RADIX);
527 while (scan_x < end_x)
528 (*scan_r++) = (*scan_x++);
535 return (bignum_shorten_length (r, x_length));
541 /* allocates memory */
542 bignum *factor_vm::bignum_subtract_unsigned(bignum * x, bignum * y)
544 GC_BIGNUM(x); GC_BIGNUM(y);
547 switch (bignum_compare_unsigned (x, y))
549 case bignum_comparison_equal:
550 return (BIGNUM_ZERO ());
551 case bignum_comparison_less:
559 case bignum_comparison_greater:
564 bignum_length_type x_length = (BIGNUM_LENGTH (x));
566 bignum * r = (allot_bignum (x_length, negative_p));
568 bignum_digit_type difference;
569 bignum_digit_type borrow = 0;
570 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
571 bignum_digit_type * scan_r = (BIGNUM_START_PTR (r));
573 bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
574 bignum_digit_type * end_y = (scan_y + (BIGNUM_LENGTH (y)));
575 while (scan_y < end_y)
577 difference = (((*scan_x++) - (*scan_y++)) - borrow);
580 (*scan_r++) = (difference + BIGNUM_RADIX);
585 (*scan_r++) = difference;
591 bignum_digit_type * end_x = ((BIGNUM_START_PTR (x)) + x_length);
593 while (scan_x < end_x)
595 difference = ((*scan_x++) - borrow);
597 (*scan_r++) = (difference + BIGNUM_RADIX);
600 (*scan_r++) = difference;
605 BIGNUM_ASSERT (borrow == 0);
606 while (scan_x < end_x)
607 (*scan_r++) = (*scan_x++);
609 return (bignum_trim (r));
614 Maximum value for product_low or product_high:
615 ((R * R) + (R * (R - 2)) + (R - 1))
616 Maximum value for carry: ((R * (R - 1)) + (R - 1))
617 where R == BIGNUM_RADIX_ROOT */
619 /* allocates memory */
620 bignum *factor_vm::bignum_multiply_unsigned(bignum * x, bignum * y, int negative_p)
622 GC_BIGNUM(x); GC_BIGNUM(y);
624 if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
631 bignum_digit_type carry;
632 bignum_digit_type y_digit_low;
633 bignum_digit_type y_digit_high;
634 bignum_digit_type x_digit_low;
635 bignum_digit_type x_digit_high;
636 bignum_digit_type product_low;
637 bignum_digit_type * scan_r;
638 bignum_digit_type * scan_y;
639 bignum_length_type x_length = (BIGNUM_LENGTH (x));
640 bignum_length_type y_length = (BIGNUM_LENGTH (y));
643 (allot_bignum_zeroed ((x_length + y_length), negative_p));
645 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
646 bignum_digit_type * end_x = (scan_x + x_length);
647 bignum_digit_type * start_y = (BIGNUM_START_PTR (y));
648 bignum_digit_type * end_y = (start_y + y_length);
649 bignum_digit_type * start_r = (BIGNUM_START_PTR (r));
650 #define x_digit x_digit_high
651 #define y_digit y_digit_high
652 #define product_high carry
653 while (scan_x < end_x)
655 x_digit = (*scan_x++);
656 x_digit_low = (HD_LOW (x_digit));
657 x_digit_high = (HD_HIGH (x_digit));
660 scan_r = (start_r++);
661 while (scan_y < end_y)
663 y_digit = (*scan_y++);
664 y_digit_low = (HD_LOW (y_digit));
665 y_digit_high = (HD_HIGH (y_digit));
668 (x_digit_low * y_digit_low) +
671 ((x_digit_high * y_digit_low) +
672 (x_digit_low * y_digit_high) +
673 (HD_HIGH (product_low)) +
676 (HD_CONS ((HD_LOW (product_high)), (HD_LOW (product_low))));
678 ((x_digit_high * y_digit_high) +
679 (HD_HIGH (product_high)));
683 return (bignum_trim (r));
690 /* allocates memory */
691 bignum *factor_vm::bignum_multiply_unsigned_small_factor(bignum * x, bignum_digit_type y, int negative_p)
695 bignum_length_type length_x = (BIGNUM_LENGTH (x));
697 bignum * p = (allot_bignum ((length_x + 1), negative_p));
699 bignum_destructive_copy (x, p);
700 (BIGNUM_REF (p, length_x)) = 0;
701 bignum_destructive_scale_up (p, y);
702 return (bignum_trim (p));
705 void factor_vm::bignum_destructive_add(bignum * bignum, bignum_digit_type n)
707 bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
708 bignum_digit_type digit;
709 digit = ((*scan) + n);
710 if (digit < BIGNUM_RADIX)
715 (*scan++) = (digit - BIGNUM_RADIX);
718 digit = ((*scan) + 1);
719 if (digit < BIGNUM_RADIX)
724 (*scan++) = (digit - BIGNUM_RADIX);
728 void factor_vm::bignum_destructive_scale_up(bignum * bignum, bignum_digit_type factor)
730 bignum_digit_type carry = 0;
731 bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
732 bignum_digit_type two_digits;
733 bignum_digit_type product_low;
734 #define product_high carry
735 bignum_digit_type * end = (scan + (BIGNUM_LENGTH (bignum)));
736 BIGNUM_ASSERT ((factor > 1) && (factor < BIGNUM_RADIX_ROOT));
739 two_digits = (*scan);
740 product_low = ((factor * (HD_LOW (two_digits))) + (HD_LOW (carry)));
742 ((factor * (HD_HIGH (two_digits))) +
743 (HD_HIGH (product_low)) +
745 (*scan++) = (HD_CONS ((HD_LOW (product_high)), (HD_LOW (product_low))));
746 carry = (HD_HIGH (product_high));
748 /* A carry here would be an overflow, i.e. it would not fit.
749 Hopefully the callers allocate enough space that this will
752 BIGNUM_ASSERT (carry == 0);
759 /* For help understanding this algorithm, see:
760 Knuth, Donald E., "The Art of Computer Programming",
761 volume 2, "Seminumerical Algorithms"
762 section 4.3.1, "Multiple-Precision Arithmetic". */
764 /* allocates memory */
765 void factor_vm::bignum_divide_unsigned_large_denominator(bignum * numerator, bignum * denominator, bignum * * quotient, bignum * * remainder, int q_negative_p, int r_negative_p)
767 GC_BIGNUM(numerator); GC_BIGNUM(denominator);
769 bignum_length_type length_n = ((BIGNUM_LENGTH (numerator)) + 1);
770 bignum_length_type length_d = (BIGNUM_LENGTH (denominator));
773 ((quotient != ((bignum * *) 0))
774 ? (allot_bignum ((length_n - length_d), q_negative_p))
775 : BIGNUM_OUT_OF_BAND);
778 bignum * u = (allot_bignum (length_n, r_negative_p));
782 BIGNUM_ASSERT (length_d > 1);
784 bignum_digit_type v1 = (BIGNUM_REF ((denominator), (length_d - 1)));
785 while (v1 < (BIGNUM_RADIX / 2))
793 bignum_destructive_copy (numerator, u);
794 (BIGNUM_REF (u, (length_n - 1))) = 0;
795 bignum_divide_unsigned_normalized (u, denominator, q);
799 bignum * v = (allot_bignum (length_d, 0));
801 bignum_destructive_normalization (numerator, u, shift);
802 bignum_destructive_normalization (denominator, v, shift);
803 bignum_divide_unsigned_normalized (u, v, q);
804 if (remainder != ((bignum * *) 0))
805 bignum_destructive_unnormalization (u, shift);
813 if (quotient != ((bignum * *) 0))
816 if (remainder != ((bignum * *) 0))
822 void factor_vm::bignum_divide_unsigned_normalized(bignum * u, bignum * v, bignum * q)
824 bignum_length_type u_length = (BIGNUM_LENGTH (u));
825 bignum_length_type v_length = (BIGNUM_LENGTH (v));
826 bignum_digit_type * u_start = (BIGNUM_START_PTR (u));
827 bignum_digit_type * u_scan = (u_start + u_length);
828 bignum_digit_type * u_scan_limit = (u_start + v_length);
829 bignum_digit_type * u_scan_start = (u_scan - v_length);
830 bignum_digit_type * v_start = (BIGNUM_START_PTR (v));
831 bignum_digit_type * v_end = (v_start + v_length);
832 bignum_digit_type * q_scan = NULL;
833 bignum_digit_type v1 = (v_end[-1]);
834 bignum_digit_type v2 = (v_end[-2]);
835 bignum_digit_type ph; /* high half of double-digit product */
836 bignum_digit_type pl; /* low half of double-digit product */
837 bignum_digit_type guess;
838 bignum_digit_type gh; /* high half-digit of guess */
839 bignum_digit_type ch; /* high half of double-digit comparand */
840 bignum_digit_type v2l = (HD_LOW (v2));
841 bignum_digit_type v2h = (HD_HIGH (v2));
842 bignum_digit_type cl; /* low half of double-digit comparand */
843 #define gl ph /* low half-digit of guess */
846 bignum_digit_type gm; /* memory loc for reference parameter */
847 if (q != BIGNUM_OUT_OF_BAND)
848 q_scan = ((BIGNUM_START_PTR (q)) + (BIGNUM_LENGTH (q)));
849 while (u_scan_limit < u_scan)
855 (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
856 guess = (((uj * BIGNUM_RADIX) + uj1) / v1); */
858 ch = (bignum_digit_divide (uj, (u_scan[-1]), v1, (&gm)));
864 ch = ((u_scan[-1]) + v1);
865 guess = (BIGNUM_RADIX - 1);
869 /* product = (guess * v2); */
870 gl = (HD_LOW (guess));
871 gh = (HD_HIGH (guess));
873 ph = ((v2l * gh) + (v2h * gl) + (HD_HIGH (pl)));
874 pl = (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl))));
875 ph = ((v2h * gh) + (HD_HIGH (ph)));
876 /* if (comparand >= product) */
877 if ((ch > ph) || ((ch == ph) && (cl >= pl)))
880 /* comparand += (v1 << BIGNUM_DIGIT_LENGTH) */
882 /* if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX)) */
883 if (ch >= BIGNUM_RADIX)
886 qj = (bignum_divide_subtract (v_start, v_end, guess, (--u_scan_start)));
887 if (q != BIGNUM_OUT_OF_BAND)
896 bignum_digit_type factor_vm::bignum_divide_subtract(bignum_digit_type * v_start, bignum_digit_type * v_end, bignum_digit_type guess, bignum_digit_type * u_start)
898 bignum_digit_type * v_scan = v_start;
899 bignum_digit_type * u_scan = u_start;
900 bignum_digit_type carry = 0;
901 if (guess == 0) return (0);
903 bignum_digit_type gl = (HD_LOW (guess));
904 bignum_digit_type gh = (HD_HIGH (guess));
906 bignum_digit_type pl;
907 bignum_digit_type vl;
911 while (v_scan < v_end)
916 pl = ((vl * gl) + (HD_LOW (carry)));
917 ph = ((vl * gh) + (vh * gl) + (HD_HIGH (pl)) + (HD_HIGH (carry)));
918 diff = ((*u_scan) - (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl)))));
921 (*u_scan++) = (diff + BIGNUM_RADIX);
922 carry = ((vh * gh) + (HD_HIGH (ph)) + 1);
927 carry = ((vh * gh) + (HD_HIGH (ph)));
932 diff = ((*u_scan) - carry);
934 (*u_scan) = (diff + BIGNUM_RADIX);
944 /* Subtraction generated carry, implying guess is one too large.
945 Add v back in to bring it back down. */
949 while (v_scan < v_end)
951 bignum_digit_type sum = ((*v_scan++) + (*u_scan) + carry);
952 if (sum < BIGNUM_RADIX)
959 (*u_scan++) = (sum - BIGNUM_RADIX);
965 bignum_digit_type sum = ((*u_scan) + carry);
966 (*u_scan) = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
971 /* allocates memory */
972 void factor_vm::bignum_divide_unsigned_medium_denominator(bignum * numerator,bignum_digit_type denominator, bignum * * quotient, bignum * * remainder,int q_negative_p, int r_negative_p)
974 GC_BIGNUM(numerator);
976 bignum_length_type length_n = (BIGNUM_LENGTH (numerator));
977 bignum_length_type length_q;
982 /* Because `bignum_digit_divide' requires a normalized denominator. */
983 while (denominator < (BIGNUM_RADIX / 2))
992 q = (allot_bignum (length_q, q_negative_p));
993 bignum_destructive_copy (numerator, q);
997 length_q = (length_n + 1);
999 q = (allot_bignum (length_q, q_negative_p));
1000 bignum_destructive_normalization (numerator, q, shift);
1003 bignum_digit_type r = 0;
1004 bignum_digit_type * start = (BIGNUM_START_PTR (q));
1005 bignum_digit_type * scan = (start + length_q);
1006 bignum_digit_type qj;
1008 while (start < scan)
1010 r = (bignum_digit_divide (r, (*--scan), denominator, (&qj)));
1014 q = bignum_trim (q);
1016 if (remainder != ((bignum * *) 0))
1021 (*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
1024 if (quotient != ((bignum * *) 0))
1030 void factor_vm::bignum_destructive_normalization(bignum * source, bignum * target, int shift_left)
1032 bignum_digit_type digit;
1033 bignum_digit_type * scan_source = (BIGNUM_START_PTR (source));
1034 bignum_digit_type carry = 0;
1035 bignum_digit_type * scan_target = (BIGNUM_START_PTR (target));
1036 bignum_digit_type * end_source = (scan_source + (BIGNUM_LENGTH (source)));
1037 bignum_digit_type * end_target = (scan_target + (BIGNUM_LENGTH (target)));
1038 int shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
1039 bignum_digit_type mask = (((cell)1 << shift_right) - 1);
1040 while (scan_source < end_source)
1042 digit = (*scan_source++);
1043 (*scan_target++) = (((digit & mask) << shift_left) | carry);
1044 carry = (digit >> shift_right);
1046 if (scan_target < end_target)
1047 (*scan_target) = carry;
1049 BIGNUM_ASSERT (carry == 0);
1053 void factor_vm::bignum_destructive_unnormalization(bignum * bignum, int shift_right)
1055 bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
1056 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
1057 bignum_digit_type digit;
1058 bignum_digit_type carry = 0;
1059 int shift_left = (BIGNUM_DIGIT_LENGTH - shift_right);
1060 bignum_digit_type mask = (((fixnum)1 << shift_right) - 1);
1061 while (start < scan)
1064 (*scan) = ((digit >> shift_right) | carry);
1065 carry = ((digit & mask) << shift_left);
1067 BIGNUM_ASSERT (carry == 0);
1071 /* This is a reduced version of the division algorithm, applied to the
1072 case of dividing two bignum digits by one bignum digit. It is
1073 assumed that the numerator, denominator are normalized. */
1075 #define BDD_STEP(qn, j) \
1080 uj_uj1 = (HD_CONS (uj, (u[j + 1]))); \
1081 guess = (uj_uj1 / v1); \
1082 comparand = (HD_CONS ((uj_uj1 % v1), (u[j + 2]))); \
1086 guess = (BIGNUM_RADIX_ROOT - 1); \
1087 comparand = (HD_CONS (((u[j + 1]) + v1), (u[j + 2]))); \
1089 while ((guess * v2) > comparand) \
1092 comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH); \
1093 if (comparand >= BIGNUM_RADIX) \
1096 qn = (bignum_digit_divide_subtract (v1, v2, guess, (&u[j]))); \
1099 bignum_digit_type factor_vm::bignum_digit_divide(bignum_digit_type uh, bignum_digit_type ul, bignum_digit_type v, bignum_digit_type * q) /* return value */
1101 bignum_digit_type guess;
1102 bignum_digit_type comparand;
1103 bignum_digit_type v1 = (HD_HIGH (v));
1104 bignum_digit_type v2 = (HD_LOW (v));
1105 bignum_digit_type uj;
1106 bignum_digit_type uj_uj1;
1107 bignum_digit_type q1;
1108 bignum_digit_type q2;
1109 bignum_digit_type u [4];
1123 (u[0]) = (HD_HIGH (uh));
1124 (u[1]) = (HD_LOW (uh));
1125 (u[2]) = (HD_HIGH (ul));
1126 (u[3]) = (HD_LOW (ul));
1131 (*q) = (HD_CONS (q1, q2));
1132 return (HD_CONS ((u[2]), (u[3])));
1137 #define BDDS_MULSUB(vn, un, carry_in) \
1139 product = ((vn * guess) + carry_in); \
1140 diff = (un - (HD_LOW (product))); \
1143 un = (diff + BIGNUM_RADIX_ROOT); \
1144 carry = ((HD_HIGH (product)) + 1); \
1149 carry = (HD_HIGH (product)); \
1153 #define BDDS_ADD(vn, un, carry_in) \
1155 sum = (vn + un + carry_in); \
1156 if (sum < BIGNUM_RADIX_ROOT) \
1163 un = (sum - BIGNUM_RADIX_ROOT); \
1168 bignum_digit_type factor_vm::bignum_digit_divide_subtract(bignum_digit_type v1, bignum_digit_type v2, bignum_digit_type guess, bignum_digit_type * u)
1171 bignum_digit_type product;
1172 bignum_digit_type diff;
1173 bignum_digit_type carry;
1174 BDDS_MULSUB (v2, (u[2]), 0);
1175 BDDS_MULSUB (v1, (u[1]), carry);
1178 diff = ((u[0]) - carry);
1180 (u[0]) = (diff + BIGNUM_RADIX);
1188 bignum_digit_type sum;
1189 bignum_digit_type carry;
1190 BDDS_ADD(v2, (u[2]), 0);
1191 BDDS_ADD(v1, (u[1]), carry);
1201 /* allocates memory */
1202 void factor_vm::bignum_divide_unsigned_small_denominator(bignum * numerator, bignum_digit_type denominator, bignum * * quotient, bignum * * remainder,int q_negative_p, int r_negative_p)
1204 GC_BIGNUM(numerator);
1206 bignum * q = (bignum_new_sign (numerator, q_negative_p));
1209 bignum_digit_type r = (bignum_destructive_scale_down (q, denominator));
1211 q = (bignum_trim (q));
1213 if (remainder != ((bignum * *) 0))
1214 (*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
1221 /* Given (denominator > 1), it is fairly easy to show that
1222 (quotient_high < BIGNUM_RADIX_ROOT), after which it is easy to see
1223 that all digits are < BIGNUM_RADIX. */
1225 bignum_digit_type factor_vm::bignum_destructive_scale_down(bignum * bignum, bignum_digit_type denominator)
1227 bignum_digit_type numerator;
1228 bignum_digit_type remainder = 0;
1229 bignum_digit_type two_digits;
1230 #define quotient_high remainder
1231 bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
1232 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
1233 BIGNUM_ASSERT ((denominator > 1) && (denominator < BIGNUM_RADIX_ROOT));
1234 while (start < scan)
1236 two_digits = (*--scan);
1237 numerator = (HD_CONS (remainder, (HD_HIGH (two_digits))));
1238 quotient_high = (numerator / denominator);
1239 numerator = (HD_CONS ((numerator % denominator), (HD_LOW (two_digits))));
1240 (*scan) = (HD_CONS (quotient_high, (numerator / denominator)));
1241 remainder = (numerator % denominator);
1244 #undef quotient_high
1247 /* allocates memory */
1248 bignum * factor_vm::bignum_remainder_unsigned_small_denominator(bignum * n, bignum_digit_type d, int negative_p)
1250 bignum_digit_type two_digits;
1251 bignum_digit_type * start = (BIGNUM_START_PTR (n));
1252 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (n)));
1253 bignum_digit_type r = 0;
1254 BIGNUM_ASSERT ((d > 1) && (d < BIGNUM_RADIX_ROOT));
1255 while (start < scan)
1257 two_digits = (*--scan);
1259 ((HD_CONS (((HD_CONS (r, (HD_HIGH (two_digits)))) % d),
1260 (HD_LOW (two_digits))))
1263 return (bignum_digit_to_bignum (r, negative_p));
1266 /* allocates memory */
1267 bignum *factor_vm::bignum_digit_to_bignum(bignum_digit_type digit, int negative_p)
1270 return (BIGNUM_ZERO ());
1273 bignum * result = (allot_bignum (1, negative_p));
1274 (BIGNUM_REF (result, 0)) = digit;
1279 /* allocates memory */
1280 bignum *factor_vm::allot_bignum(bignum_length_type length, int negative_p)
1282 BIGNUM_ASSERT ((length >= 0) || (length < BIGNUM_RADIX));
1283 bignum * result = allot_uninitialized_array<bignum>(length + 1);
1284 BIGNUM_SET_NEGATIVE_P (result, negative_p);
1288 /* allocates memory */
1289 bignum * factor_vm::allot_bignum_zeroed(bignum_length_type length, int negative_p)
1291 bignum * result = allot_bignum(length,negative_p);
1292 bignum_digit_type * scan = (BIGNUM_START_PTR (result));
1293 bignum_digit_type * end = (scan + length);
1299 #define BIGNUM_REDUCE_LENGTH(source, length) \
1300 source = reallot_array(source,length + 1)
1302 /* allocates memory */
1303 bignum *factor_vm::bignum_shorten_length(bignum * bignum, bignum_length_type length)
1305 bignum_length_type current_length = (BIGNUM_LENGTH (bignum));
1306 BIGNUM_ASSERT ((length >= 0) || (length <= current_length));
1307 if (length < current_length)
1309 BIGNUM_REDUCE_LENGTH (bignum, length);
1310 BIGNUM_SET_NEGATIVE_P (bignum, (length != 0) && (BIGNUM_NEGATIVE_P (bignum)));
1315 /* allocates memory */
1316 bignum *factor_vm::bignum_trim(bignum * bignum)
1318 bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
1319 bignum_digit_type * end = (start + (BIGNUM_LENGTH (bignum)));
1320 bignum_digit_type * scan = end;
1321 while ((start <= scan) && ((*--scan) == 0))
1326 bignum_length_type length = (scan - start);
1327 BIGNUM_REDUCE_LENGTH (bignum, length);
1328 BIGNUM_SET_NEGATIVE_P (bignum, (length != 0) && (BIGNUM_NEGATIVE_P (bignum)));
1335 /* allocates memory */
1336 bignum *factor_vm::bignum_new_sign(bignum * x, int negative_p)
1339 bignum * result = (allot_bignum ((BIGNUM_LENGTH (x)), negative_p));
1341 bignum_destructive_copy (x, result);
1345 /* allocates memory */
1346 bignum *factor_vm::bignum_maybe_new_sign(bignum * x, int negative_p)
1348 if ((BIGNUM_NEGATIVE_P (x)) ? negative_p : (! negative_p))
1353 (allot_bignum ((BIGNUM_LENGTH (x)), negative_p));
1354 bignum_destructive_copy (x, result);
1359 void factor_vm::bignum_destructive_copy(bignum * source, bignum * target)
1361 bignum_digit_type * scan_source = (BIGNUM_START_PTR (source));
1362 bignum_digit_type * end_source =
1363 (scan_source + (BIGNUM_LENGTH (source)));
1364 bignum_digit_type * scan_target = (BIGNUM_START_PTR (target));
1365 while (scan_source < end_source)
1366 (*scan_target++) = (*scan_source++);
1371 * Added bitwise operations (and oddp).
1374 /* allocates memory */
1375 bignum *factor_vm::bignum_bitwise_not(bignum * x)
1377 return bignum_subtract(BIGNUM_ONE(1), x);
1380 /* allocates memory */
1381 bignum *factor_vm::bignum_arithmetic_shift(bignum * arg1, fixnum n)
1383 if (BIGNUM_NEGATIVE_P(arg1) && n < 0)
1384 return bignum_bitwise_not(bignum_magnitude_ash(bignum_bitwise_not(arg1), n));
1386 return bignum_magnitude_ash(arg1, n);
1393 /* allocates memory */
1394 bignum *factor_vm::bignum_bitwise_and(bignum * arg1, bignum * arg2)
1397 (BIGNUM_NEGATIVE_P (arg1))
1398 ? (BIGNUM_NEGATIVE_P (arg2))
1399 ? bignum_negneg_bitwise_op(AND_OP, arg1, arg2)
1400 : bignum_posneg_bitwise_op(AND_OP, arg2, arg1)
1401 : (BIGNUM_NEGATIVE_P (arg2))
1402 ? bignum_posneg_bitwise_op(AND_OP, arg1, arg2)
1403 : bignum_pospos_bitwise_op(AND_OP, arg1, arg2)
1407 /* allocates memory */
1408 bignum *factor_vm::bignum_bitwise_ior(bignum * arg1, bignum * arg2)
1411 (BIGNUM_NEGATIVE_P (arg1))
1412 ? (BIGNUM_NEGATIVE_P (arg2))
1413 ? bignum_negneg_bitwise_op(IOR_OP, arg1, arg2)
1414 : bignum_posneg_bitwise_op(IOR_OP, arg2, arg1)
1415 : (BIGNUM_NEGATIVE_P (arg2))
1416 ? bignum_posneg_bitwise_op(IOR_OP, arg1, arg2)
1417 : bignum_pospos_bitwise_op(IOR_OP, arg1, arg2)
1421 /* allocates memory */
1422 bignum *factor_vm::bignum_bitwise_xor(bignum * arg1, bignum * arg2)
1425 (BIGNUM_NEGATIVE_P (arg1))
1426 ? (BIGNUM_NEGATIVE_P (arg2))
1427 ? bignum_negneg_bitwise_op(XOR_OP, arg1, arg2)
1428 : bignum_posneg_bitwise_op(XOR_OP, arg2, arg1)
1429 : (BIGNUM_NEGATIVE_P (arg2))
1430 ? bignum_posneg_bitwise_op(XOR_OP, arg1, arg2)
1431 : bignum_pospos_bitwise_op(XOR_OP, arg1, arg2)
1435 /* allocates memory */
1436 /* ash for the magnitude */
1437 /* assume arg1 is a big number, n is a long */
1438 bignum *factor_vm::bignum_magnitude_ash(bignum * arg1, fixnum n)
1442 bignum * result = NULL;
1443 bignum_digit_type *scan1;
1444 bignum_digit_type *scanr;
1445 bignum_digit_type *end;
1447 fixnum digit_offset,bit_offset;
1449 if (BIGNUM_ZERO_P (arg1)) return (arg1);
1452 digit_offset = n / BIGNUM_DIGIT_LENGTH;
1453 bit_offset = n % BIGNUM_DIGIT_LENGTH;
1455 result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) + digit_offset + 1,
1456 BIGNUM_NEGATIVE_P(arg1));
1458 scanr = BIGNUM_START_PTR (result) + digit_offset;
1459 scan1 = BIGNUM_START_PTR (arg1);
1460 end = scan1 + BIGNUM_LENGTH (arg1);
1462 while (scan1 < end) {
1463 *scanr = *scanr | (*scan1 & BIGNUM_DIGIT_MASK) << bit_offset;
1464 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1466 *scanr = *scan1++ >> (BIGNUM_DIGIT_LENGTH - bit_offset);
1467 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1471 && (-n >= (BIGNUM_LENGTH (arg1) * (bignum_length_type) BIGNUM_DIGIT_LENGTH)))
1472 result = BIGNUM_ZERO ();
1475 digit_offset = -n / BIGNUM_DIGIT_LENGTH;
1476 bit_offset = -n % BIGNUM_DIGIT_LENGTH;
1478 result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) - digit_offset,
1479 BIGNUM_NEGATIVE_P(arg1));
1481 scanr = BIGNUM_START_PTR (result);
1482 scan1 = BIGNUM_START_PTR (arg1) + digit_offset;
1483 end = scanr + BIGNUM_LENGTH (result) - 1;
1485 while (scanr < end) {
1486 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset ;
1488 *scan1 << (BIGNUM_DIGIT_LENGTH - bit_offset)) & BIGNUM_DIGIT_MASK;
1491 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset ;
1493 else if (n == 0) result = arg1;
1495 return (bignum_trim (result));
1498 /* allocates memory */
1499 bignum *factor_vm::bignum_pospos_bitwise_op(int op, bignum * arg1, bignum * arg2)
1501 GC_BIGNUM(arg1); GC_BIGNUM(arg2);
1504 bignum_length_type max_length;
1506 bignum_digit_type *scan1, *end1, digit1;
1507 bignum_digit_type *scan2, *end2, digit2;
1508 bignum_digit_type *scanr, *endr;
1510 max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
1511 ? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2);
1513 result = allot_bignum(max_length, 0);
1515 scanr = BIGNUM_START_PTR(result);
1516 scan1 = BIGNUM_START_PTR(arg1);
1517 scan2 = BIGNUM_START_PTR(arg2);
1518 endr = scanr + max_length;
1519 end1 = scan1 + BIGNUM_LENGTH(arg1);
1520 end2 = scan2 + BIGNUM_LENGTH(arg2);
1522 while (scanr < endr) {
1523 digit1 = (scan1 < end1) ? *scan1++ : 0;
1524 digit2 = (scan2 < end2) ? *scan2++ : 0;
1525 *scanr++ = (op == AND_OP) ? digit1 & digit2 :
1526 (op == IOR_OP) ? digit1 | digit2 :
1529 return bignum_trim(result);
1532 /* allocates memory */
1533 bignum *factor_vm::bignum_posneg_bitwise_op(int op, bignum * arg1, bignum * arg2)
1535 GC_BIGNUM(arg1); GC_BIGNUM(arg2);
1538 bignum_length_type max_length;
1540 bignum_digit_type *scan1, *end1, digit1;
1541 bignum_digit_type *scan2, *end2, digit2, carry2;
1542 bignum_digit_type *scanr, *endr;
1544 char neg_p = op == IOR_OP || op == XOR_OP;
1546 max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1)
1547 ? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2) + 1;
1549 result = allot_bignum(max_length, neg_p);
1551 scanr = BIGNUM_START_PTR(result);
1552 scan1 = BIGNUM_START_PTR(arg1);
1553 scan2 = BIGNUM_START_PTR(arg2);
1554 endr = scanr + max_length;
1555 end1 = scan1 + BIGNUM_LENGTH(arg1);
1556 end2 = scan2 + BIGNUM_LENGTH(arg2);
1560 while (scanr < endr) {
1561 digit1 = (scan1 < end1) ? *scan1++ : 0;
1562 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK)
1565 if (digit2 < BIGNUM_RADIX)
1569 digit2 = (digit2 - BIGNUM_RADIX);
1573 *scanr++ = (op == AND_OP) ? digit1 & digit2 :
1574 (op == IOR_OP) ? digit1 | digit2 :
1579 bignum_negate_magnitude(result);
1581 return bignum_trim(result);
1584 /* allocates memory */
1585 bignum *factor_vm::bignum_negneg_bitwise_op(int op, bignum * arg1, bignum * arg2)
1587 GC_BIGNUM(arg1); GC_BIGNUM(arg2);
1590 bignum_length_type max_length;
1592 bignum_digit_type *scan1, *end1, digit1, carry1;
1593 bignum_digit_type *scan2, *end2, digit2, carry2;
1594 bignum_digit_type *scanr, *endr;
1596 char neg_p = op == AND_OP || op == IOR_OP;
1598 max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
1599 ? BIGNUM_LENGTH(arg1) + 1 : BIGNUM_LENGTH(arg2) + 1;
1601 result = allot_bignum(max_length, neg_p);
1603 scanr = BIGNUM_START_PTR(result);
1604 scan1 = BIGNUM_START_PTR(arg1);
1605 scan2 = BIGNUM_START_PTR(arg2);
1606 endr = scanr + max_length;
1607 end1 = scan1 + BIGNUM_LENGTH(arg1);
1608 end2 = scan2 + BIGNUM_LENGTH(arg2);
1613 while (scanr < endr) {
1614 digit1 = (~((scan1 < end1) ? *scan1++ : 0) & BIGNUM_DIGIT_MASK) + carry1;
1615 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
1617 if (digit1 < BIGNUM_RADIX)
1621 digit1 = (digit1 - BIGNUM_RADIX);
1625 if (digit2 < BIGNUM_RADIX)
1629 digit2 = (digit2 - BIGNUM_RADIX);
1633 *scanr++ = (op == AND_OP) ? digit1 & digit2 :
1634 (op == IOR_OP) ? digit1 | digit2 :
1639 bignum_negate_magnitude(result);
1641 return bignum_trim(result);
1644 void factor_vm::bignum_negate_magnitude(bignum * arg)
1646 bignum_digit_type *scan;
1647 bignum_digit_type *end;
1648 bignum_digit_type digit;
1649 bignum_digit_type carry;
1651 scan = BIGNUM_START_PTR(arg);
1652 end = scan + BIGNUM_LENGTH(arg);
1656 while (scan < end) {
1657 digit = (~*scan & BIGNUM_DIGIT_MASK) + carry;
1659 if (digit < BIGNUM_RADIX)
1663 digit = (digit - BIGNUM_RADIX);
1671 /* Allocates memory */
1672 bignum *factor_vm::bignum_integer_length(bignum * x)
1676 bignum_length_type index = ((BIGNUM_LENGTH (x)) - 1);
1677 bignum_digit_type digit = (BIGNUM_REF (x, index));
1679 bignum * result = (allot_bignum (2, 0));
1681 (BIGNUM_REF (result, 0)) = index;
1682 (BIGNUM_REF (result, 1)) = 0;
1683 bignum_destructive_scale_up (result, BIGNUM_DIGIT_LENGTH);
1686 bignum_destructive_add (result, ((bignum_digit_type) 1));
1689 return (bignum_trim (result));
1692 /* Allocates memory */
1693 int factor_vm::bignum_logbitp(int shift, bignum * arg)
1695 return((BIGNUM_NEGATIVE_P (arg))
1696 ? !bignum_unsigned_logbitp (shift, bignum_bitwise_not (arg))
1697 : bignum_unsigned_logbitp (shift,arg));
1700 int factor_vm::bignum_unsigned_logbitp(int shift, bignum * bignum)
1702 bignum_length_type len = (BIGNUM_LENGTH (bignum));
1703 int index = shift / BIGNUM_DIGIT_LENGTH;
1706 bignum_digit_type digit = (BIGNUM_REF (bignum, index));
1707 int p = shift % BIGNUM_DIGIT_LENGTH;
1708 bignum_digit_type mask = ((fixnum)1) << p;
1709 return (digit & mask) ? 1 : 0;