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
49 * - Added bignum_gcd implementation
59 int factor_vm::bignum_equal_p(bignum * x, bignum * y)
64 : ((! (BIGNUM_ZERO_P (y)))
65 && ((BIGNUM_NEGATIVE_P (x))
66 ? (BIGNUM_NEGATIVE_P (y))
67 : (! (BIGNUM_NEGATIVE_P (y))))
68 && (bignum_equal_p_unsigned (x, y))));
71 enum bignum_comparison factor_vm::bignum_compare(bignum * x, bignum * y)
75 ? ((BIGNUM_ZERO_P (y))
76 ? bignum_comparison_equal
77 : (BIGNUM_NEGATIVE_P (y))
78 ? bignum_comparison_greater
79 : bignum_comparison_less)
81 ? ((BIGNUM_NEGATIVE_P (x))
82 ? bignum_comparison_less
83 : bignum_comparison_greater)
84 : (BIGNUM_NEGATIVE_P (x))
85 ? ((BIGNUM_NEGATIVE_P (y))
86 ? (bignum_compare_unsigned (y, x))
87 : (bignum_comparison_less))
88 : ((BIGNUM_NEGATIVE_P (y))
89 ? (bignum_comparison_greater)
90 : (bignum_compare_unsigned (x, y))));
93 /* Allocates memory */
94 bignum *factor_vm::bignum_add(bignum * x, bignum * y)
101 : ((BIGNUM_NEGATIVE_P (x))
102 ? ((BIGNUM_NEGATIVE_P (y))
103 ? (bignum_add_unsigned (x, y, 1))
104 : (bignum_subtract_unsigned (y, x)))
105 : ((BIGNUM_NEGATIVE_P (y))
106 ? (bignum_subtract_unsigned (x, y))
107 : (bignum_add_unsigned (x, y, 0)))));
110 /* Allocates memory */
111 bignum *factor_vm::bignum_subtract(bignum * x, bignum * y)
115 ? ((BIGNUM_ZERO_P (y))
117 : (bignum_new_sign (y, (! (BIGNUM_NEGATIVE_P (y))))))
118 : ((BIGNUM_ZERO_P (y))
120 : ((BIGNUM_NEGATIVE_P (x))
121 ? ((BIGNUM_NEGATIVE_P (y))
122 ? (bignum_subtract_unsigned (y, x))
123 : (bignum_add_unsigned (x, y, 1)))
124 : ((BIGNUM_NEGATIVE_P (y))
125 ? (bignum_add_unsigned (x, y, 0))
126 : (bignum_subtract_unsigned (x, y))))));
129 /* Allocates memory */
130 bignum *factor_vm::bignum_multiply(bignum * x, bignum * y)
132 bignum_length_type x_length = (BIGNUM_LENGTH (x));
133 bignum_length_type y_length = (BIGNUM_LENGTH (y));
135 ((BIGNUM_NEGATIVE_P (x))
136 ? (! (BIGNUM_NEGATIVE_P (y)))
137 : (BIGNUM_NEGATIVE_P (y)));
138 if (BIGNUM_ZERO_P (x))
140 if (BIGNUM_ZERO_P (y))
144 bignum_digit_type digit = (BIGNUM_REF (x, 0));
146 return (bignum_maybe_new_sign (y, negative_p));
147 if (digit < BIGNUM_RADIX_ROOT)
148 return (bignum_multiply_unsigned_small_factor (y, digit, negative_p));
152 bignum_digit_type digit = (BIGNUM_REF (y, 0));
154 return (bignum_maybe_new_sign (x, negative_p));
155 if (digit < BIGNUM_RADIX_ROOT)
156 return (bignum_multiply_unsigned_small_factor (x, digit, negative_p));
158 return (bignum_multiply_unsigned (x, y, negative_p));
161 /* Allocates memory */
162 void factor_vm::bignum_divide(bignum * numerator, bignum * denominator, bignum * * quotient, bignum * * remainder)
164 if (BIGNUM_ZERO_P (denominator))
166 divide_by_zero_error();
169 if (BIGNUM_ZERO_P (numerator))
171 (*quotient) = numerator;
172 (*remainder) = numerator;
176 int r_negative_p = (BIGNUM_NEGATIVE_P (numerator));
178 ((BIGNUM_NEGATIVE_P (denominator)) ? (! r_negative_p) : r_negative_p);
179 switch (bignum_compare_unsigned (numerator, denominator))
181 case bignum_comparison_equal:
183 (*quotient) = (BIGNUM_ONE (q_negative_p));
184 (*remainder) = (BIGNUM_ZERO ());
187 case bignum_comparison_less:
189 (*quotient) = (BIGNUM_ZERO ());
190 (*remainder) = numerator;
193 case bignum_comparison_greater:
195 if ((BIGNUM_LENGTH (denominator)) == 1)
197 bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
201 (bignum_maybe_new_sign (numerator, q_negative_p));
202 (*remainder) = (BIGNUM_ZERO ());
205 else if (digit < BIGNUM_RADIX_ROOT)
207 bignum_divide_unsigned_small_denominator
210 q_negative_p, r_negative_p);
215 bignum_divide_unsigned_medium_denominator
218 q_negative_p, r_negative_p);
222 bignum_divide_unsigned_large_denominator
223 (numerator, denominator,
225 q_negative_p, r_negative_p);
232 /* Allocates memory */
233 bignum *factor_vm::bignum_quotient(bignum * numerator, bignum * denominator)
235 if (BIGNUM_ZERO_P (denominator))
237 divide_by_zero_error();
238 return (BIGNUM_OUT_OF_BAND);
240 if (BIGNUM_ZERO_P (numerator))
244 ((BIGNUM_NEGATIVE_P (denominator))
245 ? (! (BIGNUM_NEGATIVE_P (numerator)))
246 : (BIGNUM_NEGATIVE_P (numerator)));
247 switch (bignum_compare_unsigned (numerator, denominator))
249 case bignum_comparison_equal:
250 return (BIGNUM_ONE (q_negative_p));
251 case bignum_comparison_less:
252 return (BIGNUM_ZERO ());
253 case bignum_comparison_greater:
254 default: /* to appease gcc -Wall */
257 if ((BIGNUM_LENGTH (denominator)) == 1)
259 bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
261 return (bignum_maybe_new_sign (numerator, q_negative_p));
262 if (digit < BIGNUM_RADIX_ROOT)
263 bignum_divide_unsigned_small_denominator
265 ("ient), ((bignum * *) 0),
268 bignum_divide_unsigned_medium_denominator
270 ("ient), ((bignum * *) 0),
274 bignum_divide_unsigned_large_denominator
275 (numerator, denominator,
276 ("ient), ((bignum * *) 0),
284 /* Allocates memory */
285 bignum *factor_vm::bignum_remainder(bignum * numerator, bignum * denominator)
287 if (BIGNUM_ZERO_P (denominator))
289 divide_by_zero_error();
290 return (BIGNUM_OUT_OF_BAND);
292 if (BIGNUM_ZERO_P (numerator))
294 switch (bignum_compare_unsigned (numerator, denominator))
296 case bignum_comparison_equal:
297 return (BIGNUM_ZERO ());
298 case bignum_comparison_less:
300 case bignum_comparison_greater:
301 default: /* to appease gcc -Wall */
304 if ((BIGNUM_LENGTH (denominator)) == 1)
306 bignum_digit_type digit = (BIGNUM_REF (denominator, 0));
308 return (BIGNUM_ZERO ());
309 if (digit < BIGNUM_RADIX_ROOT)
311 (bignum_remainder_unsigned_small_denominator
312 (numerator, digit, (BIGNUM_NEGATIVE_P (numerator))));
313 bignum_divide_unsigned_medium_denominator
315 ((bignum * *) 0), (&remainder),
316 0, (BIGNUM_NEGATIVE_P (numerator)));
319 bignum_divide_unsigned_large_denominator
320 (numerator, denominator,
321 ((bignum * *) 0), (&remainder),
322 0, (BIGNUM_NEGATIVE_P (numerator)));
328 /* cell_to_bignum, fixnum_to_bignum, long_long_to_bignum, ulong_long_to_bignum */
329 /* Allocates memory */
330 #define FOO_TO_BIGNUM(name,type,stype,utype) \
331 bignum * factor_vm::name##_to_bignum(type n) \
334 bignum_digit_type result_digits [BIGNUM_DIGITS_FOR(type)]; \
335 bignum_digit_type * end_digits = result_digits; \
336 /* Special cases win when these small constants are cached. */ \
337 if (n == 0) return (BIGNUM_ZERO ()); \
338 if (n == 1) return (BIGNUM_ONE (0)); \
339 if (n < (type)0 && n == (type)-1) return (BIGNUM_ONE (1)); \
341 utype accumulator = ((negative_p = (n < (type)0)) ? ((type)(-(stype)n)) : n); \
344 (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK); \
345 accumulator >>= BIGNUM_DIGIT_LENGTH; \
347 while (accumulator != 0); \
351 (allot_bignum ((end_digits - result_digits), negative_p)); \
352 bignum_digit_type * scan_digits = result_digits; \
353 bignum_digit_type * scan_result = (BIGNUM_START_PTR (result)); \
354 while (scan_digits < end_digits) \
355 (*scan_result++) = (*scan_digits++); \
360 FOO_TO_BIGNUM(cell,cell,fixnum,cell)
361 FOO_TO_BIGNUM(fixnum,fixnum,fixnum,cell)
362 FOO_TO_BIGNUM(long_long,s64,s64,u64)
363 FOO_TO_BIGNUM(ulong_long,u64,s64,u64)
365 /* cannot allocate memory */
366 /* bignum_to_cell, fixnum_to_cell, long_long_to_cell, ulong_long_to_cell */
367 #define BIGNUM_TO_FOO(name,type,stype,utype) \
368 type factor_vm::bignum_to_##name(bignum * bignum) \
370 if (BIGNUM_ZERO_P (bignum)) \
373 utype accumulator = 0; \
374 bignum_digit_type * start = (BIGNUM_START_PTR (bignum)); \
375 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum))); \
376 while (start < scan) \
377 accumulator = ((accumulator << BIGNUM_DIGIT_LENGTH) + (*--scan)); \
378 return ((BIGNUM_NEGATIVE_P (bignum)) ? ((type)(-(stype)accumulator)) : accumulator); \
382 BIGNUM_TO_FOO(cell,cell,fixnum,cell)
383 BIGNUM_TO_FOO(fixnum,fixnum,fixnum,cell)
384 BIGNUM_TO_FOO(long_long,s64,s64,u64)
385 BIGNUM_TO_FOO(ulong_long,u64,s64,u64)
387 #define DTB_WRITE_DIGIT(factor) \
389 significand *= (factor); \
390 digit = ((bignum_digit_type) significand); \
392 significand -= ((double) digit); \
395 #define inf std::numeric_limits<double>::infinity()
397 /* Allocates memory */
398 bignum *factor_vm::double_to_bignum(double x)
400 if (x == inf || x == -inf || x != x) return (BIGNUM_ZERO ());
402 double significand = (frexp (x, (&exponent)));
403 if (exponent <= 0) return (BIGNUM_ZERO ());
404 if (exponent == 1) return (BIGNUM_ONE (x < 0));
405 if (significand < 0) significand = (-significand);
407 bignum_length_type length = (BIGNUM_BITS_TO_DIGITS (exponent));
408 bignum * result = (allot_bignum (length, (x < 0)));
409 bignum_digit_type * start = (BIGNUM_START_PTR (result));
410 bignum_digit_type * scan = (start + length);
411 bignum_digit_type digit;
412 int odd_bits = (exponent % BIGNUM_DIGIT_LENGTH);
414 DTB_WRITE_DIGIT ((fixnum)1 << odd_bits);
417 if (significand == 0)
423 DTB_WRITE_DIGIT (BIGNUM_RADIX);
429 #undef DTB_WRITE_DIGIT
433 int factor_vm::bignum_equal_p_unsigned(bignum * x, bignum * y)
435 bignum_length_type length = (BIGNUM_LENGTH (x));
436 if (length != (BIGNUM_LENGTH (y)))
440 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
441 bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
442 bignum_digit_type * end_x = (scan_x + length);
443 while (scan_x < end_x)
444 if ((*scan_x++) != (*scan_y++))
450 enum bignum_comparison factor_vm::bignum_compare_unsigned(bignum * x, bignum * y)
452 bignum_length_type x_length = (BIGNUM_LENGTH (x));
453 bignum_length_type y_length = (BIGNUM_LENGTH (y));
454 if (x_length < y_length)
455 return (bignum_comparison_less);
456 if (x_length > y_length)
457 return (bignum_comparison_greater);
459 bignum_digit_type * start_x = (BIGNUM_START_PTR (x));
460 bignum_digit_type * scan_x = (start_x + x_length);
461 bignum_digit_type * scan_y = ((BIGNUM_START_PTR (y)) + y_length);
462 while (start_x < scan_x)
464 bignum_digit_type digit_x = (*--scan_x);
465 bignum_digit_type digit_y = (*--scan_y);
466 if (digit_x < digit_y)
467 return (bignum_comparison_less);
468 if (digit_x > digit_y)
469 return (bignum_comparison_greater);
472 return (bignum_comparison_equal);
477 /* Allocates memory */
478 bignum *factor_vm::bignum_add_unsigned(bignum * x, bignum * y, int negative_p)
480 GC_BIGNUM(x); GC_BIGNUM(y);
482 if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
489 bignum_length_type x_length = (BIGNUM_LENGTH (x));
491 bignum * r = (allot_bignum ((x_length + 1), negative_p));
493 bignum_digit_type sum;
494 bignum_digit_type carry = 0;
495 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
496 bignum_digit_type * scan_r = (BIGNUM_START_PTR (r));
498 bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
499 bignum_digit_type * end_y = (scan_y + (BIGNUM_LENGTH (y)));
500 while (scan_y < end_y)
502 sum = ((*scan_x++) + (*scan_y++) + carry);
503 if (sum < BIGNUM_RADIX)
510 (*scan_r++) = (sum - BIGNUM_RADIX);
516 bignum_digit_type * end_x = ((BIGNUM_START_PTR (x)) + x_length);
518 while (scan_x < end_x)
520 sum = ((*scan_x++) + 1);
521 if (sum < BIGNUM_RADIX)
528 (*scan_r++) = (sum - BIGNUM_RADIX);
530 while (scan_x < end_x)
531 (*scan_r++) = (*scan_x++);
538 return (bignum_shorten_length (r, x_length));
544 /* Allocates memory */
545 bignum *factor_vm::bignum_subtract_unsigned(bignum * x, bignum * y)
547 GC_BIGNUM(x); GC_BIGNUM(y);
550 switch (bignum_compare_unsigned (x, y))
552 case bignum_comparison_equal:
553 return (BIGNUM_ZERO ());
554 case bignum_comparison_less:
562 case bignum_comparison_greater:
567 bignum_length_type x_length = (BIGNUM_LENGTH (x));
569 bignum * r = (allot_bignum (x_length, negative_p));
571 bignum_digit_type difference;
572 bignum_digit_type borrow = 0;
573 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
574 bignum_digit_type * scan_r = (BIGNUM_START_PTR (r));
576 bignum_digit_type * scan_y = (BIGNUM_START_PTR (y));
577 bignum_digit_type * end_y = (scan_y + (BIGNUM_LENGTH (y)));
578 while (scan_y < end_y)
580 difference = (((*scan_x++) - (*scan_y++)) - borrow);
583 (*scan_r++) = (difference + BIGNUM_RADIX);
588 (*scan_r++) = difference;
594 bignum_digit_type * end_x = ((BIGNUM_START_PTR (x)) + x_length);
596 while (scan_x < end_x)
598 difference = ((*scan_x++) - borrow);
600 (*scan_r++) = (difference + BIGNUM_RADIX);
603 (*scan_r++) = difference;
608 BIGNUM_ASSERT (borrow == 0);
609 while (scan_x < end_x)
610 (*scan_r++) = (*scan_x++);
612 return (bignum_trim (r));
617 Maximum value for product_low or product_high:
618 ((R * R) + (R * (R - 2)) + (R - 1))
619 Maximum value for carry: ((R * (R - 1)) + (R - 1))
620 where R == BIGNUM_RADIX_ROOT */
622 /* Allocates memory */
623 bignum *factor_vm::bignum_multiply_unsigned(bignum * x, bignum * y, int negative_p)
625 GC_BIGNUM(x); GC_BIGNUM(y);
627 if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
634 bignum_digit_type carry;
635 bignum_digit_type y_digit_low;
636 bignum_digit_type y_digit_high;
637 bignum_digit_type x_digit_low;
638 bignum_digit_type x_digit_high;
639 bignum_digit_type product_low;
640 bignum_digit_type * scan_r;
641 bignum_digit_type * scan_y;
642 bignum_length_type x_length = (BIGNUM_LENGTH (x));
643 bignum_length_type y_length = (BIGNUM_LENGTH (y));
646 (allot_bignum_zeroed ((x_length + y_length), negative_p));
648 bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
649 bignum_digit_type * end_x = (scan_x + x_length);
650 bignum_digit_type * start_y = (BIGNUM_START_PTR (y));
651 bignum_digit_type * end_y = (start_y + y_length);
652 bignum_digit_type * start_r = (BIGNUM_START_PTR (r));
653 #define x_digit x_digit_high
654 #define y_digit y_digit_high
655 #define product_high carry
656 while (scan_x < end_x)
658 x_digit = (*scan_x++);
659 x_digit_low = (HD_LOW (x_digit));
660 x_digit_high = (HD_HIGH (x_digit));
663 scan_r = (start_r++);
664 while (scan_y < end_y)
666 y_digit = (*scan_y++);
667 y_digit_low = (HD_LOW (y_digit));
668 y_digit_high = (HD_HIGH (y_digit));
671 (x_digit_low * y_digit_low) +
674 ((x_digit_high * y_digit_low) +
675 (x_digit_low * y_digit_high) +
676 (HD_HIGH (product_low)) +
679 (HD_CONS ((HD_LOW (product_high)), (HD_LOW (product_low))));
681 ((x_digit_high * y_digit_high) +
682 (HD_HIGH (product_high)));
686 return (bignum_trim (r));
693 /* Allocates memory */
694 bignum *factor_vm::bignum_multiply_unsigned_small_factor(bignum * x, bignum_digit_type y, int negative_p)
698 bignum_length_type length_x = (BIGNUM_LENGTH (x));
700 bignum * p = (allot_bignum ((length_x + 1), negative_p));
702 bignum_destructive_copy (x, p);
703 (BIGNUM_REF (p, length_x)) = 0;
704 bignum_destructive_scale_up (p, y);
705 return (bignum_trim (p));
708 void factor_vm::bignum_destructive_add(bignum * bignum, bignum_digit_type n)
710 bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
711 bignum_digit_type digit;
712 digit = ((*scan) + n);
713 if (digit < BIGNUM_RADIX)
718 (*scan++) = (digit - BIGNUM_RADIX);
721 digit = ((*scan) + 1);
722 if (digit < BIGNUM_RADIX)
727 (*scan++) = (digit - BIGNUM_RADIX);
731 void factor_vm::bignum_destructive_scale_up(bignum * bignum, bignum_digit_type factor)
733 bignum_digit_type carry = 0;
734 bignum_digit_type * scan = (BIGNUM_START_PTR (bignum));
735 bignum_digit_type two_digits;
736 bignum_digit_type product_low;
737 #define product_high carry
738 bignum_digit_type * end = (scan + (BIGNUM_LENGTH (bignum)));
739 BIGNUM_ASSERT ((factor > 1) && (factor < BIGNUM_RADIX_ROOT));
742 two_digits = (*scan);
743 product_low = ((factor * (HD_LOW (two_digits))) + (HD_LOW (carry)));
745 ((factor * (HD_HIGH (two_digits))) +
746 (HD_HIGH (product_low)) +
748 (*scan++) = (HD_CONS ((HD_LOW (product_high)), (HD_LOW (product_low))));
749 carry = (HD_HIGH (product_high));
751 /* A carry here would be an overflow, i.e. it would not fit.
752 Hopefully the callers allocate enough space that this will
755 BIGNUM_ASSERT (carry == 0);
762 /* For help understanding this algorithm, see:
763 Knuth, Donald E., "The Art of Computer Programming",
764 volume 2, "Seminumerical Algorithms"
765 section 4.3.1, "Multiple-Precision Arithmetic". */
767 /* Allocates memory */
768 void factor_vm::bignum_divide_unsigned_large_denominator(bignum * numerator, bignum * denominator, bignum * * quotient, bignum * * remainder, int q_negative_p, int r_negative_p)
770 GC_BIGNUM(numerator); GC_BIGNUM(denominator);
772 bignum_length_type length_n = ((BIGNUM_LENGTH (numerator)) + 1);
773 bignum_length_type length_d = (BIGNUM_LENGTH (denominator));
776 ((quotient != ((bignum * *) 0))
777 ? (allot_bignum ((length_n - length_d), q_negative_p))
778 : BIGNUM_OUT_OF_BAND);
781 bignum * u = (allot_bignum (length_n, r_negative_p));
785 BIGNUM_ASSERT (length_d > 1);
787 bignum_digit_type v1 = (BIGNUM_REF ((denominator), (length_d - 1)));
788 while (v1 < (BIGNUM_RADIX / 2))
796 bignum_destructive_copy (numerator, u);
797 (BIGNUM_REF (u, (length_n - 1))) = 0;
798 bignum_divide_unsigned_normalized (u, denominator, q);
802 bignum * v = (allot_bignum (length_d, 0));
804 bignum_destructive_normalization (numerator, u, shift);
805 bignum_destructive_normalization (denominator, v, shift);
806 bignum_divide_unsigned_normalized (u, v, q);
807 if (remainder != ((bignum * *) 0))
808 bignum_destructive_unnormalization (u, shift);
816 if (quotient != ((bignum * *) 0))
819 if (remainder != ((bignum * *) 0))
825 void factor_vm::bignum_divide_unsigned_normalized(bignum * u, bignum * v, bignum * q)
827 bignum_length_type u_length = (BIGNUM_LENGTH (u));
828 bignum_length_type v_length = (BIGNUM_LENGTH (v));
829 bignum_digit_type * u_start = (BIGNUM_START_PTR (u));
830 bignum_digit_type * u_scan = (u_start + u_length);
831 bignum_digit_type * u_scan_limit = (u_start + v_length);
832 bignum_digit_type * u_scan_start = (u_scan - v_length);
833 bignum_digit_type * v_start = (BIGNUM_START_PTR (v));
834 bignum_digit_type * v_end = (v_start + v_length);
835 bignum_digit_type * q_scan = NULL;
836 bignum_digit_type v1 = (v_end[-1]);
837 bignum_digit_type v2 = (v_end[-2]);
838 bignum_digit_type ph; /* high half of double-digit product */
839 bignum_digit_type pl; /* low half of double-digit product */
840 bignum_digit_type guess;
841 bignum_digit_type gh; /* high half-digit of guess */
842 bignum_digit_type ch; /* high half of double-digit comparand */
843 bignum_digit_type v2l = (HD_LOW (v2));
844 bignum_digit_type v2h = (HD_HIGH (v2));
845 bignum_digit_type cl; /* low half of double-digit comparand */
846 #define gl ph /* low half-digit of guess */
849 bignum_digit_type gm; /* memory loc for reference parameter */
850 if (q != BIGNUM_OUT_OF_BAND)
851 q_scan = ((BIGNUM_START_PTR (q)) + (BIGNUM_LENGTH (q)));
852 while (u_scan_limit < u_scan)
858 (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
859 guess = (((uj * BIGNUM_RADIX) + uj1) / v1); */
861 ch = (bignum_digit_divide (uj, (u_scan[-1]), v1, (&gm)));
867 ch = ((u_scan[-1]) + v1);
868 guess = (BIGNUM_RADIX - 1);
872 /* product = (guess * v2); */
873 gl = (HD_LOW (guess));
874 gh = (HD_HIGH (guess));
876 ph = ((v2l * gh) + (v2h * gl) + (HD_HIGH (pl)));
877 pl = (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl))));
878 ph = ((v2h * gh) + (HD_HIGH (ph)));
879 /* if (comparand >= product) */
880 if ((ch > ph) || ((ch == ph) && (cl >= pl)))
883 /* comparand += (v1 << BIGNUM_DIGIT_LENGTH) */
885 /* if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX)) */
886 if (ch >= BIGNUM_RADIX)
889 qj = (bignum_divide_subtract (v_start, v_end, guess, (--u_scan_start)));
890 if (q != BIGNUM_OUT_OF_BAND)
899 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)
901 bignum_digit_type * v_scan = v_start;
902 bignum_digit_type * u_scan = u_start;
903 bignum_digit_type carry = 0;
904 if (guess == 0) return (0);
906 bignum_digit_type gl = (HD_LOW (guess));
907 bignum_digit_type gh = (HD_HIGH (guess));
909 bignum_digit_type pl;
910 bignum_digit_type vl;
914 while (v_scan < v_end)
919 pl = ((vl * gl) + (HD_LOW (carry)));
920 ph = ((vl * gh) + (vh * gl) + (HD_HIGH (pl)) + (HD_HIGH (carry)));
921 diff = ((*u_scan) - (HD_CONS ((HD_LOW (ph)), (HD_LOW (pl)))));
924 (*u_scan++) = (diff + BIGNUM_RADIX);
925 carry = ((vh * gh) + (HD_HIGH (ph)) + 1);
930 carry = ((vh * gh) + (HD_HIGH (ph)));
935 diff = ((*u_scan) - carry);
937 (*u_scan) = (diff + BIGNUM_RADIX);
947 /* Subtraction generated carry, implying guess is one too large.
948 Add v back in to bring it back down. */
952 while (v_scan < v_end)
954 bignum_digit_type sum = ((*v_scan++) + (*u_scan) + carry);
955 if (sum < BIGNUM_RADIX)
962 (*u_scan++) = (sum - BIGNUM_RADIX);
968 bignum_digit_type sum = ((*u_scan) + carry);
969 (*u_scan) = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
974 /* Allocates memory */
975 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)
977 GC_BIGNUM(numerator);
979 bignum_length_type length_n = (BIGNUM_LENGTH (numerator));
980 bignum_length_type length_q;
985 /* Because `bignum_digit_divide' requires a normalized denominator. */
986 while (denominator < (BIGNUM_RADIX / 2))
995 q = (allot_bignum (length_q, q_negative_p));
996 bignum_destructive_copy (numerator, q);
1000 length_q = (length_n + 1);
1002 q = (allot_bignum (length_q, q_negative_p));
1003 bignum_destructive_normalization (numerator, q, shift);
1006 bignum_digit_type r = 0;
1007 bignum_digit_type * start = (BIGNUM_START_PTR (q));
1008 bignum_digit_type * scan = (start + length_q);
1009 bignum_digit_type qj;
1011 while (start < scan)
1013 r = (bignum_digit_divide (r, (*--scan), denominator, (&qj)));
1017 q = bignum_trim (q);
1019 if (remainder != ((bignum * *) 0))
1024 (*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
1027 if (quotient != ((bignum * *) 0))
1033 void factor_vm::bignum_destructive_normalization(bignum * source, bignum * target, int shift_left)
1035 bignum_digit_type digit;
1036 bignum_digit_type * scan_source = (BIGNUM_START_PTR (source));
1037 bignum_digit_type carry = 0;
1038 bignum_digit_type * scan_target = (BIGNUM_START_PTR (target));
1039 bignum_digit_type * end_source = (scan_source + (BIGNUM_LENGTH (source)));
1040 bignum_digit_type * end_target = (scan_target + (BIGNUM_LENGTH (target)));
1041 int shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
1042 bignum_digit_type mask = (((cell)1 << shift_right) - 1);
1043 while (scan_source < end_source)
1045 digit = (*scan_source++);
1046 (*scan_target++) = (((digit & mask) << shift_left) | carry);
1047 carry = (digit >> shift_right);
1049 if (scan_target < end_target)
1050 (*scan_target) = carry;
1052 BIGNUM_ASSERT (carry == 0);
1056 void factor_vm::bignum_destructive_unnormalization(bignum * bignum, int shift_right)
1058 bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
1059 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
1060 bignum_digit_type digit;
1061 bignum_digit_type carry = 0;
1062 int shift_left = (BIGNUM_DIGIT_LENGTH - shift_right);
1063 bignum_digit_type mask = (((fixnum)1 << shift_right) - 1);
1064 while (start < scan)
1067 (*scan) = ((digit >> shift_right) | carry);
1068 carry = ((digit & mask) << shift_left);
1070 BIGNUM_ASSERT (carry == 0);
1074 /* This is a reduced version of the division algorithm, applied to the
1075 case of dividing two bignum digits by one bignum digit. It is
1076 assumed that the numerator, denominator are normalized. */
1078 #define BDD_STEP(qn, j) \
1083 uj_uj1 = (HD_CONS (uj, (u[j + 1]))); \
1084 guess = (uj_uj1 / v1); \
1085 comparand = (HD_CONS ((uj_uj1 % v1), (u[j + 2]))); \
1089 guess = (BIGNUM_RADIX_ROOT - 1); \
1090 comparand = (HD_CONS (((u[j + 1]) + v1), (u[j + 2]))); \
1092 while ((guess * v2) > comparand) \
1095 comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH); \
1096 if (comparand >= BIGNUM_RADIX) \
1099 qn = (bignum_digit_divide_subtract (v1, v2, guess, (&u[j]))); \
1102 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 */
1104 bignum_digit_type guess;
1105 bignum_digit_type comparand;
1106 bignum_digit_type v1 = (HD_HIGH (v));
1107 bignum_digit_type v2 = (HD_LOW (v));
1108 bignum_digit_type uj;
1109 bignum_digit_type uj_uj1;
1110 bignum_digit_type q1;
1111 bignum_digit_type q2;
1112 bignum_digit_type u [4];
1126 (u[0]) = (HD_HIGH (uh));
1127 (u[1]) = (HD_LOW (uh));
1128 (u[2]) = (HD_HIGH (ul));
1129 (u[3]) = (HD_LOW (ul));
1134 (*q) = (HD_CONS (q1, q2));
1135 return (HD_CONS ((u[2]), (u[3])));
1140 #define BDDS_MULSUB(vn, un, carry_in) \
1142 product = ((vn * guess) + carry_in); \
1143 diff = (un - (HD_LOW (product))); \
1146 un = (diff + BIGNUM_RADIX_ROOT); \
1147 carry = ((HD_HIGH (product)) + 1); \
1152 carry = (HD_HIGH (product)); \
1156 #define BDDS_ADD(vn, un, carry_in) \
1158 sum = (vn + un + carry_in); \
1159 if (sum < BIGNUM_RADIX_ROOT) \
1166 un = (sum - BIGNUM_RADIX_ROOT); \
1171 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)
1174 bignum_digit_type product;
1175 bignum_digit_type diff;
1176 bignum_digit_type carry;
1177 BDDS_MULSUB (v2, (u[2]), 0);
1178 BDDS_MULSUB (v1, (u[1]), carry);
1181 diff = ((u[0]) - carry);
1183 (u[0]) = (diff + BIGNUM_RADIX);
1191 bignum_digit_type sum;
1192 bignum_digit_type carry;
1193 BDDS_ADD(v2, (u[2]), 0);
1194 BDDS_ADD(v1, (u[1]), carry);
1204 /* Allocates memory */
1205 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)
1207 GC_BIGNUM(numerator);
1209 bignum * q = (bignum_new_sign (numerator, q_negative_p));
1212 bignum_digit_type r = (bignum_destructive_scale_down (q, denominator));
1214 q = (bignum_trim (q));
1216 if (remainder != ((bignum * *) 0))
1217 (*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
1224 /* Given (denominator > 1), it is fairly easy to show that
1225 (quotient_high < BIGNUM_RADIX_ROOT), after which it is easy to see
1226 that all digits are < BIGNUM_RADIX. */
1228 bignum_digit_type factor_vm::bignum_destructive_scale_down(bignum * bignum, bignum_digit_type denominator)
1230 bignum_digit_type numerator;
1231 bignum_digit_type remainder = 0;
1232 bignum_digit_type two_digits;
1233 #define quotient_high remainder
1234 bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
1235 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (bignum)));
1236 BIGNUM_ASSERT ((denominator > 1) && (denominator < BIGNUM_RADIX_ROOT));
1237 while (start < scan)
1239 two_digits = (*--scan);
1240 numerator = (HD_CONS (remainder, (HD_HIGH (two_digits))));
1241 quotient_high = (numerator / denominator);
1242 numerator = (HD_CONS ((numerator % denominator), (HD_LOW (two_digits))));
1243 (*scan) = (HD_CONS (quotient_high, (numerator / denominator)));
1244 remainder = (numerator % denominator);
1247 #undef quotient_high
1250 /* Allocates memory */
1251 bignum * factor_vm::bignum_remainder_unsigned_small_denominator(bignum * n, bignum_digit_type d, int negative_p)
1253 bignum_digit_type two_digits;
1254 bignum_digit_type * start = (BIGNUM_START_PTR (n));
1255 bignum_digit_type * scan = (start + (BIGNUM_LENGTH (n)));
1256 bignum_digit_type r = 0;
1257 BIGNUM_ASSERT ((d > 1) && (d < BIGNUM_RADIX_ROOT));
1258 while (start < scan)
1260 two_digits = (*--scan);
1262 ((HD_CONS (((HD_CONS (r, (HD_HIGH (two_digits)))) % d),
1263 (HD_LOW (two_digits))))
1266 return (bignum_digit_to_bignum (r, negative_p));
1269 /* Allocates memory */
1270 bignum *factor_vm::bignum_digit_to_bignum(bignum_digit_type digit, int negative_p)
1273 return (BIGNUM_ZERO ());
1276 bignum * result = (allot_bignum (1, negative_p));
1277 (BIGNUM_REF (result, 0)) = digit;
1282 /* Allocates memory */
1283 bignum *factor_vm::allot_bignum(bignum_length_type length, int negative_p)
1285 BIGNUM_ASSERT ((length >= 0) || (length < BIGNUM_RADIX));
1286 bignum * result = allot_uninitialized_array<bignum>(length + 1);
1287 BIGNUM_SET_NEGATIVE_P (result, negative_p);
1291 /* Allocates memory */
1292 bignum * factor_vm::allot_bignum_zeroed(bignum_length_type length, int negative_p)
1294 bignum * result = allot_bignum(length,negative_p);
1295 bignum_digit_type * scan = (BIGNUM_START_PTR (result));
1296 bignum_digit_type * end = (scan + length);
1302 /* can allocate if not in nursery or size is larger */
1303 /* Allocates memory conditionally */
1304 #define BIGNUM_REDUCE_LENGTH(source, length) \
1305 source = reallot_array(source,length + 1)
1307 /* Allocates memory */
1308 bignum *factor_vm::bignum_shorten_length(bignum * bignum, bignum_length_type length)
1310 bignum_length_type current_length = (BIGNUM_LENGTH (bignum));
1311 BIGNUM_ASSERT ((length >= 0) || (length <= current_length));
1312 if (length < current_length)
1315 BIGNUM_REDUCE_LENGTH (bignum, length);
1316 BIGNUM_SET_NEGATIVE_P (bignum, (length != 0) && (BIGNUM_NEGATIVE_P (bignum)));
1321 /* Allocates memory */
1322 bignum *factor_vm::bignum_trim(bignum * bignum)
1324 bignum_digit_type * start = (BIGNUM_START_PTR (bignum));
1325 bignum_digit_type * end = (start + (BIGNUM_LENGTH (bignum)));
1326 bignum_digit_type * scan = end;
1327 while ((start <= scan) && ((*--scan) == 0))
1333 bignum_length_type length = (scan - start);
1334 BIGNUM_REDUCE_LENGTH (bignum, length);
1335 BIGNUM_SET_NEGATIVE_P (bignum, (length != 0) && (BIGNUM_NEGATIVE_P (bignum)));
1342 /* Allocates memory */
1343 bignum *factor_vm::bignum_new_sign(bignum * x, int negative_p)
1346 bignum * result = (allot_bignum ((BIGNUM_LENGTH (x)), negative_p));
1348 bignum_destructive_copy (x, result);
1352 /* Allocates memory */
1353 bignum *factor_vm::bignum_maybe_new_sign(bignum * x, int negative_p)
1355 if ((BIGNUM_NEGATIVE_P (x)) ? negative_p : (! negative_p))
1361 (allot_bignum ((BIGNUM_LENGTH (x)), negative_p));
1362 bignum_destructive_copy (x, result);
1367 void factor_vm::bignum_destructive_copy(bignum * source, bignum * target)
1369 bignum_digit_type * scan_source = (BIGNUM_START_PTR (source));
1370 bignum_digit_type * end_source =
1371 (scan_source + (BIGNUM_LENGTH (source)));
1372 bignum_digit_type * scan_target = (BIGNUM_START_PTR (target));
1373 while (scan_source < end_source)
1374 (*scan_target++) = (*scan_source++);
1379 * Added bitwise operations (and oddp).
1382 /* Allocates memory */
1383 bignum *factor_vm::bignum_bitwise_not(bignum * x)
1387 bignum_length_type size = BIGNUM_LENGTH (x);
1388 bignum_digit_type *scan_x, *end_x, *scan_y;
1392 if (BIGNUM_NEGATIVE_P (x)) {
1393 y = allot_bignum (size, 0);
1394 scan_x = BIGNUM_START_PTR (x);
1395 end_x = scan_x + size;
1396 scan_y = BIGNUM_START_PTR (y);
1397 while (scan_x < end_x) {
1399 *scan_y++ = BIGNUM_RADIX - 1;
1402 *scan_y++ = *scan_x++ - 1;
1408 y = allot_bignum (size, 1);
1409 scan_x = BIGNUM_START_PTR (x);
1410 end_x = scan_x + size;
1411 scan_y = BIGNUM_START_PTR (y);
1412 while (scan_x < end_x) {
1413 if (*scan_x == (BIGNUM_RADIX - 1)) {
1417 *scan_y++ = *scan_x++ + 1;
1424 while (scan_x < end_x) {
1425 *scan_y++ = *scan_x++;
1430 x = allot_bignum (size + 1, BIGNUM_NEGATIVE_P (y));
1431 bignum_destructive_copy (y, x);
1432 scan_x = BIGNUM_START_PTR (x);
1433 *(scan_x + size) = 1;
1436 return bignum_trim (y);
1440 /* Allocates memory */
1441 bignum *factor_vm::bignum_arithmetic_shift(bignum * arg1, fixnum n)
1443 if (BIGNUM_NEGATIVE_P(arg1) && n < 0)
1444 return bignum_bitwise_not(bignum_magnitude_ash(bignum_bitwise_not(arg1), n));
1446 return bignum_magnitude_ash(arg1, n);
1453 /* Allocates memory */
1454 bignum *factor_vm::bignum_bitwise_and(bignum * arg1, bignum * arg2)
1457 (BIGNUM_NEGATIVE_P (arg1))
1458 ? (BIGNUM_NEGATIVE_P (arg2))
1459 ? bignum_negneg_bitwise_op(AND_OP, arg1, arg2)
1460 : bignum_posneg_bitwise_op(AND_OP, arg2, arg1)
1461 : (BIGNUM_NEGATIVE_P (arg2))
1462 ? bignum_posneg_bitwise_op(AND_OP, arg1, arg2)
1463 : bignum_pospos_bitwise_op(AND_OP, arg1, arg2)
1467 /* Allocates memory */
1468 bignum *factor_vm::bignum_bitwise_ior(bignum * arg1, bignum * arg2)
1471 (BIGNUM_NEGATIVE_P (arg1))
1472 ? (BIGNUM_NEGATIVE_P (arg2))
1473 ? bignum_negneg_bitwise_op(IOR_OP, arg1, arg2)
1474 : bignum_posneg_bitwise_op(IOR_OP, arg2, arg1)
1475 : (BIGNUM_NEGATIVE_P (arg2))
1476 ? bignum_posneg_bitwise_op(IOR_OP, arg1, arg2)
1477 : bignum_pospos_bitwise_op(IOR_OP, arg1, arg2)
1481 /* Allocates memory */
1482 bignum *factor_vm::bignum_bitwise_xor(bignum * arg1, bignum * arg2)
1485 (BIGNUM_NEGATIVE_P (arg1))
1486 ? (BIGNUM_NEGATIVE_P (arg2))
1487 ? bignum_negneg_bitwise_op(XOR_OP, arg1, arg2)
1488 : bignum_posneg_bitwise_op(XOR_OP, arg2, arg1)
1489 : (BIGNUM_NEGATIVE_P (arg2))
1490 ? bignum_posneg_bitwise_op(XOR_OP, arg1, arg2)
1491 : bignum_pospos_bitwise_op(XOR_OP, arg1, arg2)
1495 /* Allocates memory */
1496 /* ash for the magnitude */
1497 /* assume arg1 is a big number, n is a long */
1498 bignum *factor_vm::bignum_magnitude_ash(bignum * arg1, fixnum n)
1502 bignum * result = NULL;
1503 bignum_digit_type *scan1;
1504 bignum_digit_type *scanr;
1505 bignum_digit_type *end;
1507 fixnum digit_offset,bit_offset;
1509 if (BIGNUM_ZERO_P (arg1)) return (arg1);
1512 digit_offset = n / BIGNUM_DIGIT_LENGTH;
1513 bit_offset = n % BIGNUM_DIGIT_LENGTH;
1515 result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) + digit_offset + 1,
1516 BIGNUM_NEGATIVE_P(arg1));
1518 scanr = BIGNUM_START_PTR (result) + digit_offset;
1519 scan1 = BIGNUM_START_PTR (arg1);
1520 end = scan1 + BIGNUM_LENGTH (arg1);
1522 while (scan1 < end) {
1523 *scanr = *scanr | (*scan1 & BIGNUM_DIGIT_MASK) << bit_offset;
1524 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1526 *scanr = *scan1++ >> (BIGNUM_DIGIT_LENGTH - bit_offset);
1527 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1531 && (-n >= (BIGNUM_LENGTH (arg1) * (bignum_length_type) BIGNUM_DIGIT_LENGTH)))
1532 result = BIGNUM_ZERO ();
1535 digit_offset = -n / BIGNUM_DIGIT_LENGTH;
1536 bit_offset = -n % BIGNUM_DIGIT_LENGTH;
1538 result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) - digit_offset,
1539 BIGNUM_NEGATIVE_P(arg1));
1541 scanr = BIGNUM_START_PTR (result);
1542 scan1 = BIGNUM_START_PTR (arg1) + digit_offset;
1543 end = scanr + BIGNUM_LENGTH (result) - 1;
1545 while (scanr < end) {
1546 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset ;
1548 *scan1 << (BIGNUM_DIGIT_LENGTH - bit_offset)) & BIGNUM_DIGIT_MASK;
1551 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset ;
1553 else if (n == 0) result = arg1;
1555 return (bignum_trim (result));
1558 /* Allocates memory */
1559 bignum *factor_vm::bignum_pospos_bitwise_op(int op, bignum * arg1, bignum * arg2)
1561 GC_BIGNUM(arg1); GC_BIGNUM(arg2);
1564 bignum_length_type max_length;
1566 bignum_digit_type *scan1, *end1, digit1;
1567 bignum_digit_type *scan2, *end2, digit2;
1568 bignum_digit_type *scanr, *endr;
1570 max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
1571 ? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2);
1573 result = allot_bignum(max_length, 0);
1575 scanr = BIGNUM_START_PTR(result);
1576 scan1 = BIGNUM_START_PTR(arg1);
1577 scan2 = BIGNUM_START_PTR(arg2);
1578 endr = scanr + max_length;
1579 end1 = scan1 + BIGNUM_LENGTH(arg1);
1580 end2 = scan2 + BIGNUM_LENGTH(arg2);
1582 while (scanr < endr) {
1583 digit1 = (scan1 < end1) ? *scan1++ : 0;
1584 digit2 = (scan2 < end2) ? *scan2++ : 0;
1585 *scanr++ = (op == AND_OP) ? digit1 & digit2 :
1586 (op == IOR_OP) ? digit1 | digit2 :
1589 return bignum_trim(result);
1592 /* Allocates memory */
1593 bignum *factor_vm::bignum_posneg_bitwise_op(int op, bignum * arg1, bignum * arg2)
1595 GC_BIGNUM(arg1); GC_BIGNUM(arg2);
1598 bignum_length_type max_length;
1600 bignum_digit_type *scan1, *end1, digit1;
1601 bignum_digit_type *scan2, *end2, digit2, carry2;
1602 bignum_digit_type *scanr, *endr;
1604 char neg_p = op == IOR_OP || op == XOR_OP;
1606 max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1)
1607 ? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2) + 1;
1609 result = allot_bignum(max_length, neg_p);
1611 scanr = BIGNUM_START_PTR(result);
1612 scan1 = BIGNUM_START_PTR(arg1);
1613 scan2 = BIGNUM_START_PTR(arg2);
1614 endr = scanr + max_length;
1615 end1 = scan1 + BIGNUM_LENGTH(arg1);
1616 end2 = scan2 + BIGNUM_LENGTH(arg2);
1620 while (scanr < endr) {
1621 digit1 = (scan1 < end1) ? *scan1++ : 0;
1622 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK)
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 /* Allocates memory */
1645 bignum *factor_vm::bignum_negneg_bitwise_op(int op, bignum * arg1, bignum * arg2)
1647 GC_BIGNUM(arg1); GC_BIGNUM(arg2);
1650 bignum_length_type max_length;
1652 bignum_digit_type *scan1, *end1, digit1, carry1;
1653 bignum_digit_type *scan2, *end2, digit2, carry2;
1654 bignum_digit_type *scanr, *endr;
1656 char neg_p = op == AND_OP || op == IOR_OP;
1658 max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
1659 ? BIGNUM_LENGTH(arg1) + 1 : BIGNUM_LENGTH(arg2) + 1;
1661 result = allot_bignum(max_length, neg_p);
1663 scanr = BIGNUM_START_PTR(result);
1664 scan1 = BIGNUM_START_PTR(arg1);
1665 scan2 = BIGNUM_START_PTR(arg2);
1666 endr = scanr + max_length;
1667 end1 = scan1 + BIGNUM_LENGTH(arg1);
1668 end2 = scan2 + BIGNUM_LENGTH(arg2);
1673 while (scanr < endr) {
1674 digit1 = (~((scan1 < end1) ? *scan1++ : 0) & BIGNUM_DIGIT_MASK) + carry1;
1675 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
1677 if (digit1 < BIGNUM_RADIX)
1681 digit1 = (digit1 - BIGNUM_RADIX);
1685 if (digit2 < BIGNUM_RADIX)
1689 digit2 = (digit2 - BIGNUM_RADIX);
1693 *scanr++ = (op == AND_OP) ? digit1 & digit2 :
1694 (op == IOR_OP) ? digit1 | digit2 :
1699 bignum_negate_magnitude(result);
1701 return bignum_trim(result);
1704 void factor_vm::bignum_negate_magnitude(bignum * arg)
1706 bignum_digit_type *scan;
1707 bignum_digit_type *end;
1708 bignum_digit_type digit;
1709 bignum_digit_type carry;
1711 scan = BIGNUM_START_PTR(arg);
1712 end = scan + BIGNUM_LENGTH(arg);
1716 while (scan < end) {
1717 digit = (~*scan & BIGNUM_DIGIT_MASK) + carry;
1719 if (digit < BIGNUM_RADIX)
1723 digit = (digit - BIGNUM_RADIX);
1731 /* Allocates memory */
1732 bignum *factor_vm::bignum_integer_length(bignum * x)
1736 bignum_length_type index = ((BIGNUM_LENGTH (x)) - 1);
1737 bignum_digit_type digit = (BIGNUM_REF (x, index));
1739 bignum * result = (allot_bignum (2, 0));
1741 (BIGNUM_REF (result, 0)) = index;
1742 (BIGNUM_REF (result, 1)) = 0;
1743 bignum_destructive_scale_up (result, BIGNUM_DIGIT_LENGTH);
1746 bignum_destructive_add (result, ((bignum_digit_type) 1));
1749 return (bignum_trim (result));
1752 /* Allocates memory */
1753 int factor_vm::bignum_logbitp(int shift, bignum * arg)
1755 return((BIGNUM_NEGATIVE_P (arg))
1756 ? !bignum_unsigned_logbitp (shift, bignum_bitwise_not (arg))
1757 : bignum_unsigned_logbitp (shift,arg));
1760 int factor_vm::bignum_unsigned_logbitp(int shift, bignum * bignum)
1762 bignum_length_type len = (BIGNUM_LENGTH (bignum));
1763 int index = shift / BIGNUM_DIGIT_LENGTH;
1766 bignum_digit_type digit = (BIGNUM_REF (bignum, index));
1767 int p = shift % BIGNUM_DIGIT_LENGTH;
1768 bignum_digit_type mask = ((fixnum)1) << p;
1769 return (digit & mask) ? 1 : 0;
1774 /* Allocates memory */
1775 bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
1780 bignum_length_type size_a, size_b;
1781 bignum_digit_type * scan_a, * scan_b, * scan_d, * a_end, * b_end;
1783 if (BIGNUM_NEGATIVE_P (a)) {
1784 size_a = BIGNUM_LENGTH (a);
1785 d = allot_bignum (size_a, 0);
1786 scan_d = BIGNUM_START_PTR (d);
1787 scan_a = BIGNUM_START_PTR (a);
1788 a_end = scan_a + size_a;
1789 while (scan_a < a_end)
1790 (*scan_d++) = (*scan_a++);
1794 if (BIGNUM_NEGATIVE_P (b)) {
1795 size_b = BIGNUM_LENGTH (b);
1796 d = allot_bignum (size_b, 0);
1797 scan_d = BIGNUM_START_PTR (d);
1798 scan_b = BIGNUM_START_PTR (b);
1799 b_end = scan_b + size_b;
1800 while (scan_b < b_end)
1801 (*scan_d++) = (*scan_b++);
1805 if (bignum_compare(a, b) == bignum_comparison_less) {
1809 while (BIGNUM_LENGTH (b) != 0) {
1810 d = bignum_remainder (a, b);
1812 if (d == BIGNUM_OUT_OF_BAND) {
1822 /* Allocates memory */
1823 bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
1827 bignum *c, *d, *e, *f;
1828 bignum_twodigit_type x, y, q, s, t, A, B, C, D;
1830 bignum_length_type size_a, size_b, size_c;
1831 bignum_digit_type *scan_a, *scan_b, *scan_c, *scan_d;
1832 bignum_digit_type *a_end, *b_end, *c_end;
1834 /* clone the bignums so we can modify them in-place */
1835 size_a = BIGNUM_LENGTH (a);
1836 c = allot_bignum (size_a, 0);
1837 scan_a = BIGNUM_START_PTR (a);
1838 a_end = scan_a + size_a;
1840 scan_c = BIGNUM_START_PTR (c);
1841 while (scan_a < a_end)
1842 (*scan_c++) = (*scan_a++);
1844 size_b = BIGNUM_LENGTH (b);
1845 d = allot_bignum (size_b, 0);
1846 scan_b = BIGNUM_START_PTR (b);
1847 b_end = scan_b + size_b;
1849 scan_d = BIGNUM_START_PTR (d);
1850 while (scan_b < b_end)
1851 (*scan_d++) = (*scan_b++);
1854 /* Initial reduction: make sure that 0 <= b <= a. */
1855 if (bignum_compare(a, b) == bignum_comparison_less) {
1857 std::swap(size_a, size_b);
1860 while (size_a > 1) {
1861 nbits = log2 (BIGNUM_REF (a, size_a-1));
1862 x = ((BIGNUM_REF (a, size_a-1) << (BIGNUM_DIGIT_LENGTH - nbits)) |
1863 (BIGNUM_REF (a, size_a-2) >> nbits));
1864 y = ((size_b >= size_a - 1 ? BIGNUM_REF (b, size_a-2) >> nbits : 0) |
1865 (size_b >= size_a ? BIGNUM_REF (b, size_a-1) << (BIGNUM_DIGIT_LENGTH - nbits) : 0));
1867 /* inner loop of Lehmer's algorithm; */
1868 A = 1; B = 0; C = 0; D = 1;
1873 q = (x + (A - 1)) / (y - C);
1886 A = D; B = C; C = s; D = t;
1890 /* no progress; do a Euclidean step */
1892 return bignum_trim (a);
1894 e = bignum_trim (a);
1896 f = bignum_trim (b);
1898 c = bignum_remainder (e, f);
1900 if (c == BIGNUM_OUT_OF_BAND) {
1905 scan_a = BIGNUM_START_PTR (a);
1906 scan_b = BIGNUM_START_PTR (b);
1907 a_end = scan_a + size_a;
1908 b_end = scan_b + size_b;
1909 while (scan_b < b_end) *(scan_a++) = *(scan_b++);
1910 while (scan_a < a_end) *(scan_a++) = 0;
1914 scan_b = BIGNUM_START_PTR (b);
1915 scan_c = BIGNUM_START_PTR (c);
1916 size_c = BIGNUM_LENGTH (c);
1917 c_end = scan_c + size_c;
1918 while (scan_c < c_end) *(scan_b++) = *(scan_c++);
1919 while (scan_b < b_end) *(scan_b++) = 0;
1926 a, b = A*b - B*a, D*a - C*b if k is odd
1927 a, b = A*a - B*b, D*b - C*a if k is even
1929 scan_a = BIGNUM_START_PTR (a);
1930 scan_b = BIGNUM_START_PTR (b);
1933 a_end = scan_a + size_a;
1934 b_end = scan_b + size_b;
1938 while (scan_b < b_end) {
1939 s += (A * *scan_b) - (B * *scan_a);
1940 t += (D * *scan_a++) - (C * *scan_b++);
1941 *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK);
1942 *scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1943 s >>= BIGNUM_DIGIT_LENGTH;
1944 t >>= BIGNUM_DIGIT_LENGTH;
1946 while (scan_a < a_end) {
1948 t += (D * *scan_a++);
1949 *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK);
1950 //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1951 s >>= BIGNUM_DIGIT_LENGTH;
1952 t >>= BIGNUM_DIGIT_LENGTH;
1956 while (scan_b < b_end) {
1957 s += (A * *scan_a) - (B * *scan_b);
1958 t += (D * *scan_b++) - (C * *scan_a++);
1959 *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK);
1960 *scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1961 s >>= BIGNUM_DIGIT_LENGTH;
1962 t >>= BIGNUM_DIGIT_LENGTH;
1964 while (scan_a < a_end) {
1966 t -= (C * *scan_a++);
1967 *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK);
1968 //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1969 s >>= BIGNUM_DIGIT_LENGTH;
1970 t >>= BIGNUM_DIGIT_LENGTH;
1973 BIGNUM_ASSERT (s == 0);
1974 BIGNUM_ASSERT (t == 0);
1976 // update size_a and size_b to remove any zeros at end
1977 while (size_a > 0 && *(--scan_a) == 0) size_a--;
1978 while (size_b > 0 && *(--scan_b) == 0) size_b--;
1980 BIGNUM_ASSERT (size_a >= size_b);
1983 /* a fits into a fixnum, so b must too */
1984 fixnum xx = bignum_to_fixnum (a);
1985 fixnum yy = bignum_to_fixnum (b);
1988 /* usual Euclidean algorithm for longs */
1995 return fixnum_to_bignum (xx);