1 // Copyright (C) 1989-94 Massachusetts Institute of Technology
2 // Portions copyright (C) 2004-2008 Slava Pestov
4 // This material was developed by the Scheme project at the Massachusetts
5 // Institute of Technology, Department of Electrical Engineering and
6 // Computer Science. Permission to copy and modify this software, to
7 // redistribute either the original software or a modified version, and
8 // to use this software for any purpose is granted, subject to the
9 // following restrictions and understandings.
11 // 1. Any copy made of this software must include this copyright notice
14 // 2. Users of this software agree to make their best efforts (a) to
15 // return to the MIT Scheme project any improvements or extensions that
16 // they make, so that these may be included in future releases; and (b)
17 // to inform MIT of noteworthy uses of this software.
19 // 3. All materials developed as a consequence of the use of this
20 // software shall duly acknowledge such use, in accordance with the usual
21 // standards of acknowledging credit in academic research.
23 // 4. MIT has made no warrantee or representation that the operation of
24 // this software will be error-free, and MIT is under no obligation to
25 // provide any services, by way of maintenance, update, or otherwise.
27 // 5. In conjunction with products arising from the use of this material,
28 // there shall be no use of the name of the Massachusetts Institute of
29 // Technology nor of any adaptation thereof in any advertising,
30 // promotional, or sales literature without prior written consent from
33 // Changes for Scheme 48:
34 // * - Converted to ANSI.
35 // * - Added bitwise operations.
36 // * - Added s48 to the beginning of all externally visible names.
37 // * - Cached the bignum representations of -1, 0, and 1.
39 // Changes for Factor:
40 // * - Adapt bignumint.h for Factor memory manager
41 // * - Add more bignum <-> C type conversions
42 // * - Remove unused functions
43 // * - Add local variable GC root recording
44 // * - Remove s48 prefix from function names
45 // * - Various fixes for Win64
47 // * - Added bignum_gcd implementation
55 int factor_vm::bignum_equal_p(bignum* x, bignum* y) {
56 return ((BIGNUM_ZERO_P(x))
58 : ((!(BIGNUM_ZERO_P(y))) &&
59 ((BIGNUM_NEGATIVE_P(x)) ? (BIGNUM_NEGATIVE_P(y))
60 : (!(BIGNUM_NEGATIVE_P(y)))) &&
61 (bignum_equal_p_unsigned(x, y))));
64 enum bignum_comparison factor_vm::bignum_compare(bignum* x, bignum* y) {
65 return ((BIGNUM_ZERO_P(x)) ? ((BIGNUM_ZERO_P(y)) ? BIGNUM_COMPARISON_EQUAL
66 : (BIGNUM_NEGATIVE_P(y))
67 ? BIGNUM_COMPARISON_GREATER
68 : BIGNUM_COMPARISON_LESS)
70 ? ((BIGNUM_NEGATIVE_P(x)) ? BIGNUM_COMPARISON_LESS
71 : BIGNUM_COMPARISON_GREATER)
72 : (BIGNUM_NEGATIVE_P(x))
73 ? ((BIGNUM_NEGATIVE_P(y)) ? (bignum_compare_unsigned(y, x))
74 : (BIGNUM_COMPARISON_LESS))
75 : ((BIGNUM_NEGATIVE_P(y)) ? (BIGNUM_COMPARISON_GREATER)
76 : (bignum_compare_unsigned(x, y))));
80 bignum* factor_vm::bignum_add(bignum* x, bignum* y) {
82 (BIGNUM_ZERO_P(x)) ? (y) : (BIGNUM_ZERO_P(y))
84 : ((BIGNUM_NEGATIVE_P(x))
85 ? ((BIGNUM_NEGATIVE_P(y)) ? (bignum_add_unsigned(x, y, 1))
86 : (bignum_subtract_unsigned(y, x)))
87 : ((BIGNUM_NEGATIVE_P(y)) ? (bignum_subtract_unsigned(x, y))
88 : (bignum_add_unsigned(x, y, 0)))));
92 bignum* factor_vm::bignum_subtract(bignum* x, bignum* y) {
93 return ((BIGNUM_ZERO_P(x))
94 ? ((BIGNUM_ZERO_P(y)) ? (y) : (bignum_new_sign(
95 y, (!(BIGNUM_NEGATIVE_P(y))))))
98 : ((BIGNUM_NEGATIVE_P(x))
99 ? ((BIGNUM_NEGATIVE_P(y))
100 ? (bignum_subtract_unsigned(y, x))
101 : (bignum_add_unsigned(x, y, 1)))
102 : ((BIGNUM_NEGATIVE_P(y))
103 ? (bignum_add_unsigned(x, y, 0))
104 : (bignum_subtract_unsigned(x, y))))));
108 bignum *factor_vm::bignum_square(bignum* x_)
110 return bignum_multiply(x_, x_);
114 bignum *factor_vm::bignum_square(bignum* x_)
116 data_root<bignum> x(x_, this);
118 bignum_length_type length = (BIGNUM_LENGTH (x));
119 bignum * z = (allot_bignum_zeroed ((length + length), 0));
121 bignum_digit_type * scan_z = BIGNUM_START_PTR (z);
122 bignum_digit_type * scan_x = BIGNUM_START_PTR (x);
123 bignum_digit_type * end_x = scan_x + length;
125 for (int i = 0; i < length; ++i) {
126 bignum_twodigit_type carry;
127 bignum_twodigit_type f = BIGNUM_REF (x, i);
128 bignum_digit_type *pz = scan_z + (i << 1);
129 bignum_digit_type *px = scan_x + i + 1;
132 *pz++ = carry & BIGNUM_DIGIT_MASK;
133 carry >>= BIGNUM_DIGIT_LENGTH;
134 BIGNUM_ASSERT (carry <= BIGNUM_DIGIT_MASK);
139 carry += *pz + *px++ * f;
140 *pz++ = carry & BIGNUM_DIGIT_MASK;
141 carry >>= BIGNUM_DIGIT_LENGTH;
142 BIGNUM_ASSERT (carry <= (BIGNUM_DIGIT_MASK << 1));
146 *pz++ = carry & BIGNUM_DIGIT_MASK;
147 carry >>= BIGNUM_DIGIT_LENGTH;
150 *pz += carry & BIGNUM_DIGIT_MASK;
151 BIGNUM_ASSERT ((carry >> BIGNUM_DIGIT_LENGTH) == 0);
153 return (bignum_trim (z));
158 bignum* factor_vm::bignum_multiply(bignum* x, bignum* y) {
162 return bignum_square(x);
166 bignum_length_type x_length = (BIGNUM_LENGTH(x));
167 bignum_length_type y_length = (BIGNUM_LENGTH(y));
168 int negative_p = ((BIGNUM_NEGATIVE_P(x)) ? (!(BIGNUM_NEGATIVE_P(y)))
169 : (BIGNUM_NEGATIVE_P(y)));
170 if (BIGNUM_ZERO_P(x))
172 if (BIGNUM_ZERO_P(y))
175 bignum_digit_type digit = (BIGNUM_REF(x, 0));
177 return (bignum_maybe_new_sign(y, negative_p));
178 if (digit < BIGNUM_RADIX_ROOT)
179 return (bignum_multiply_unsigned_small_factor(y, digit, negative_p));
182 bignum_digit_type digit = (BIGNUM_REF(y, 0));
184 return (bignum_maybe_new_sign(x, negative_p));
185 if (digit < BIGNUM_RADIX_ROOT)
186 return (bignum_multiply_unsigned_small_factor(x, digit, negative_p));
188 return (bignum_multiply_unsigned(x, y, negative_p));
192 void factor_vm::bignum_divide(bignum* numerator, bignum* denominator,
193 bignum** quotient, bignum** remainder) {
194 if (BIGNUM_ZERO_P(denominator)) {
195 divide_by_zero_error();
196 (*quotient) = denominator;
197 (*remainder) = denominator;
200 if (BIGNUM_ZERO_P(numerator)) {
201 (*quotient) = numerator;
202 (*remainder) = numerator;
204 int r_negative_p = (BIGNUM_NEGATIVE_P(numerator));
206 ((BIGNUM_NEGATIVE_P(denominator)) ? (!r_negative_p) : r_negative_p);
207 switch (bignum_compare_unsigned(numerator, denominator)) {
208 case BIGNUM_COMPARISON_EQUAL: {
209 (*quotient) = (BIGNUM_ONE(q_negative_p));
210 (*remainder) = (BIGNUM_ZERO());
213 case BIGNUM_COMPARISON_LESS: {
214 (*quotient) = (BIGNUM_ZERO());
215 (*remainder) = numerator;
218 case BIGNUM_COMPARISON_GREATER: {
219 if ((BIGNUM_LENGTH(denominator)) == 1) {
220 bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
222 (*quotient) = (bignum_maybe_new_sign(numerator, q_negative_p));
223 (*remainder) = (BIGNUM_ZERO());
225 } else if (digit < BIGNUM_RADIX_ROOT) {
226 bignum_divide_unsigned_small_denominator(numerator, digit, quotient,
227 remainder, q_negative_p,
231 bignum_divide_unsigned_medium_denominator(
232 numerator, digit, quotient, remainder, q_negative_p,
237 bignum_divide_unsigned_large_denominator(
238 numerator, denominator, quotient, remainder, q_negative_p,
247 bignum* factor_vm::bignum_quotient(bignum* numerator, bignum* denominator) {
248 if (BIGNUM_ZERO_P(denominator)) {
249 divide_by_zero_error();
250 return (BIGNUM_OUT_OF_BAND);
252 if (BIGNUM_ZERO_P(numerator))
256 ((BIGNUM_NEGATIVE_P(denominator)) ? (!(BIGNUM_NEGATIVE_P(numerator)))
257 : (BIGNUM_NEGATIVE_P(numerator)));
258 switch (bignum_compare_unsigned(numerator, denominator)) {
259 case BIGNUM_COMPARISON_EQUAL:
260 return (BIGNUM_ONE(q_negative_p));
261 case BIGNUM_COMPARISON_LESS:
262 return (BIGNUM_ZERO());
263 case BIGNUM_COMPARISON_GREATER:
264 default: // to appease gcc -Wall
267 if ((BIGNUM_LENGTH(denominator)) == 1) {
268 bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
270 return (bignum_maybe_new_sign(numerator, q_negative_p));
271 if (digit < BIGNUM_RADIX_ROOT)
272 bignum_divide_unsigned_small_denominator(
273 numerator, digit, ("ient), ((bignum**)0), q_negative_p, 0);
275 bignum_divide_unsigned_medium_denominator(
276 numerator, digit, ("ient), ((bignum**)0), q_negative_p, 0);
278 bignum_divide_unsigned_large_denominator(
279 numerator, denominator, ("ient), ((bignum**)0), q_negative_p,
288 bignum* factor_vm::bignum_remainder(bignum* numerator, bignum* denominator) {
289 if (BIGNUM_ZERO_P(denominator)) {
290 divide_by_zero_error();
291 return (BIGNUM_OUT_OF_BAND);
293 if (BIGNUM_ZERO_P(numerator))
295 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) {
305 bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
307 return (BIGNUM_ZERO());
308 if (digit < BIGNUM_RADIX_ROOT)
309 return (bignum_remainder_unsigned_small_denominator(
310 numerator, digit, (BIGNUM_NEGATIVE_P(numerator))));
311 bignum_divide_unsigned_medium_denominator(
312 numerator, digit, ((bignum**)0), (&remainder), 0,
313 (BIGNUM_NEGATIVE_P(numerator)));
315 bignum_divide_unsigned_large_denominator(
316 numerator, denominator, ((bignum**)0), (&remainder), 0,
317 (BIGNUM_NEGATIVE_P(numerator)));
323 // cell_to_bignum, fixnum_to_bignum, long_long_to_bignum, ulong_long_to_bignum
326 #define FOO_TO_BIGNUM_SIGNED(name, type, utype) \
327 bignum* factor_vm::name##_to_bignum(type n) { \
329 /* Special cases win when these small constants are cached. */ \
331 return (BIGNUM_ZERO()); \
333 return (BIGNUM_ONE(0)); \
334 if (n < (type) 0 && n == (type) -1) \
335 return (BIGNUM_ONE(1)); \
337 utype accumulator = \
338 ((negative_p = n < (type) 0) ? -n : n); \
339 if (accumulator < BIGNUM_RADIX) \
341 bignum* result = allot_bignum(1, negative_p); \
342 bignum_digit_type* scan = (BIGNUM_START_PTR(result)); \
343 *scan = (accumulator & BIGNUM_DIGIT_MASK); \
346 bignum_digit_type result_digits[BIGNUM_DIGITS_FOR(type)]; \
347 bignum_digit_type* end_digits = result_digits; \
349 (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK); \
350 accumulator >>= BIGNUM_DIGIT_LENGTH; \
351 } while (accumulator != 0); \
353 (allot_bignum((end_digits - result_digits), negative_p)); \
354 bignum_digit_type* scan_digits = result_digits; \
355 bignum_digit_type* scan_result = (BIGNUM_START_PTR(result)); \
356 while (scan_digits < end_digits) \
357 (*scan_result++) = (*scan_digits++); \
364 #define FOO_TO_BIGNUM_UNSIGNED(name, type, utype) \
365 bignum* factor_vm::name##_to_bignum(type n) { \
366 /* Special cases win when these small constants are cached. */ \
368 return (BIGNUM_ZERO()); \
370 return (BIGNUM_ONE(0)); \
372 utype accumulator = n; \
373 if (accumulator < BIGNUM_RADIX) \
375 bignum* result = allot_bignum(1, false); \
376 bignum_digit_type* scan = (BIGNUM_START_PTR(result)); \
377 *scan = (accumulator & BIGNUM_DIGIT_MASK); \
380 bignum_digit_type result_digits[BIGNUM_DIGITS_FOR(type)]; \
381 bignum_digit_type* end_digits = result_digits; \
383 (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK); \
384 accumulator >>= BIGNUM_DIGIT_LENGTH; \
385 } while (accumulator != 0); \
387 (allot_bignum((end_digits - result_digits), false)); \
388 bignum_digit_type* scan_digits = result_digits; \
389 bignum_digit_type* scan_result = (BIGNUM_START_PTR(result)); \
390 while (scan_digits < end_digits) \
391 (*scan_result++) = (*scan_digits++); \
397 FOO_TO_BIGNUM_SIGNED(fixnum, fixnum, cell)
398 FOO_TO_BIGNUM_UNSIGNED(cell, cell, cell)
399 FOO_TO_BIGNUM_SIGNED(long_long, int64_t, uint64_t)
400 FOO_TO_BIGNUM_UNSIGNED(ulong_long, uint64_t, uint64_t)
402 // cannot allocate memory
403 // bignum_to_cell, fixnum_to_cell, long_long_to_cell, ulong_long_to_cell
404 #define BIGNUM_TO_FOO(name, type, stype, utype) \
405 type bignum_to_##name(bignum* bn) { \
406 if (BIGNUM_ZERO_P(bn)) \
409 utype accumulator = 0; \
410 bignum_digit_type* start = (BIGNUM_START_PTR(bn)); \
411 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(bn))); \
412 while (start < scan) \
413 accumulator = ((accumulator << BIGNUM_DIGIT_LENGTH) + (*--scan)); \
414 return ((BIGNUM_NEGATIVE_P(bn)) ? ((type)(-(stype) accumulator)) \
419 BIGNUM_TO_FOO(cell, cell, fixnum, cell)
420 BIGNUM_TO_FOO(fixnum, fixnum, fixnum, cell)
421 BIGNUM_TO_FOO(long_long, int64_t, int64_t, uint64_t)
422 BIGNUM_TO_FOO(ulong_long, uint64_t, int64_t, uint64_t)
424 bool bignum_fits_fixnum_p(bignum* bn) {
425 fixnum len = BIGNUM_LENGTH(bn);
430 bignum_digit_type dig = BIGNUM_START_PTR(bn)[0];
431 return (BIGNUM_NEGATIVE_P(bn) && dig <= -fixnum_min) ||
432 (!BIGNUM_NEGATIVE_P(bn) && dig <= fixnum_max);
435 cell bignum_maybe_to_fixnum(bignum* bn) {
436 if (bignum_fits_fixnum_p(bn))
437 return tag_fixnum(bignum_to_fixnum(bn));
438 return tag<bignum>(bn);
441 // cannot allocate memory
442 fixnum factor_vm::bignum_to_fixnum_strict(bignum* bn) {
444 if (!bignum_fits_fixnum_p(bn)) {
445 general_error(ERROR_OUT_OF_FIXNUM_RANGE, tag<bignum>(bn), false_object);
447 fixnum fix = bignum_to_fixnum(bn);
448 FACTOR_ASSERT(fix <= fixnum_max && fix >= fixnum_min);
452 #define DTB_WRITE_DIGIT(factor) \
454 significand *= (factor); \
455 digit = ((bignum_digit_type) significand); \
457 significand -= ((double)digit); \
460 #define inf std::numeric_limits<double>::infinity()
463 bignum* factor_vm::double_to_bignum(double x) {
464 if (x == inf || x == -inf || x != x)
465 return (BIGNUM_ZERO());
467 double significand = (frexp(x, (&exponent)));
469 return (BIGNUM_ZERO());
471 return (BIGNUM_ONE(x < 0));
473 significand = (-significand);
475 bignum_length_type length = (BIGNUM_BITS_TO_DIGITS(exponent));
476 bignum* result = (allot_bignum(length, (x < 0)));
477 bignum_digit_type* start = (BIGNUM_START_PTR(result));
478 bignum_digit_type* scan = (start + length);
479 bignum_digit_type digit;
480 int odd_bits = (exponent % BIGNUM_DIGIT_LENGTH);
482 DTB_WRITE_DIGIT((fixnum)1 << odd_bits);
483 while (start < scan) {
484 if (significand == 0) {
489 DTB_WRITE_DIGIT(BIGNUM_RADIX);
495 #undef DTB_WRITE_DIGIT
499 int factor_vm::bignum_equal_p_unsigned(bignum* x, bignum* y) {
500 bignum_length_type length = (BIGNUM_LENGTH(x));
501 if (length != (BIGNUM_LENGTH(y)))
504 bignum_digit_type* scan_x = (BIGNUM_START_PTR(x));
505 bignum_digit_type* scan_y = (BIGNUM_START_PTR(y));
506 bignum_digit_type* end_x = (scan_x + length);
507 while (scan_x < end_x)
508 if ((*scan_x++) != (*scan_y++))
514 enum bignum_comparison factor_vm::bignum_compare_unsigned(bignum* x,
516 bignum_length_type x_length = (BIGNUM_LENGTH(x));
517 bignum_length_type y_length = (BIGNUM_LENGTH(y));
518 if (x_length < y_length)
519 return BIGNUM_COMPARISON_LESS;
520 if (x_length > y_length)
521 return BIGNUM_COMPARISON_GREATER;
523 bignum_digit_type* start_x = (BIGNUM_START_PTR(x));
524 bignum_digit_type* scan_x = (start_x + x_length);
525 bignum_digit_type* scan_y = ((BIGNUM_START_PTR(y)) + y_length);
526 while (start_x < scan_x) {
527 bignum_digit_type digit_x = (*--scan_x);
528 bignum_digit_type digit_y = (*--scan_y);
529 if (digit_x < digit_y)
530 return BIGNUM_COMPARISON_LESS;
531 if (digit_x > digit_y)
532 return BIGNUM_COMPARISON_GREATER;
535 return BIGNUM_COMPARISON_EQUAL;
541 bignum* factor_vm::bignum_add_unsigned(bignum* x_, bignum* y_, int negative_p) {
543 data_root<bignum> x(x_, this);
544 data_root<bignum> y(y_, this);
545 if ((BIGNUM_LENGTH(y)) > (BIGNUM_LENGTH(x))) {
549 bignum_length_type x_length = (BIGNUM_LENGTH(x));
551 bignum* r = (allot_bignum((x_length + 1), negative_p));
553 bignum_digit_type sum;
554 bignum_digit_type carry = 0;
555 bignum_digit_type* scan_x = (BIGNUM_START_PTR(x));
556 bignum_digit_type* scan_r = (BIGNUM_START_PTR(r));
558 bignum_digit_type* scan_y = (BIGNUM_START_PTR(y));
559 bignum_digit_type* end_y = (scan_y + (BIGNUM_LENGTH(y)));
560 while (scan_y < end_y) {
561 sum = ((*scan_x++) + (*scan_y++) + carry);
562 if (sum < BIGNUM_RADIX) {
566 (*scan_r++) = (sum - BIGNUM_RADIX);
572 bignum_digit_type* end_x = BIGNUM_START_PTR(x) + x_length;
574 while (scan_x < end_x) {
575 sum = ((*scan_x++) + 1);
576 if (sum < BIGNUM_RADIX) {
581 (*scan_r++) = (sum - BIGNUM_RADIX);
583 while (scan_x < end_x)
584 (*scan_r++) = (*scan_x++);
590 return (bignum_shorten_length(r, x_length));
597 bignum* factor_vm::bignum_subtract_unsigned(bignum* x_, bignum* y_) {
599 data_root<bignum> x(x_, this);
600 data_root<bignum> y(y_, this);
603 switch (bignum_compare_unsigned(x.untagged(), y.untagged())) {
604 case BIGNUM_COMPARISON_EQUAL:
605 return (BIGNUM_ZERO());
606 case BIGNUM_COMPARISON_LESS:
610 case BIGNUM_COMPARISON_GREATER:
615 bignum_length_type x_length = (BIGNUM_LENGTH(x));
617 bignum* r = (allot_bignum(x_length, negative_p));
619 bignum_digit_type difference;
620 bignum_digit_type borrow = 0;
621 bignum_digit_type* scan_x = BIGNUM_START_PTR(x);
622 bignum_digit_type* scan_r = BIGNUM_START_PTR(r);
624 bignum_digit_type* scan_y = BIGNUM_START_PTR(y);
625 bignum_digit_type* end_y = (scan_y + (BIGNUM_LENGTH(y)));
626 while (scan_y < end_y) {
627 difference = (((*scan_x++) - (*scan_y++)) - borrow);
628 if (difference < 0) {
629 (*scan_r++) = (difference + BIGNUM_RADIX);
632 (*scan_r++) = difference;
638 bignum_digit_type* end_x = BIGNUM_START_PTR(x) + x_length;
640 while (scan_x < end_x) {
641 difference = ((*scan_x++) - borrow);
643 (*scan_r++) = (difference + BIGNUM_RADIX);
645 (*scan_r++) = difference;
650 BIGNUM_ASSERT(borrow == 0);
651 while (scan_x < end_x)
652 (*scan_r++) = (*scan_x++);
654 return (bignum_trim(r));
659 // Maximum value for product_low or product_high:
660 // ((R * R) + (R * (R - 2)) + (R - 1))
661 // Maximum value for carry: ((R * (R - 1)) + (R - 1))
662 // where R == BIGNUM_RADIX_ROOT
665 bignum* factor_vm::bignum_multiply_unsigned(bignum* x_, bignum* y_,
668 data_root<bignum> x(x_, this);
669 data_root<bignum> y(y_, this);
671 if (BIGNUM_LENGTH(y) > BIGNUM_LENGTH(x)) {
675 bignum_digit_type carry;
676 bignum_digit_type y_digit_low;
677 bignum_digit_type y_digit_high;
678 bignum_digit_type x_digit_low;
679 bignum_digit_type x_digit_high;
680 bignum_digit_type product_low;
681 bignum_digit_type* scan_r;
682 bignum_digit_type* scan_y;
683 bignum_length_type x_length = BIGNUM_LENGTH(x);
684 bignum_length_type y_length = BIGNUM_LENGTH(y);
686 bignum* r = (allot_bignum_zeroed((x_length + y_length), negative_p));
688 bignum_digit_type* scan_x = BIGNUM_START_PTR(x);
689 bignum_digit_type* end_x = (scan_x + x_length);
690 bignum_digit_type* start_y = BIGNUM_START_PTR(y);
691 bignum_digit_type* end_y = (start_y + y_length);
692 bignum_digit_type* start_r = (BIGNUM_START_PTR(r));
693 #define x_digit x_digit_high
694 #define y_digit y_digit_high
695 #define product_high carry
696 while (scan_x < end_x) {
697 x_digit = (*scan_x++);
698 x_digit_low = (HD_LOW(x_digit));
699 x_digit_high = (HD_HIGH(x_digit));
702 scan_r = (start_r++);
703 while (scan_y < end_y) {
704 y_digit = (*scan_y++);
705 y_digit_low = (HD_LOW(y_digit));
706 y_digit_high = (HD_HIGH(y_digit));
708 ((*scan_r) + (x_digit_low * y_digit_low) + (HD_LOW(carry)));
710 ((x_digit_high * y_digit_low) + (x_digit_low * y_digit_high) +
711 (HD_HIGH(product_low)) + (HD_HIGH(carry)));
712 (*scan_r++) = (HD_CONS((HD_LOW(product_high)), (HD_LOW(product_low))));
713 carry = ((x_digit_high * y_digit_high) + (HD_HIGH(product_high)));
717 return (bignum_trim(r));
725 bignum* factor_vm::bignum_multiply_unsigned_small_factor(bignum* x_,
728 data_root<bignum> x(x_, this);
730 bignum_length_type length_x = (BIGNUM_LENGTH(x));
732 bignum* p = (allot_bignum((length_x + 1), negative_p));
734 bignum_destructive_copy(x.untagged(), p);
735 (BIGNUM_REF(p, length_x)) = 0;
736 bignum_destructive_scale_up(p, y);
737 return (bignum_trim(p));
740 void factor_vm::bignum_destructive_add(bignum* bn, bignum_digit_type n) {
741 bignum_digit_type* scan = (BIGNUM_START_PTR(bn));
742 bignum_digit_type digit;
743 digit = ((*scan) + n);
744 if (digit < BIGNUM_RADIX) {
748 (*scan++) = (digit - BIGNUM_RADIX);
750 digit = ((*scan) + 1);
751 if (digit < BIGNUM_RADIX) {
755 (*scan++) = (digit - BIGNUM_RADIX);
759 void factor_vm::bignum_destructive_scale_up(bignum* bn,
760 bignum_digit_type factor) {
761 bignum_digit_type carry = 0;
762 bignum_digit_type* scan = (BIGNUM_START_PTR(bn));
763 bignum_digit_type two_digits;
764 bignum_digit_type product_low;
765 #define product_high carry
766 bignum_digit_type* end = (scan + (BIGNUM_LENGTH(bn)));
767 BIGNUM_ASSERT((factor > 1) && (factor < BIGNUM_RADIX_ROOT));
769 two_digits = (*scan);
770 product_low = ((factor * (HD_LOW(two_digits))) + (HD_LOW(carry)));
771 product_high = ((factor * (HD_HIGH(two_digits))) + (HD_HIGH(product_low)) +
773 (*scan++) = (HD_CONS((HD_LOW(product_high)), (HD_LOW(product_low))));
774 carry = (HD_HIGH(product_high));
776 // A carry here would be an overflow, i.e. it would not fit.
777 // Hopefully the callers allocate enough space that this will
779 BIGNUM_ASSERT(carry == 0);
786 // For help understanding this algorithm, see:
787 // Knuth, Donald E., "The Art of Computer Programming",
788 // volume 2, "Seminumerical Algorithms"
789 // section 4.3.1, "Multiple-Precision Arithmetic".
792 void factor_vm::bignum_divide_unsigned_large_denominator(
793 bignum* numerator_, bignum* denominator_,
794 bignum** quotient, bignum** remainder,
795 int q_negative_p, int r_negative_p) {
797 data_root<bignum> numerator(numerator_, this);
798 data_root<bignum> denominator(denominator_, this);
800 bignum_length_type length_n = BIGNUM_LENGTH(numerator) + 1;
801 bignum_length_type length_d = BIGNUM_LENGTH(denominator);
803 data_root<bignum> u(allot_bignum(length_n, r_negative_p), this);
806 BIGNUM_ASSERT(length_d > 1);
808 bignum_digit_type v1 = BIGNUM_REF(denominator.untagged(), length_d - 1);
809 while (v1 < (BIGNUM_RADIX / 2)) {
815 if (quotient != NULL) {
816 bignum *q_ = allot_bignum(length_n - length_d, q_negative_p);
817 data_root<bignum> q(q_, this);
820 bignum_destructive_copy(numerator.untagged(), u.untagged());
821 (BIGNUM_REF(u.untagged(), (length_n - 1))) = 0;
822 bignum_divide_unsigned_normalized(u.untagged(),
823 denominator.untagged(),
826 bignum* v = allot_bignum(length_d, 0);
827 bignum_destructive_normalization(numerator.untagged(),
830 bignum_destructive_normalization(denominator.untagged(), v, shift);
831 bignum_divide_unsigned_normalized(u.untagged(), v, q.untagged());
832 if (remainder != NULL)
833 bignum_destructive_unnormalization(u.untagged(), shift);
836 q.set_untagged(bignum_trim(q.untagged()));
837 *quotient = q.untagged();
841 bignum_destructive_copy(numerator.untagged(), u.untagged());
842 (BIGNUM_REF(u.untagged(), (length_n - 1))) = 0;
843 bignum_divide_unsigned_normalized(u.untagged(),
844 denominator.untagged(),
847 bignum* v = allot_bignum(length_d, 0);
848 bignum_destructive_normalization(numerator.untagged(),
851 bignum_destructive_normalization(denominator.untagged(),
854 bignum_divide_unsigned_normalized(u.untagged(), v, NULL);
855 if (remainder != NULL)
856 bignum_destructive_unnormalization(u.untagged(), shift);
860 u.set_untagged(bignum_trim(u.untagged()));
861 if (remainder != NULL)
862 *remainder = u.untagged();
865 void factor_vm::bignum_divide_unsigned_normalized(bignum* u, bignum* v,
867 bignum_length_type u_length = (BIGNUM_LENGTH(u));
868 bignum_length_type v_length = (BIGNUM_LENGTH(v));
869 bignum_digit_type* u_start = (BIGNUM_START_PTR(u));
870 bignum_digit_type* u_scan = (u_start + u_length);
871 bignum_digit_type* u_scan_limit = (u_start + v_length);
872 bignum_digit_type* u_scan_start = (u_scan - v_length);
873 bignum_digit_type* v_start = (BIGNUM_START_PTR(v));
874 bignum_digit_type* v_end = (v_start + v_length);
875 bignum_digit_type* q_scan = NULL;
876 bignum_digit_type v1 = (v_end[-1]);
877 bignum_digit_type v2 = (v_end[-2]);
878 bignum_digit_type ph; // high half of double-digit product
879 bignum_digit_type pl; // low half of double-digit product
880 bignum_digit_type guess;
881 bignum_digit_type gh; // high half-digit of guess
882 bignum_digit_type ch; // high half of double-digit comparand
883 bignum_digit_type v2l = (HD_LOW(v2));
884 bignum_digit_type v2h = (HD_HIGH(v2));
885 bignum_digit_type cl; // low half of double-digit comparand
886 #define gl ph // low half-digit of guess
889 bignum_digit_type gm; // memory loc for reference parameter
890 if (q != BIGNUM_OUT_OF_BAND)
891 q_scan = ((BIGNUM_START_PTR(q)) + (BIGNUM_LENGTH(q)));
892 while (u_scan_limit < u_scan) {
896 // (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
897 // guess = (((uj * BIGNUM_RADIX) + uj1) / v1);
899 ch = (bignum_digit_divide(uj, (u_scan[-1]), v1, (&gm)));
903 ch = ((u_scan[-1]) + v1);
904 guess = (BIGNUM_RADIX - 1);
907 // product = (guess * v2);
908 gl = (HD_LOW(guess));
909 gh = (HD_HIGH(guess));
911 ph = ((v2l * gh) + (v2h * gl) + (HD_HIGH(pl)));
912 pl = (HD_CONS((HD_LOW(ph)), (HD_LOW(pl))));
913 ph = ((v2h * gh) + (HD_HIGH(ph)));
914 // if (comparand >= product)
915 if ((ch > ph) || ((ch == ph) && (cl >= pl)))
918 // comparand += (v1 << BIGNUM_DIGIT_LENGTH)
920 // if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX))
921 if (ch >= BIGNUM_RADIX)
924 qj = (bignum_divide_subtract(v_start, v_end, guess, (--u_scan_start)));
925 if (q != BIGNUM_OUT_OF_BAND)
934 bignum_digit_type factor_vm::bignum_divide_subtract(
935 bignum_digit_type* v_start, bignum_digit_type* v_end,
936 bignum_digit_type guess, bignum_digit_type* u_start) {
937 bignum_digit_type* v_scan = v_start;
938 bignum_digit_type* u_scan = u_start;
939 bignum_digit_type carry = 0;
943 bignum_digit_type gl = (HD_LOW(guess));
944 bignum_digit_type gh = (HD_HIGH(guess));
946 bignum_digit_type pl;
947 bignum_digit_type vl;
951 while (v_scan < v_end) {
955 pl = ((vl * gl) + (HD_LOW(carry)));
956 ph = ((vl * gh) + (vh * gl) + (HD_HIGH(pl)) + (HD_HIGH(carry)));
957 diff = ((*u_scan) - (HD_CONS((HD_LOW(ph)), (HD_LOW(pl)))));
959 (*u_scan++) = (diff + BIGNUM_RADIX);
960 carry = ((vh * gh) + (HD_HIGH(ph)) + 1);
963 carry = ((vh * gh) + (HD_HIGH(ph)));
968 diff = ((*u_scan) - carry);
970 (*u_scan) = (diff + BIGNUM_RADIX);
979 // Subtraction generated carry, implying guess is one too large.
980 // Add v back in to bring it back down.
984 while (v_scan < v_end) {
985 bignum_digit_type sum = ((*v_scan++) + (*u_scan) + carry);
986 if (sum < BIGNUM_RADIX) {
990 (*u_scan++) = (sum - BIGNUM_RADIX);
995 bignum_digit_type sum = ((*u_scan) + carry);
996 (*u_scan) = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
1002 void factor_vm::bignum_divide_unsigned_medium_denominator(
1003 bignum* numerator_, bignum_digit_type denominator, bignum** quotient,
1004 bignum** remainder, int q_negative_p, int r_negative_p) {
1006 data_root<bignum> numerator(numerator_, this);
1008 bignum_length_type length_n = (BIGNUM_LENGTH(numerator));
1011 // Because `bignum_digit_divide' requires a normalized denominator.
1012 while (denominator < (BIGNUM_RADIX / 2)) {
1017 bignum_length_type length_q = (shift == 0) ? length_n : length_n + 1;
1018 data_root<bignum> q(allot_bignum(length_q, q_negative_p), this);
1020 bignum_destructive_copy(numerator.untagged(), q.untagged());
1022 bignum_destructive_normalization(numerator.untagged(), q.untagged(), shift);
1025 bignum_digit_type r = 0;
1026 bignum_digit_type* start = (BIGNUM_START_PTR(q));
1027 bignum_digit_type* scan = (start + length_q);
1028 bignum_digit_type qj;
1030 while (start < scan) {
1031 r = (bignum_digit_divide(r, (*--scan), denominator, (&qj)));
1035 q.set_untagged(bignum_trim(q.untagged()));
1037 if (remainder != ((bignum**)0)) {
1041 (*remainder) = (bignum_digit_to_bignum(r, r_negative_p));
1044 if (quotient != ((bignum**)0))
1045 (*quotient) = q.untagged();
1050 void factor_vm::bignum_destructive_normalization(bignum* source, bignum* target,
1052 bignum_digit_type digit;
1053 bignum_digit_type* scan_source = (BIGNUM_START_PTR(source));
1054 bignum_digit_type carry = 0;
1055 bignum_digit_type* scan_target = (BIGNUM_START_PTR(target));
1056 bignum_digit_type* end_source = (scan_source + (BIGNUM_LENGTH(source)));
1057 bignum_digit_type* end_target = (scan_target + (BIGNUM_LENGTH(target)));
1058 int shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
1059 bignum_digit_type mask = (((cell)1 << shift_right) - 1);
1060 while (scan_source < end_source) {
1061 digit = (*scan_source++);
1062 (*scan_target++) = (((digit & mask) << shift_left) | carry);
1063 carry = (digit >> shift_right);
1065 if (scan_target < end_target)
1066 (*scan_target) = carry;
1068 BIGNUM_ASSERT(carry == 0);
1072 void factor_vm::bignum_destructive_unnormalization(bignum* bn,
1074 bignum_digit_type* start = (BIGNUM_START_PTR(bn));
1075 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(bn)));
1076 bignum_digit_type digit;
1077 bignum_digit_type carry = 0;
1078 int shift_left = (BIGNUM_DIGIT_LENGTH - shift_right);
1079 bignum_digit_type mask = (((fixnum)1 << shift_right) - 1);
1080 while (start < scan) {
1082 (*scan) = ((digit >> shift_right) | carry);
1083 carry = ((digit & mask) << shift_left);
1085 BIGNUM_ASSERT(carry == 0);
1089 // This is a reduced version of the division algorithm, applied to the
1090 // case of dividing two bignum digits by one bignum digit. It is
1091 // assumed that the numerator, denominator are normalized.
1093 #define BDD_STEP(qn, j) \
1097 uj_uj1 = (HD_CONS(uj, (u[j + 1]))); \
1098 guess = (uj_uj1 / v1); \
1099 comparand = (HD_CONS((uj_uj1 % v1), (u[j + 2]))); \
1101 guess = (BIGNUM_RADIX_ROOT - 1); \
1102 comparand = (HD_CONS(((u[j + 1]) + v1), (u[j + 2]))); \
1104 while ((guess * v2) > comparand) { \
1106 comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH); \
1107 if (comparand >= BIGNUM_RADIX) \
1110 qn = (bignum_digit_divide_subtract(v1, v2, guess, (&u[j]))); \
1113 bignum_digit_type factor_vm::bignum_digit_divide(
1114 bignum_digit_type uh, bignum_digit_type ul, bignum_digit_type v,
1115 bignum_digit_type* q) // return value
1117 bignum_digit_type guess;
1118 bignum_digit_type comparand;
1119 bignum_digit_type v1 = (HD_HIGH(v));
1120 bignum_digit_type v2 = (HD_LOW(v));
1121 bignum_digit_type uj;
1122 bignum_digit_type uj_uj1;
1123 bignum_digit_type q1;
1124 bignum_digit_type q2;
1125 bignum_digit_type u[4];
1130 } else if (ul == v) {
1135 (u[0]) = (HD_HIGH(uh));
1136 (u[1]) = (HD_LOW(uh));
1137 (u[2]) = (HD_HIGH(ul));
1138 (u[3]) = (HD_LOW(ul));
1143 (*q) = (HD_CONS(q1, q2));
1144 return (HD_CONS((u[2]), (u[3])));
1149 #define BDDS_MULSUB(vn, un, carry_in) \
1151 product = ((vn * guess) + carry_in); \
1152 diff = (un - (HD_LOW(product))); \
1154 un = (diff + BIGNUM_RADIX_ROOT); \
1155 carry = ((HD_HIGH(product)) + 1); \
1158 carry = (HD_HIGH(product)); \
1162 #define BDDS_ADD(vn, un, carry_in) \
1164 sum = (vn + un + carry_in); \
1165 if (sum < BIGNUM_RADIX_ROOT) { \
1169 un = (sum - BIGNUM_RADIX_ROOT); \
1174 bignum_digit_type factor_vm::bignum_digit_divide_subtract(
1175 bignum_digit_type v1, bignum_digit_type v2, bignum_digit_type guess,
1176 bignum_digit_type* u) {
1178 bignum_digit_type product;
1179 bignum_digit_type diff;
1180 bignum_digit_type carry;
1181 BDDS_MULSUB(v2, (u[2]), 0);
1182 BDDS_MULSUB(v1, (u[1]), carry);
1185 diff = ((u[0]) - carry);
1187 (u[0]) = (diff + BIGNUM_RADIX);
1194 bignum_digit_type sum;
1195 bignum_digit_type carry;
1196 BDDS_ADD(v2, (u[2]), 0);
1197 BDDS_ADD(v1, (u[1]), carry);
1208 void factor_vm::bignum_divide_unsigned_small_denominator(
1209 bignum* numerator_, bignum_digit_type denominator, bignum** quotient,
1210 bignum** remainder, int q_negative_p, int r_negative_p) {
1211 data_root<bignum> numerator(numerator_, this);
1213 bignum* q_ = bignum_new_sign(numerator.untagged(), q_negative_p);
1214 data_root<bignum> q(q_, this);
1216 bignum_digit_type r = bignum_destructive_scale_down(q.untagged(), denominator);
1218 q.set_untagged(bignum_trim(q.untagged()));
1220 if (remainder != ((bignum**)0))
1221 (*remainder) = bignum_digit_to_bignum(r, r_negative_p);
1223 (*quotient) = q.untagged();
1228 // Given (denominator > 1), it is fairly easy to show that
1229 // (quotient_high < BIGNUM_RADIX_ROOT), after which it is easy to see
1230 // that all digits are < BIGNUM_RADIX.
1232 bignum_digit_type factor_vm::bignum_destructive_scale_down(
1233 bignum* bn, bignum_digit_type denominator) {
1234 bignum_digit_type numerator;
1235 bignum_digit_type remainder = 0;
1236 bignum_digit_type two_digits;
1237 #define quotient_high remainder
1238 bignum_digit_type* start = (BIGNUM_START_PTR(bn));
1239 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(bn)));
1240 BIGNUM_ASSERT((denominator > 1) && (denominator < BIGNUM_RADIX_ROOT));
1241 while (start < scan) {
1242 two_digits = (*--scan);
1243 numerator = (HD_CONS(remainder, (HD_HIGH(two_digits))));
1244 quotient_high = (numerator / denominator);
1245 numerator = (HD_CONS((numerator % denominator), (HD_LOW(two_digits))));
1246 (*scan) = (HD_CONS(quotient_high, (numerator / denominator)));
1247 remainder = (numerator % denominator);
1250 #undef quotient_high
1254 bignum* factor_vm::bignum_remainder_unsigned_small_denominator(
1255 bignum* n, bignum_digit_type d, int negative_p) {
1256 bignum_digit_type two_digits;
1257 bignum_digit_type* start = (BIGNUM_START_PTR(n));
1258 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(n)));
1259 bignum_digit_type r = 0;
1260 BIGNUM_ASSERT((d > 1) && (d < BIGNUM_RADIX_ROOT));
1261 while (start < scan) {
1262 two_digits = (*--scan);
1263 r = ((HD_CONS(((HD_CONS(r, (HD_HIGH(two_digits)))) % d),
1264 (HD_LOW(two_digits)))) %
1267 return (bignum_digit_to_bignum(r, negative_p));
1271 bignum* factor_vm::bignum_digit_to_bignum(bignum_digit_type digit,
1274 return (BIGNUM_ZERO());
1276 bignum* result = (allot_bignum(1, negative_p));
1277 (BIGNUM_REF(result, 0)) = digit;
1283 bignum* factor_vm::allot_bignum(bignum_length_type length, int negative_p) {
1284 BIGNUM_ASSERT((length >= 0) || (length < BIGNUM_RADIX));
1285 bignum* result = allot_uninitialized_array<bignum>(length + 1);
1286 BIGNUM_SET_NEGATIVE_P(result, negative_p);
1291 bignum* factor_vm::allot_bignum_zeroed(bignum_length_type length,
1293 bignum* result = allot_bignum(length, negative_p);
1294 bignum_digit_type* scan = (BIGNUM_START_PTR(result));
1295 bignum_digit_type* end = (scan + length);
1302 bignum* factor_vm::bignum_shorten_length(bignum* bn,
1303 bignum_length_type length) {
1304 bignum_length_type current_length = (BIGNUM_LENGTH(bn));
1305 BIGNUM_ASSERT((length >= 0) || (length <= current_length));
1306 if (length < current_length) {
1307 bn = reallot_array(bn, length + 1);
1308 BIGNUM_SET_NEGATIVE_P(bn, (length != 0) && (BIGNUM_NEGATIVE_P(bn)));
1314 bignum* factor_vm::bignum_trim(bignum* bn) {
1315 bignum_digit_type* start = (BIGNUM_START_PTR(bn));
1316 bignum_digit_type* end = (start + (BIGNUM_LENGTH(bn)));
1317 bignum_digit_type* scan = end;
1318 while ((start <= scan) && ((*--scan) == 0))
1322 bignum_length_type length = (scan - start);
1323 bn = reallot_array(bn, length + 1);
1324 BIGNUM_SET_NEGATIVE_P(bn, (length != 0) && (BIGNUM_NEGATIVE_P(bn)));
1332 bignum* factor_vm::bignum_new_sign(bignum* x_, int negative_p) {
1333 data_root<bignum> x(x_, this);
1334 bignum* result = allot_bignum(BIGNUM_LENGTH(x), negative_p);
1335 bignum_destructive_copy(x.untagged(), result);
1340 bignum* factor_vm::bignum_maybe_new_sign(bignum* x_, int negative_p) {
1341 if ((BIGNUM_NEGATIVE_P(x_)) ? negative_p : (!negative_p))
1344 return bignum_new_sign(x_, negative_p);
1348 void factor_vm::bignum_destructive_copy(bignum* source, bignum* target) {
1349 bignum_digit_type* scan_source = (BIGNUM_START_PTR(source));
1350 bignum_digit_type* end_source = (scan_source + (BIGNUM_LENGTH(source)));
1351 bignum_digit_type* scan_target = (BIGNUM_START_PTR(target));
1352 while (scan_source < end_source)
1353 (*scan_target++) = (*scan_source++);
1357 // * Added bitwise operations (and oddp).
1360 bignum* factor_vm::bignum_bitwise_not(bignum* x_) {
1363 bignum_length_type size = BIGNUM_LENGTH(x_);
1364 int is_negative = BIGNUM_NEGATIVE_P(x_);
1365 data_root<bignum> x(x_, this);
1366 data_root<bignum> y(allot_bignum(size, is_negative ? 0 : 1), this);
1368 bignum_digit_type* scan_x = BIGNUM_START_PTR(x);
1369 bignum_digit_type* end_x = scan_x + size;
1370 bignum_digit_type* scan_y = BIGNUM_START_PTR(y);
1373 while (scan_x < end_x) {
1375 *scan_y++ = BIGNUM_RADIX - 1;
1378 *scan_y++ = *scan_x++ - 1;
1384 while (scan_x < end_x) {
1385 if (*scan_x == (BIGNUM_RADIX - 1)) {
1389 *scan_y++ = *scan_x++ + 1;
1396 while (scan_x < end_x) {
1397 *scan_y++ = *scan_x++;
1401 bignum* ret = allot_bignum(size + 1, BIGNUM_NEGATIVE_P(y));
1402 bignum_destructive_copy(y.untagged(), ret);
1403 bignum_digit_type* ret_start = BIGNUM_START_PTR(ret);
1404 *(ret_start + size) = 1;
1407 return bignum_trim(y.untagged());
1412 bignum* factor_vm::bignum_arithmetic_shift(bignum* arg1, fixnum n) {
1413 if (BIGNUM_NEGATIVE_P(arg1) && n < 0)
1414 return bignum_bitwise_not(
1415 bignum_magnitude_ash(bignum_bitwise_not(arg1), n));
1417 return bignum_magnitude_ash(arg1, n);
1425 bignum* factor_vm::bignum_bitwise_and(bignum* arg1, bignum* arg2) {
1426 return ((BIGNUM_NEGATIVE_P(arg1)) ? (BIGNUM_NEGATIVE_P(arg2))
1427 ? bignum_negneg_bitwise_op(AND_OP, arg1, arg2)
1428 : bignum_posneg_bitwise_op(AND_OP, arg2, arg1)
1429 : (BIGNUM_NEGATIVE_P(arg2))
1430 ? bignum_posneg_bitwise_op(AND_OP, arg1, arg2)
1431 : bignum_pospos_bitwise_op(AND_OP, arg1, arg2));
1435 bignum* factor_vm::bignum_bitwise_ior(bignum* arg1, bignum* arg2) {
1436 return ((BIGNUM_NEGATIVE_P(arg1)) ? (BIGNUM_NEGATIVE_P(arg2))
1437 ? bignum_negneg_bitwise_op(IOR_OP, arg1, arg2)
1438 : bignum_posneg_bitwise_op(IOR_OP, arg2, arg1)
1439 : (BIGNUM_NEGATIVE_P(arg2))
1440 ? bignum_posneg_bitwise_op(IOR_OP, arg1, arg2)
1441 : bignum_pospos_bitwise_op(IOR_OP, arg1, arg2));
1445 bignum* factor_vm::bignum_bitwise_xor(bignum* arg1, bignum* arg2) {
1446 return ((BIGNUM_NEGATIVE_P(arg1)) ? (BIGNUM_NEGATIVE_P(arg2))
1447 ? bignum_negneg_bitwise_op(XOR_OP, arg1, arg2)
1448 : bignum_posneg_bitwise_op(XOR_OP, arg2, arg1)
1449 : (BIGNUM_NEGATIVE_P(arg2))
1450 ? bignum_posneg_bitwise_op(XOR_OP, arg1, arg2)
1451 : bignum_pospos_bitwise_op(XOR_OP, arg1, arg2));
1455 // ash for the magnitude
1456 // assume arg1 is a big number, n is a long
1457 bignum* factor_vm::bignum_magnitude_ash(bignum* arg1_, fixnum n) {
1459 data_root<bignum> arg1(arg1_, this);
1461 bignum* result = NULL;
1462 bignum_digit_type* scan1;
1463 bignum_digit_type* scanr;
1464 bignum_digit_type* end;
1466 fixnum digit_offset, bit_offset;
1468 if (BIGNUM_ZERO_P(arg1))
1469 return arg1.untagged();
1472 digit_offset = n / BIGNUM_DIGIT_LENGTH;
1473 bit_offset = n % BIGNUM_DIGIT_LENGTH;
1475 result = allot_bignum_zeroed(BIGNUM_LENGTH(arg1) + digit_offset + 1,
1476 BIGNUM_NEGATIVE_P(arg1));
1478 scanr = BIGNUM_START_PTR(result) + digit_offset;
1479 scan1 = BIGNUM_START_PTR(arg1);
1480 end = scan1 + BIGNUM_LENGTH(arg1);
1482 while (scan1 < end) {
1483 *scanr = *scanr | (*scan1 & BIGNUM_DIGIT_MASK) << bit_offset;
1484 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1486 *scanr = *scan1++ >> (BIGNUM_DIGIT_LENGTH - bit_offset);
1487 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1489 } else if (n < 0 && (-n >= (BIGNUM_LENGTH(arg1) * (bignum_length_type)
1490 BIGNUM_DIGIT_LENGTH))) {
1491 result = BIGNUM_ZERO();
1493 digit_offset = -n / BIGNUM_DIGIT_LENGTH;
1494 bit_offset = -n % BIGNUM_DIGIT_LENGTH;
1496 result = allot_bignum_zeroed(BIGNUM_LENGTH(arg1) - digit_offset,
1497 BIGNUM_NEGATIVE_P(arg1));
1499 scanr = BIGNUM_START_PTR(result);
1500 scan1 = BIGNUM_START_PTR(arg1) + digit_offset;
1501 end = scanr + BIGNUM_LENGTH(result) - 1;
1503 while (scanr < end) {
1504 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset;
1505 *scanr = (*scanr | *scan1 << (BIGNUM_DIGIT_LENGTH - bit_offset)) &
1509 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset;
1510 } else if (n == 0) {
1511 result = arg1.untagged();
1514 return bignum_trim(result);
1518 bignum* factor_vm::bignum_pospos_bitwise_op(int op, bignum* arg1_,
1520 data_root<bignum> arg1(arg1_, this);
1521 data_root<bignum> arg2(arg2_, this);
1523 bignum_length_type max_length;
1525 bignum_digit_type* scan1, *end1, digit1;
1526 bignum_digit_type* scan2, *end2, digit2;
1527 bignum_digit_type* scanr, *endr;
1530 (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2)) ? BIGNUM_LENGTH(arg1)
1531 : BIGNUM_LENGTH(arg2);
1533 bignum* result = allot_bignum(max_length, 0);
1535 scanr = BIGNUM_START_PTR(result);
1536 scan1 = BIGNUM_START_PTR(arg1);
1537 scan2 = BIGNUM_START_PTR(arg2);
1538 endr = scanr + max_length;
1539 end1 = scan1 + BIGNUM_LENGTH(arg1);
1540 end2 = scan2 + BIGNUM_LENGTH(arg2);
1542 while (scanr < endr) {
1543 digit1 = (scan1 < end1) ? *scan1++ : 0;
1544 digit2 = (scan2 < end2) ? *scan2++ : 0;
1546 (op == AND_OP) ? digit1 & digit2 : (op == IOR_OP) ? digit1 | digit2
1549 return bignum_trim(result);
1553 bignum* factor_vm::bignum_posneg_bitwise_op(int op, bignum* arg1_,
1555 data_root<bignum> arg1(arg1_, this);
1556 data_root<bignum> arg2(arg2_, this);
1558 bignum_length_type max_length;
1560 bignum_digit_type* scan1, *end1, digit1;
1561 bignum_digit_type* scan2, *end2, digit2, carry2;
1562 bignum_digit_type* scanr, *endr;
1564 char neg_p = op == IOR_OP || op == XOR_OP;
1567 (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1) ? BIGNUM_LENGTH(arg1)
1568 : BIGNUM_LENGTH(arg2) + 1;
1570 bignum* result = allot_bignum(max_length, neg_p);
1572 scanr = BIGNUM_START_PTR(result);
1573 scan1 = BIGNUM_START_PTR(arg1);
1574 scan2 = BIGNUM_START_PTR(arg2);
1575 endr = scanr + max_length;
1576 end1 = scan1 + BIGNUM_LENGTH(arg1);
1577 end2 = scan2 + BIGNUM_LENGTH(arg2);
1581 while (scanr < endr) {
1582 digit1 = (scan1 < end1) ? *scan1++ : 0;
1583 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
1585 if (digit2 < BIGNUM_RADIX)
1588 digit2 = (digit2 - BIGNUM_RADIX);
1593 (op == AND_OP) ? digit1 & digit2 : (op == IOR_OP) ? digit1 | digit2
1598 bignum_negate_magnitude(result);
1600 return bignum_trim(result);
1604 bignum* factor_vm::bignum_negneg_bitwise_op(int op, bignum* arg1_,
1606 data_root<bignum> arg1(arg1_, this);
1607 data_root<bignum> arg2(arg2_, this);
1609 bignum_length_type max_length;
1611 bignum_digit_type* scan1, *end1, digit1, carry1;
1612 bignum_digit_type* scan2, *end2, digit2, carry2;
1613 bignum_digit_type* scanr, *endr;
1615 char neg_p = op == AND_OP || op == IOR_OP;
1618 (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2)) ? BIGNUM_LENGTH(arg1) + 1
1619 : BIGNUM_LENGTH(arg2) + 1;
1621 bignum* result = allot_bignum(max_length, neg_p);
1623 scanr = BIGNUM_START_PTR(result);
1624 scan1 = BIGNUM_START_PTR(arg1);
1625 scan2 = BIGNUM_START_PTR(arg2);
1626 endr = scanr + max_length;
1627 end1 = scan1 + BIGNUM_LENGTH(arg1);
1628 end2 = scan2 + BIGNUM_LENGTH(arg2);
1633 while (scanr < endr) {
1634 digit1 = (~((scan1 < end1) ? *scan1++ : 0) & BIGNUM_DIGIT_MASK) + carry1;
1635 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
1637 if (digit1 < BIGNUM_RADIX)
1640 digit1 = (digit1 - BIGNUM_RADIX);
1644 if (digit2 < BIGNUM_RADIX)
1647 digit2 = (digit2 - BIGNUM_RADIX);
1652 (op == AND_OP) ? digit1 & digit2 : (op == IOR_OP) ? digit1 | digit2
1657 bignum_negate_magnitude(result);
1659 return bignum_trim(result);
1662 void factor_vm::bignum_negate_magnitude(bignum* arg) {
1663 bignum_digit_type* scan;
1664 bignum_digit_type* end;
1665 bignum_digit_type digit;
1666 bignum_digit_type carry;
1668 scan = BIGNUM_START_PTR(arg);
1669 end = scan + BIGNUM_LENGTH(arg);
1673 while (scan < end) {
1674 digit = (~ * scan & BIGNUM_DIGIT_MASK) + carry;
1676 if (digit < BIGNUM_RADIX)
1679 digit = (digit - BIGNUM_RADIX);
1688 bignum* factor_vm::bignum_integer_length(bignum* x_) {
1689 data_root<bignum> x(x_, this);
1690 bignum_length_type index = ((BIGNUM_LENGTH(x)) - 1);
1691 bignum_digit_type digit = (BIGNUM_REF(x, index));
1692 bignum_digit_type carry = 0;
1700 if (index < BIGNUM_RADIX_ROOT) {
1701 result = allot_bignum(1, 0);
1702 (BIGNUM_REF(result, 0)) = (index * BIGNUM_DIGIT_LENGTH) + carry;
1704 result = allot_bignum(2, 0);
1705 (BIGNUM_REF(result, 0)) = index;
1706 (BIGNUM_REF(result, 1)) = 0;
1707 bignum_destructive_scale_up(result, BIGNUM_DIGIT_LENGTH);
1708 bignum_destructive_add(result, carry);
1710 return (bignum_trim(result));
1714 int factor_vm::bignum_logbitp(int shift, bignum* arg) {
1715 return ((BIGNUM_NEGATIVE_P(arg))
1716 ? !bignum_unsigned_logbitp(shift, bignum_bitwise_not(arg))
1717 : bignum_unsigned_logbitp(shift, arg));
1720 int factor_vm::bignum_unsigned_logbitp(int shift, bignum* bn) {
1721 bignum_length_type len = (BIGNUM_LENGTH(bn));
1722 int index = shift / BIGNUM_DIGIT_LENGTH;
1725 bignum_digit_type digit = (BIGNUM_REF(bn, index));
1726 int p = shift % BIGNUM_DIGIT_LENGTH;
1727 bignum_digit_type mask = ((fixnum)1) << p;
1728 return (digit & mask) ? 1 : 0;
1732 // Allocates memory.
1733 bignum* factor_vm::bignum_gcd(bignum* a_, bignum* b_) {
1735 data_root<bignum> a(a_, this);
1736 data_root<bignum> b(b_, this);
1738 // Copies of a and b with that are both positive.
1739 data_root<bignum> ac(bignum_maybe_new_sign(a.untagged(), 0), this);
1740 data_root<bignum> bc(bignum_maybe_new_sign(b.untagged(), 0), this);
1742 if (bignum_compare(ac.untagged(), bc.untagged()) == BIGNUM_COMPARISON_LESS) {
1746 while (BIGNUM_LENGTH(bc) != 0) {
1747 data_root<bignum> d(bignum_remainder(ac.untagged(), bc.untagged()), this);
1748 if (d.untagged() == BIGNUM_OUT_OF_BAND) {
1749 return d.untagged();
1754 return ac.untagged();
1758 bignum* factor_vm::bignum_gcd(bignum* a_, bignum* b_) {
1759 data_root<bignum> a(a_, this);
1760 data_root<bignum> b(b_, this);
1761 bignum_twodigit_type x, y, q, s, t, A, B, C, D;
1762 unsigned long nbits;
1764 bignum_length_type size_a, size_b, size_c;
1765 bignum_digit_type* scan_a, *scan_b, *scan_c, *scan_d;
1766 bignum_digit_type* a_end, *b_end, *c_end;
1768 // clone the bignums so we can modify them in-place
1769 size_a = BIGNUM_LENGTH(a);
1770 data_root<bignum> c(allot_bignum(size_a, 0), this);
1771 // c = allot_bignum(size_a, 0);
1772 scan_a = BIGNUM_START_PTR(a);
1773 a_end = scan_a + size_a;
1774 scan_c = BIGNUM_START_PTR(c);
1775 while (scan_a < a_end)
1776 (*scan_c++) = (*scan_a++);
1778 size_b = BIGNUM_LENGTH(b);
1779 data_root<bignum> d(allot_bignum(size_b, 0), this);
1780 scan_b = BIGNUM_START_PTR(b);
1781 b_end = scan_b + size_b;
1782 scan_d = BIGNUM_START_PTR(d);
1783 while (scan_b < b_end)
1784 (*scan_d++) = (*scan_b++);
1787 // Initial reduction: make sure that 0 <= b <= a.
1788 if (bignum_compare(a.untagged(), b.untagged()) == BIGNUM_COMPARISON_LESS) {
1790 std::swap(size_a, size_b);
1793 while (size_a > 1) {
1794 nbits = log2(BIGNUM_REF(a, size_a - 1));
1795 x = ((BIGNUM_REF(a, size_a - 1) << (BIGNUM_DIGIT_LENGTH - nbits)) |
1796 (BIGNUM_REF(a, size_a - 2) >> nbits));
1797 y = ((size_b >= size_a - 1 ? BIGNUM_REF(b, size_a - 2) >> nbits : 0) |
1799 ? BIGNUM_REF(b, size_a - 1) << (BIGNUM_DIGIT_LENGTH - nbits)
1802 // inner loop of Lehmer's algorithm;
1811 q = (x + (A - 1)) / (y - C);
1831 // no progress; do a Euclidean step
1833 return bignum_trim(a.untagged());
1835 data_root<bignum> e(bignum_trim(a.untagged()), this);
1836 data_root<bignum> f(bignum_trim(b.untagged()), this);
1837 c.set_untagged(bignum_remainder(e.untagged(), f.untagged()));
1838 if (c.untagged() == BIGNUM_OUT_OF_BAND) {
1839 return c.untagged();
1843 scan_a = BIGNUM_START_PTR(a);
1844 scan_b = BIGNUM_START_PTR(b);
1845 a_end = scan_a + size_a;
1846 b_end = scan_b + size_b;
1847 while (scan_b < b_end)
1848 *(scan_a++) = *(scan_b++);
1849 while (scan_a < a_end)
1854 scan_b = BIGNUM_START_PTR(b);
1855 scan_c = BIGNUM_START_PTR(c);
1856 size_c = BIGNUM_LENGTH(c);
1857 c_end = scan_c + size_c;
1858 while (scan_c < c_end)
1859 *(scan_b++) = *(scan_c++);
1860 while (scan_b < b_end)
1867 // a, b = A*b - B*a, D*a - C*b if k is odd
1868 // a, b = A*a - B*b, D*b - C*a if k is even
1870 scan_a = BIGNUM_START_PTR(a);
1871 scan_b = BIGNUM_START_PTR(b);
1874 a_end = scan_a + size_a;
1875 b_end = scan_b + size_b;
1879 while (scan_b < b_end) {
1880 s += (A * *scan_b) - (B * *scan_a);
1881 t += (D * *scan_a++) - (C * *scan_b++);
1882 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1883 *scan_d++ = (bignum_digit_type)(t & BIGNUM_DIGIT_MASK);
1884 s >>= BIGNUM_DIGIT_LENGTH;
1885 t >>= BIGNUM_DIGIT_LENGTH;
1887 while (scan_a < a_end) {
1889 t += (D * *scan_a++);
1890 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1891 //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1892 s >>= BIGNUM_DIGIT_LENGTH;
1893 t >>= BIGNUM_DIGIT_LENGTH;
1896 while (scan_b < b_end) {
1897 s += (A * *scan_a) - (B * *scan_b);
1898 t += (D * *scan_b++) - (C * *scan_a++);
1899 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1900 *scan_d++ = (bignum_digit_type)(t & BIGNUM_DIGIT_MASK);
1901 s >>= BIGNUM_DIGIT_LENGTH;
1902 t >>= BIGNUM_DIGIT_LENGTH;
1904 while (scan_a < a_end) {
1906 t -= (C * *scan_a++);
1907 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1908 //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1909 s >>= BIGNUM_DIGIT_LENGTH;
1910 t >>= BIGNUM_DIGIT_LENGTH;
1913 BIGNUM_ASSERT(s == 0);
1914 BIGNUM_ASSERT(t == 0);
1916 // update size_a and size_b to remove any zeros at end
1917 while (size_a > 0 && *(--scan_a) == 0)
1919 while (size_b > 0 && *(--scan_b) == 0)
1922 BIGNUM_ASSERT(size_a >= size_b);
1925 // a fits into a fixnum, so b must too
1926 fixnum xx = bignum_to_fixnum(a.untagged());
1927 fixnum yy = bignum_to_fixnum(b.untagged());
1930 // usual Euclidean algorithm for longs
1937 return fixnum_to_bignum(xx);