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
58 int factor_vm::bignum_equal_p(bignum* x, bignum* y) {
59 return ((BIGNUM_ZERO_P(x))
61 : ((!(BIGNUM_ZERO_P(y))) &&
62 ((BIGNUM_NEGATIVE_P(x)) ? (BIGNUM_NEGATIVE_P(y))
63 : (!(BIGNUM_NEGATIVE_P(y)))) &&
64 (bignum_equal_p_unsigned(x, y))));
67 enum bignum_comparison factor_vm::bignum_compare(bignum* x, bignum* y) {
68 return ((BIGNUM_ZERO_P(x)) ? ((BIGNUM_ZERO_P(y)) ? bignum_comparison_equal
69 : (BIGNUM_NEGATIVE_P(y))
70 ? bignum_comparison_greater
71 : bignum_comparison_less)
73 ? ((BIGNUM_NEGATIVE_P(x)) ? bignum_comparison_less
74 : bignum_comparison_greater)
75 : (BIGNUM_NEGATIVE_P(x))
76 ? ((BIGNUM_NEGATIVE_P(y)) ? (bignum_compare_unsigned(y, x))
77 : (bignum_comparison_less))
78 : ((BIGNUM_NEGATIVE_P(y)) ? (bignum_comparison_greater)
79 : (bignum_compare_unsigned(x, y))));
82 /* Allocates memory */
83 bignum* factor_vm::bignum_add(bignum* x, bignum* y) {
85 (BIGNUM_ZERO_P(x)) ? (y) : (BIGNUM_ZERO_P(y))
87 : ((BIGNUM_NEGATIVE_P(x))
88 ? ((BIGNUM_NEGATIVE_P(y)) ? (bignum_add_unsigned(x, y, 1))
89 : (bignum_subtract_unsigned(y, x)))
90 : ((BIGNUM_NEGATIVE_P(y)) ? (bignum_subtract_unsigned(x, y))
91 : (bignum_add_unsigned(x, y, 0)))));
94 /* Allocates memory */
95 bignum* factor_vm::bignum_subtract(bignum* x, bignum* y) {
96 return ((BIGNUM_ZERO_P(x))
97 ? ((BIGNUM_ZERO_P(y)) ? (y) : (bignum_new_sign(
98 y, (!(BIGNUM_NEGATIVE_P(y))))))
101 : ((BIGNUM_NEGATIVE_P(x))
102 ? ((BIGNUM_NEGATIVE_P(y))
103 ? (bignum_subtract_unsigned(y, x))
104 : (bignum_add_unsigned(x, y, 1)))
105 : ((BIGNUM_NEGATIVE_P(y))
106 ? (bignum_add_unsigned(x, y, 0))
107 : (bignum_subtract_unsigned(x, y))))));
111 bignum *factor_vm::bignum_square(bignum* x_)
113 return bignum_multiply(x_, x_);
116 /* Allocates memory */
117 bignum *factor_vm::bignum_square(bignum* x_)
119 data_root<bignum> x(x_, this);
121 bignum_length_type length = (BIGNUM_LENGTH (x));
122 bignum * z = (allot_bignum_zeroed ((length + length), 0));
124 bignum_digit_type * scan_z = BIGNUM_START_PTR (z);
125 bignum_digit_type * scan_x = BIGNUM_START_PTR (x);
126 bignum_digit_type * end_x = scan_x + length;
128 for (int i = 0; i < length; ++i) {
129 bignum_twodigit_type carry;
130 bignum_twodigit_type f = BIGNUM_REF (x, i);
131 bignum_digit_type *pz = scan_z + (i << 1);
132 bignum_digit_type *px = scan_x + i + 1;
135 *pz++ = carry & BIGNUM_DIGIT_MASK;
136 carry >>= BIGNUM_DIGIT_LENGTH;
137 BIGNUM_ASSERT (carry <= BIGNUM_DIGIT_MASK);
142 carry += *pz + *px++ * f;
143 *pz++ = carry & BIGNUM_DIGIT_MASK;
144 carry >>= BIGNUM_DIGIT_LENGTH;
145 BIGNUM_ASSERT (carry <= (BIGNUM_DIGIT_MASK << 1));
149 *pz++ = carry & BIGNUM_DIGIT_MASK;
150 carry >>= BIGNUM_DIGIT_LENGTH;
153 *pz += carry & BIGNUM_DIGIT_MASK;
154 BIGNUM_ASSERT ((carry >> BIGNUM_DIGIT_LENGTH) == 0);
156 return (bignum_trim (z));
160 /* Allocates memory */
161 bignum* factor_vm::bignum_multiply(bignum* x, bignum* y) {
165 return bignum_square(x);
169 bignum_length_type x_length = (BIGNUM_LENGTH(x));
170 bignum_length_type y_length = (BIGNUM_LENGTH(y));
171 int negative_p = ((BIGNUM_NEGATIVE_P(x)) ? (!(BIGNUM_NEGATIVE_P(y)))
172 : (BIGNUM_NEGATIVE_P(y)));
173 if (BIGNUM_ZERO_P(x))
175 if (BIGNUM_ZERO_P(y))
178 bignum_digit_type digit = (BIGNUM_REF(x, 0));
180 return (bignum_maybe_new_sign(y, negative_p));
181 if (digit < BIGNUM_RADIX_ROOT)
182 return (bignum_multiply_unsigned_small_factor(y, digit, negative_p));
185 bignum_digit_type digit = (BIGNUM_REF(y, 0));
187 return (bignum_maybe_new_sign(x, negative_p));
188 if (digit < BIGNUM_RADIX_ROOT)
189 return (bignum_multiply_unsigned_small_factor(x, digit, negative_p));
191 return (bignum_multiply_unsigned(x, y, negative_p));
194 /* Allocates memory */
195 void factor_vm::bignum_divide(bignum* numerator, bignum* denominator,
196 bignum** quotient, bignum** remainder) {
197 if (BIGNUM_ZERO_P(denominator)) {
198 divide_by_zero_error();
201 if (BIGNUM_ZERO_P(numerator)) {
202 (*quotient) = numerator;
203 (*remainder) = numerator;
205 int r_negative_p = (BIGNUM_NEGATIVE_P(numerator));
207 ((BIGNUM_NEGATIVE_P(denominator)) ? (!r_negative_p) : r_negative_p);
208 switch (bignum_compare_unsigned(numerator, denominator)) {
209 case bignum_comparison_equal: {
210 (*quotient) = (BIGNUM_ONE(q_negative_p));
211 (*remainder) = (BIGNUM_ZERO());
214 case bignum_comparison_less: {
215 (*quotient) = (BIGNUM_ZERO());
216 (*remainder) = numerator;
219 case bignum_comparison_greater: {
220 if ((BIGNUM_LENGTH(denominator)) == 1) {
221 bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
223 (*quotient) = (bignum_maybe_new_sign(numerator, q_negative_p));
224 (*remainder) = (BIGNUM_ZERO());
226 } else if (digit < BIGNUM_RADIX_ROOT) {
227 bignum_divide_unsigned_small_denominator(numerator, digit, quotient,
228 remainder, q_negative_p,
232 bignum_divide_unsigned_medium_denominator(
233 numerator, digit, quotient, remainder, q_negative_p,
238 bignum_divide_unsigned_large_denominator(
239 numerator, denominator, quotient, remainder, q_negative_p,
247 /* Allocates memory */
248 bignum* factor_vm::bignum_quotient(bignum* numerator, bignum* denominator) {
249 if (BIGNUM_ZERO_P(denominator)) {
250 divide_by_zero_error();
251 return (BIGNUM_OUT_OF_BAND);
253 if (BIGNUM_ZERO_P(numerator))
257 ((BIGNUM_NEGATIVE_P(denominator)) ? (!(BIGNUM_NEGATIVE_P(numerator)))
258 : (BIGNUM_NEGATIVE_P(numerator)));
259 switch (bignum_compare_unsigned(numerator, denominator)) {
260 case bignum_comparison_equal:
261 return (BIGNUM_ONE(q_negative_p));
262 case bignum_comparison_less:
263 return (BIGNUM_ZERO());
264 case bignum_comparison_greater:
265 default: /* to appease gcc -Wall */
268 if ((BIGNUM_LENGTH(denominator)) == 1) {
269 bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
271 return (bignum_maybe_new_sign(numerator, q_negative_p));
272 if (digit < BIGNUM_RADIX_ROOT)
273 bignum_divide_unsigned_small_denominator(
274 numerator, digit, ("ient), ((bignum**)0), q_negative_p, 0);
276 bignum_divide_unsigned_medium_denominator(
277 numerator, digit, ("ient), ((bignum**)0), q_negative_p, 0);
279 bignum_divide_unsigned_large_denominator(
280 numerator, denominator, ("ient), ((bignum**)0), q_negative_p,
288 /* Allocates memory */
289 bignum* factor_vm::bignum_remainder(bignum* numerator, bignum* denominator) {
290 if (BIGNUM_ZERO_P(denominator)) {
291 divide_by_zero_error();
292 return (BIGNUM_OUT_OF_BAND);
294 if (BIGNUM_ZERO_P(numerator))
296 switch (bignum_compare_unsigned(numerator, denominator)) {
297 case bignum_comparison_equal:
298 return (BIGNUM_ZERO());
299 case bignum_comparison_less:
301 case bignum_comparison_greater:
302 default: /* to appease gcc -Wall */
305 if ((BIGNUM_LENGTH(denominator)) == 1) {
306 bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
308 return (BIGNUM_ZERO());
309 if (digit < BIGNUM_RADIX_ROOT)
310 return (bignum_remainder_unsigned_small_denominator(
311 numerator, digit, (BIGNUM_NEGATIVE_P(numerator))));
312 bignum_divide_unsigned_medium_denominator(
313 numerator, digit, ((bignum**)0), (&remainder), 0,
314 (BIGNUM_NEGATIVE_P(numerator)));
316 bignum_divide_unsigned_large_denominator(
317 numerator, denominator, ((bignum**)0), (&remainder), 0,
318 (BIGNUM_NEGATIVE_P(numerator)));
324 /* cell_to_bignum, fixnum_to_bignum, long_long_to_bignum, ulong_long_to_bignum
326 /* Allocates memory */
327 #define FOO_TO_BIGNUM(name, type, stype, utype) \
328 bignum* factor_vm::name##_to_bignum(type n) { \
330 /* Special cases win when these small constants are cached. */ \
332 return (BIGNUM_ZERO()); \
334 return (BIGNUM_ONE(0)); \
335 if (n < (type) 0 && n == (type) - 1) \
336 return (BIGNUM_ONE(1)); \
338 utype accumulator = \
339 ((negative_p = (n < (type) 0)) ? ((type)(-(stype) n)) : n); \
340 if (accumulator < BIGNUM_RADIX) \
342 bignum* result = allot_bignum(1, negative_p); \
343 bignum_digit_type* scan = (BIGNUM_START_PTR(result)); \
344 *scan = (accumulator & BIGNUM_DIGIT_MASK); \
347 bignum_digit_type result_digits[BIGNUM_DIGITS_FOR(type)]; \
348 bignum_digit_type* end_digits = result_digits; \
350 (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK); \
351 accumulator >>= BIGNUM_DIGIT_LENGTH; \
352 } while (accumulator != 0); \
354 (allot_bignum((end_digits - result_digits), negative_p)); \
355 bignum_digit_type* scan_digits = result_digits; \
356 bignum_digit_type* scan_result = (BIGNUM_START_PTR(result)); \
357 while (scan_digits < end_digits) \
358 (*scan_result++) = (*scan_digits++); \
364 FOO_TO_BIGNUM(cell, cell, fixnum, cell)
365 FOO_TO_BIGNUM(fixnum, fixnum, fixnum, cell)
366 FOO_TO_BIGNUM(long_long, int64_t, int64_t, uint64_t)
367 FOO_TO_BIGNUM(ulong_long, uint64_t, int64_t, uint64_t)
369 /* cannot allocate memory */
370 /* bignum_to_cell, fixnum_to_cell, long_long_to_cell, ulong_long_to_cell */
371 #define BIGNUM_TO_FOO(name, type, stype, utype) \
372 type bignum_to_##name(bignum* bn) { \
373 if (BIGNUM_ZERO_P(bn)) \
376 utype accumulator = 0; \
377 bignum_digit_type* start = (BIGNUM_START_PTR(bn)); \
378 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(bn))); \
379 while (start < scan) \
380 accumulator = ((accumulator << BIGNUM_DIGIT_LENGTH) + (*--scan)); \
381 return ((BIGNUM_NEGATIVE_P(bn)) ? ((type)(-(stype) accumulator)) \
386 BIGNUM_TO_FOO(cell, cell, fixnum, cell)
387 BIGNUM_TO_FOO(fixnum, fixnum, fixnum, cell)
388 BIGNUM_TO_FOO(long_long, int64_t, int64_t, uint64_t)
389 BIGNUM_TO_FOO(ulong_long, uint64_t, int64_t, uint64_t)
391 /* cannot allocate memory */
392 fixnum factor_vm::bignum_to_fixnum_strict(bignum* bn) {
393 fixnum len = BIGNUM_LENGTH(bn);
394 bignum_digit_type *digits = BIGNUM_START_PTR(bn);
395 if ((len == 1 && digits[0] > fixnum_max) || (len > 1)) {
396 general_error(ERROR_OUT_OF_FIXNUM_RANGE, tag<bignum>(bn), false_object);
398 fixnum fix = bignum_to_fixnum(bn);
399 FACTOR_ASSERT(fix <= fixnum_max && fix >= fixnum_min);
403 #define DTB_WRITE_DIGIT(factor) \
405 significand *= (factor); \
406 digit = ((bignum_digit_type) significand); \
408 significand -= ((double)digit); \
411 #define inf std::numeric_limits<double>::infinity()
413 /* Allocates memory */
414 bignum* factor_vm::double_to_bignum(double x) {
415 if (x == inf || x == -inf || x != x)
416 return (BIGNUM_ZERO());
418 double significand = (frexp(x, (&exponent)));
420 return (BIGNUM_ZERO());
422 return (BIGNUM_ONE(x < 0));
424 significand = (-significand);
426 bignum_length_type length = (BIGNUM_BITS_TO_DIGITS(exponent));
427 bignum* result = (allot_bignum(length, (x < 0)));
428 bignum_digit_type* start = (BIGNUM_START_PTR(result));
429 bignum_digit_type* scan = (start + length);
430 bignum_digit_type digit;
431 int odd_bits = (exponent % BIGNUM_DIGIT_LENGTH);
433 DTB_WRITE_DIGIT((fixnum)1 << odd_bits);
434 while (start < scan) {
435 if (significand == 0) {
440 DTB_WRITE_DIGIT(BIGNUM_RADIX);
446 #undef DTB_WRITE_DIGIT
450 int factor_vm::bignum_equal_p_unsigned(bignum* x, bignum* y) {
451 bignum_length_type length = (BIGNUM_LENGTH(x));
452 if (length != (BIGNUM_LENGTH(y)))
455 bignum_digit_type* scan_x = (BIGNUM_START_PTR(x));
456 bignum_digit_type* scan_y = (BIGNUM_START_PTR(y));
457 bignum_digit_type* end_x = (scan_x + length);
458 while (scan_x < end_x)
459 if ((*scan_x++) != (*scan_y++))
465 enum bignum_comparison factor_vm::bignum_compare_unsigned(bignum* x,
467 bignum_length_type x_length = (BIGNUM_LENGTH(x));
468 bignum_length_type y_length = (BIGNUM_LENGTH(y));
469 if (x_length < y_length)
470 return (bignum_comparison_less);
471 if (x_length > y_length)
472 return (bignum_comparison_greater);
474 bignum_digit_type* start_x = (BIGNUM_START_PTR(x));
475 bignum_digit_type* scan_x = (start_x + x_length);
476 bignum_digit_type* scan_y = ((BIGNUM_START_PTR(y)) + y_length);
477 while (start_x < scan_x) {
478 bignum_digit_type digit_x = (*--scan_x);
479 bignum_digit_type digit_y = (*--scan_y);
480 if (digit_x < digit_y)
481 return (bignum_comparison_less);
482 if (digit_x > digit_y)
483 return (bignum_comparison_greater);
486 return (bignum_comparison_equal);
491 /* Allocates memory */
492 bignum* factor_vm::bignum_add_unsigned(bignum* x_, bignum* y_, int negative_p) {
494 data_root<bignum> x(x_, this);
495 data_root<bignum> y(y_, this);
496 if ((BIGNUM_LENGTH(y)) > (BIGNUM_LENGTH(x))) {
500 bignum_length_type x_length = (BIGNUM_LENGTH(x));
502 bignum* r = (allot_bignum((x_length + 1), negative_p));
504 bignum_digit_type sum;
505 bignum_digit_type carry = 0;
506 bignum_digit_type* scan_x = (BIGNUM_START_PTR(x));
507 bignum_digit_type* scan_r = (BIGNUM_START_PTR(r));
509 bignum_digit_type* scan_y = (BIGNUM_START_PTR(y));
510 bignum_digit_type* end_y = (scan_y + (BIGNUM_LENGTH(y)));
511 while (scan_y < end_y) {
512 sum = ((*scan_x++) + (*scan_y++) + carry);
513 if (sum < BIGNUM_RADIX) {
517 (*scan_r++) = (sum - BIGNUM_RADIX);
523 bignum_digit_type* end_x = BIGNUM_START_PTR(x) + x_length;
525 while (scan_x < end_x) {
526 sum = ((*scan_x++) + 1);
527 if (sum < BIGNUM_RADIX) {
532 (*scan_r++) = (sum - BIGNUM_RADIX);
534 while (scan_x < end_x)
535 (*scan_r++) = (*scan_x++);
541 return (bignum_shorten_length(r, x_length));
547 /* Allocates memory */
548 bignum* factor_vm::bignum_subtract_unsigned(bignum* x_, bignum* y_) {
550 data_root<bignum> x(x_, this);
551 data_root<bignum> y(y_, this);
554 switch (bignum_compare_unsigned(x.untagged(), y.untagged())) {
555 case bignum_comparison_equal:
556 return (BIGNUM_ZERO());
557 case bignum_comparison_less:
561 case bignum_comparison_greater:
566 bignum_length_type x_length = (BIGNUM_LENGTH(x));
568 bignum* r = (allot_bignum(x_length, negative_p));
570 bignum_digit_type difference;
571 bignum_digit_type borrow = 0;
572 bignum_digit_type* scan_x = BIGNUM_START_PTR(x);
573 bignum_digit_type* scan_r = BIGNUM_START_PTR(r);
575 bignum_digit_type* scan_y = BIGNUM_START_PTR(y);
576 bignum_digit_type* end_y = (scan_y + (BIGNUM_LENGTH(y)));
577 while (scan_y < end_y) {
578 difference = (((*scan_x++) - (*scan_y++)) - borrow);
579 if (difference < 0) {
580 (*scan_r++) = (difference + BIGNUM_RADIX);
583 (*scan_r++) = difference;
589 bignum_digit_type* end_x = BIGNUM_START_PTR(x) + x_length;
591 while (scan_x < end_x) {
592 difference = ((*scan_x++) - borrow);
594 (*scan_r++) = (difference + BIGNUM_RADIX);
596 (*scan_r++) = difference;
601 BIGNUM_ASSERT(borrow == 0);
602 while (scan_x < end_x)
603 (*scan_r++) = (*scan_x++);
605 return (bignum_trim(r));
610 Maximum value for product_low or product_high:
611 ((R * R) + (R * (R - 2)) + (R - 1))
612 Maximum value for carry: ((R * (R - 1)) + (R - 1))
613 where R == BIGNUM_RADIX_ROOT */
615 /* Allocates memory */
616 bignum* factor_vm::bignum_multiply_unsigned(bignum* x_, bignum* y_,
619 data_root<bignum> x(x_, this);
620 data_root<bignum> y(y_, this);
622 if (BIGNUM_LENGTH(y) > BIGNUM_LENGTH(x)) {
626 bignum_digit_type carry;
627 bignum_digit_type y_digit_low;
628 bignum_digit_type y_digit_high;
629 bignum_digit_type x_digit_low;
630 bignum_digit_type x_digit_high;
631 bignum_digit_type product_low;
632 bignum_digit_type* scan_r;
633 bignum_digit_type* scan_y;
634 bignum_length_type x_length = BIGNUM_LENGTH(x);
635 bignum_length_type y_length = BIGNUM_LENGTH(y);
637 bignum* r = (allot_bignum_zeroed((x_length + y_length), negative_p));
639 bignum_digit_type* scan_x = BIGNUM_START_PTR(x);
640 bignum_digit_type* end_x = (scan_x + x_length);
641 bignum_digit_type* start_y = BIGNUM_START_PTR(y);
642 bignum_digit_type* end_y = (start_y + y_length);
643 bignum_digit_type* start_r = (BIGNUM_START_PTR(r));
644 #define x_digit x_digit_high
645 #define y_digit y_digit_high
646 #define product_high carry
647 while (scan_x < end_x) {
648 x_digit = (*scan_x++);
649 x_digit_low = (HD_LOW(x_digit));
650 x_digit_high = (HD_HIGH(x_digit));
653 scan_r = (start_r++);
654 while (scan_y < end_y) {
655 y_digit = (*scan_y++);
656 y_digit_low = (HD_LOW(y_digit));
657 y_digit_high = (HD_HIGH(y_digit));
659 ((*scan_r) + (x_digit_low * y_digit_low) + (HD_LOW(carry)));
661 ((x_digit_high * y_digit_low) + (x_digit_low * y_digit_high) +
662 (HD_HIGH(product_low)) + (HD_HIGH(carry)));
663 (*scan_r++) = (HD_CONS((HD_LOW(product_high)), (HD_LOW(product_low))));
664 carry = ((x_digit_high * y_digit_high) + (HD_HIGH(product_high)));
668 return (bignum_trim(r));
675 /* Allocates memory */
676 bignum* factor_vm::bignum_multiply_unsigned_small_factor(bignum* x_,
679 data_root<bignum> x(x_, this);
681 bignum_length_type length_x = (BIGNUM_LENGTH(x));
683 bignum* p = (allot_bignum((length_x + 1), negative_p));
685 bignum_destructive_copy(x.untagged(), p);
686 (BIGNUM_REF(p, length_x)) = 0;
687 bignum_destructive_scale_up(p, y);
688 return (bignum_trim(p));
691 void factor_vm::bignum_destructive_add(bignum* bn, bignum_digit_type n) {
692 bignum_digit_type* scan = (BIGNUM_START_PTR(bn));
693 bignum_digit_type digit;
694 digit = ((*scan) + n);
695 if (digit < BIGNUM_RADIX) {
699 (*scan++) = (digit - BIGNUM_RADIX);
701 digit = ((*scan) + 1);
702 if (digit < BIGNUM_RADIX) {
706 (*scan++) = (digit - BIGNUM_RADIX);
710 void factor_vm::bignum_destructive_scale_up(bignum* bn,
711 bignum_digit_type factor) {
712 bignum_digit_type carry = 0;
713 bignum_digit_type* scan = (BIGNUM_START_PTR(bn));
714 bignum_digit_type two_digits;
715 bignum_digit_type product_low;
716 #define product_high carry
717 bignum_digit_type* end = (scan + (BIGNUM_LENGTH(bn)));
718 BIGNUM_ASSERT((factor > 1) && (factor < BIGNUM_RADIX_ROOT));
720 two_digits = (*scan);
721 product_low = ((factor * (HD_LOW(two_digits))) + (HD_LOW(carry)));
722 product_high = ((factor * (HD_HIGH(two_digits))) + (HD_HIGH(product_low)) +
724 (*scan++) = (HD_CONS((HD_LOW(product_high)), (HD_LOW(product_low))));
725 carry = (HD_HIGH(product_high));
727 /* A carry here would be an overflow, i.e. it would not fit.
728 Hopefully the callers allocate enough space that this will
731 BIGNUM_ASSERT(carry == 0);
738 /* For help understanding this algorithm, see:
739 Knuth, Donald E., "The Art of Computer Programming",
740 volume 2, "Seminumerical Algorithms"
741 section 4.3.1, "Multiple-Precision Arithmetic". */
743 /* Allocates memory */
744 void factor_vm::bignum_divide_unsigned_large_denominator(
745 bignum* numerator_, bignum* denominator_,
746 bignum** quotient, bignum** remainder,
747 int q_negative_p, int r_negative_p) {
749 data_root<bignum> numerator(numerator_, this);
750 data_root<bignum> denominator(denominator_, this);
752 bignum_length_type length_n = BIGNUM_LENGTH(numerator) + 1;
753 bignum_length_type length_d = BIGNUM_LENGTH(denominator);
755 data_root<bignum> u(allot_bignum(length_n, r_negative_p), this);
758 BIGNUM_ASSERT(length_d > 1);
760 bignum_digit_type v1 = BIGNUM_REF(denominator.untagged(), length_d - 1);
761 while (v1 < (BIGNUM_RADIX / 2)) {
767 if (quotient != NULL) {
768 bignum *q_ = allot_bignum(length_n - length_d, q_negative_p);
769 data_root<bignum> q(q_, this);
772 bignum_destructive_copy(numerator.untagged(), u.untagged());
773 (BIGNUM_REF(u.untagged(), (length_n - 1))) = 0;
774 bignum_divide_unsigned_normalized(u.untagged(),
775 denominator.untagged(),
778 bignum* v = allot_bignum(length_d, 0);
779 bignum_destructive_normalization(numerator.untagged(),
782 bignum_destructive_normalization(denominator.untagged(), v, shift);
783 bignum_divide_unsigned_normalized(u.untagged(), v, q.untagged());
784 if (remainder != NULL)
785 bignum_destructive_unnormalization(u.untagged(), shift);
788 q = bignum_trim(q.untagged());
789 *quotient = q.untagged();
793 bignum_destructive_copy(numerator.untagged(), u.untagged());
794 (BIGNUM_REF(u.untagged(), (length_n - 1))) = 0;
795 bignum_divide_unsigned_normalized(u.untagged(),
796 denominator.untagged(),
799 bignum* v = allot_bignum(length_d, 0);
800 bignum_destructive_normalization(numerator.untagged(),
803 bignum_destructive_normalization(denominator.untagged(),
806 bignum_divide_unsigned_normalized(u.untagged(), v, NULL);
807 if (remainder != NULL)
808 bignum_destructive_unnormalization(u.untagged(), shift);
812 u = bignum_trim(u.untagged());
813 if (remainder != NULL)
814 *remainder = u.untagged();
817 void factor_vm::bignum_divide_unsigned_normalized(bignum* u, bignum* v,
819 bignum_length_type u_length = (BIGNUM_LENGTH(u));
820 bignum_length_type v_length = (BIGNUM_LENGTH(v));
821 bignum_digit_type* u_start = (BIGNUM_START_PTR(u));
822 bignum_digit_type* u_scan = (u_start + u_length);
823 bignum_digit_type* u_scan_limit = (u_start + v_length);
824 bignum_digit_type* u_scan_start = (u_scan - v_length);
825 bignum_digit_type* v_start = (BIGNUM_START_PTR(v));
826 bignum_digit_type* v_end = (v_start + v_length);
827 bignum_digit_type* q_scan = NULL;
828 bignum_digit_type v1 = (v_end[-1]);
829 bignum_digit_type v2 = (v_end[-2]);
830 bignum_digit_type ph; /* high half of double-digit product */
831 bignum_digit_type pl; /* low half of double-digit product */
832 bignum_digit_type guess;
833 bignum_digit_type gh; /* high half-digit of guess */
834 bignum_digit_type ch; /* high half of double-digit comparand */
835 bignum_digit_type v2l = (HD_LOW(v2));
836 bignum_digit_type v2h = (HD_HIGH(v2));
837 bignum_digit_type cl; /* low half of double-digit comparand */
838 #define gl ph /* low half-digit of guess */
841 bignum_digit_type gm; /* memory loc for reference parameter */
842 if (q != BIGNUM_OUT_OF_BAND)
843 q_scan = ((BIGNUM_START_PTR(q)) + (BIGNUM_LENGTH(q)));
844 while (u_scan_limit < u_scan) {
848 (((((uj * BIGNUM_RADIX) + uj1) % v1) * BIGNUM_RADIX) + uj2);
849 guess = (((uj * BIGNUM_RADIX) + uj1) / v1); */
851 ch = (bignum_digit_divide(uj, (u_scan[-1]), v1, (&gm)));
855 ch = ((u_scan[-1]) + v1);
856 guess = (BIGNUM_RADIX - 1);
859 /* product = (guess * v2); */
860 gl = (HD_LOW(guess));
861 gh = (HD_HIGH(guess));
863 ph = ((v2l * gh) + (v2h * gl) + (HD_HIGH(pl)));
864 pl = (HD_CONS((HD_LOW(ph)), (HD_LOW(pl))));
865 ph = ((v2h * gh) + (HD_HIGH(ph)));
866 /* if (comparand >= product) */
867 if ((ch > ph) || ((ch == ph) && (cl >= pl)))
870 /* comparand += (v1 << BIGNUM_DIGIT_LENGTH) */
872 /* if (comparand >= (BIGNUM_RADIX * BIGNUM_RADIX)) */
873 if (ch >= BIGNUM_RADIX)
876 qj = (bignum_divide_subtract(v_start, v_end, guess, (--u_scan_start)));
877 if (q != BIGNUM_OUT_OF_BAND)
886 bignum_digit_type factor_vm::bignum_divide_subtract(
887 bignum_digit_type* v_start, bignum_digit_type* v_end,
888 bignum_digit_type guess, bignum_digit_type* u_start) {
889 bignum_digit_type* v_scan = v_start;
890 bignum_digit_type* u_scan = u_start;
891 bignum_digit_type carry = 0;
895 bignum_digit_type gl = (HD_LOW(guess));
896 bignum_digit_type gh = (HD_HIGH(guess));
898 bignum_digit_type pl;
899 bignum_digit_type vl;
903 while (v_scan < v_end) {
907 pl = ((vl * gl) + (HD_LOW(carry)));
908 ph = ((vl * gh) + (vh * gl) + (HD_HIGH(pl)) + (HD_HIGH(carry)));
909 diff = ((*u_scan) - (HD_CONS((HD_LOW(ph)), (HD_LOW(pl)))));
911 (*u_scan++) = (diff + BIGNUM_RADIX);
912 carry = ((vh * gh) + (HD_HIGH(ph)) + 1);
915 carry = ((vh * gh) + (HD_HIGH(ph)));
920 diff = ((*u_scan) - carry);
922 (*u_scan) = (diff + BIGNUM_RADIX);
931 /* Subtraction generated carry, implying guess is one too large.
932 Add v back in to bring it back down. */
936 while (v_scan < v_end) {
937 bignum_digit_type sum = ((*v_scan++) + (*u_scan) + carry);
938 if (sum < BIGNUM_RADIX) {
942 (*u_scan++) = (sum - BIGNUM_RADIX);
947 bignum_digit_type sum = ((*u_scan) + carry);
948 (*u_scan) = ((sum < BIGNUM_RADIX) ? sum : (sum - BIGNUM_RADIX));
953 /* Allocates memory */
954 void factor_vm::bignum_divide_unsigned_medium_denominator(
955 bignum* numerator_, bignum_digit_type denominator, bignum** quotient,
956 bignum** remainder, int q_negative_p, int r_negative_p) {
958 data_root<bignum> numerator(numerator_, this);
960 bignum_length_type length_n = (BIGNUM_LENGTH(numerator));
963 /* Because `bignum_digit_divide' requires a normalized denominator. */
964 while (denominator < (BIGNUM_RADIX / 2)) {
969 bignum_length_type length_q = (shift == 0) ? length_n : length_n + 1;
970 data_root<bignum> q(allot_bignum(length_q, q_negative_p), this);
972 bignum_destructive_copy(numerator.untagged(), q.untagged());
974 bignum_destructive_normalization(numerator.untagged(), q.untagged(), shift);
977 bignum_digit_type r = 0;
978 bignum_digit_type* start = (BIGNUM_START_PTR(q));
979 bignum_digit_type* scan = (start + length_q);
980 bignum_digit_type qj;
982 while (start < scan) {
983 r = (bignum_digit_divide(r, (*--scan), denominator, (&qj)));
987 q = bignum_trim(q.untagged());
989 if (remainder != ((bignum**)0)) {
993 (*remainder) = (bignum_digit_to_bignum(r, r_negative_p));
996 if (quotient != ((bignum**)0))
997 (*quotient) = q.untagged();
1002 void factor_vm::bignum_destructive_normalization(bignum* source, bignum* target,
1004 bignum_digit_type digit;
1005 bignum_digit_type* scan_source = (BIGNUM_START_PTR(source));
1006 bignum_digit_type carry = 0;
1007 bignum_digit_type* scan_target = (BIGNUM_START_PTR(target));
1008 bignum_digit_type* end_source = (scan_source + (BIGNUM_LENGTH(source)));
1009 bignum_digit_type* end_target = (scan_target + (BIGNUM_LENGTH(target)));
1010 int shift_right = (BIGNUM_DIGIT_LENGTH - shift_left);
1011 bignum_digit_type mask = (((cell)1 << shift_right) - 1);
1012 while (scan_source < end_source) {
1013 digit = (*scan_source++);
1014 (*scan_target++) = (((digit & mask) << shift_left) | carry);
1015 carry = (digit >> shift_right);
1017 if (scan_target < end_target)
1018 (*scan_target) = carry;
1020 BIGNUM_ASSERT(carry == 0);
1024 void factor_vm::bignum_destructive_unnormalization(bignum* bn,
1026 bignum_digit_type* start = (BIGNUM_START_PTR(bn));
1027 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(bn)));
1028 bignum_digit_type digit;
1029 bignum_digit_type carry = 0;
1030 int shift_left = (BIGNUM_DIGIT_LENGTH - shift_right);
1031 bignum_digit_type mask = (((fixnum)1 << shift_right) - 1);
1032 while (start < scan) {
1034 (*scan) = ((digit >> shift_right) | carry);
1035 carry = ((digit & mask) << shift_left);
1037 BIGNUM_ASSERT(carry == 0);
1041 /* This is a reduced version of the division algorithm, applied to the
1042 case of dividing two bignum digits by one bignum digit. It is
1043 assumed that the numerator, denominator are normalized. */
1045 #define BDD_STEP(qn, j) \
1049 uj_uj1 = (HD_CONS(uj, (u[j + 1]))); \
1050 guess = (uj_uj1 / v1); \
1051 comparand = (HD_CONS((uj_uj1 % v1), (u[j + 2]))); \
1053 guess = (BIGNUM_RADIX_ROOT - 1); \
1054 comparand = (HD_CONS(((u[j + 1]) + v1), (u[j + 2]))); \
1056 while ((guess * v2) > comparand) { \
1058 comparand += (v1 << BIGNUM_HALF_DIGIT_LENGTH); \
1059 if (comparand >= BIGNUM_RADIX) \
1062 qn = (bignum_digit_divide_subtract(v1, v2, guess, (&u[j]))); \
1065 bignum_digit_type factor_vm::bignum_digit_divide(
1066 bignum_digit_type uh, bignum_digit_type ul, bignum_digit_type v,
1067 bignum_digit_type* q) /* return value */
1069 bignum_digit_type guess;
1070 bignum_digit_type comparand;
1071 bignum_digit_type v1 = (HD_HIGH(v));
1072 bignum_digit_type v2 = (HD_LOW(v));
1073 bignum_digit_type uj;
1074 bignum_digit_type uj_uj1;
1075 bignum_digit_type q1;
1076 bignum_digit_type q2;
1077 bignum_digit_type u[4];
1082 } else if (ul == v) {
1087 (u[0]) = (HD_HIGH(uh));
1088 (u[1]) = (HD_LOW(uh));
1089 (u[2]) = (HD_HIGH(ul));
1090 (u[3]) = (HD_LOW(ul));
1095 (*q) = (HD_CONS(q1, q2));
1096 return (HD_CONS((u[2]), (u[3])));
1101 #define BDDS_MULSUB(vn, un, carry_in) \
1103 product = ((vn * guess) + carry_in); \
1104 diff = (un - (HD_LOW(product))); \
1106 un = (diff + BIGNUM_RADIX_ROOT); \
1107 carry = ((HD_HIGH(product)) + 1); \
1110 carry = (HD_HIGH(product)); \
1114 #define BDDS_ADD(vn, un, carry_in) \
1116 sum = (vn + un + carry_in); \
1117 if (sum < BIGNUM_RADIX_ROOT) { \
1121 un = (sum - BIGNUM_RADIX_ROOT); \
1126 bignum_digit_type factor_vm::bignum_digit_divide_subtract(
1127 bignum_digit_type v1, bignum_digit_type v2, bignum_digit_type guess,
1128 bignum_digit_type* u) {
1130 bignum_digit_type product;
1131 bignum_digit_type diff;
1132 bignum_digit_type carry;
1133 BDDS_MULSUB(v2, (u[2]), 0);
1134 BDDS_MULSUB(v1, (u[1]), carry);
1137 diff = ((u[0]) - carry);
1139 (u[0]) = (diff + BIGNUM_RADIX);
1146 bignum_digit_type sum;
1147 bignum_digit_type carry;
1148 BDDS_ADD(v2, (u[2]), 0);
1149 BDDS_ADD(v1, (u[1]), carry);
1159 /* Allocates memory */
1160 void factor_vm::bignum_divide_unsigned_small_denominator(
1161 bignum* numerator_, bignum_digit_type denominator, bignum** quotient,
1162 bignum** remainder, int q_negative_p, int r_negative_p) {
1163 data_root<bignum> numerator(numerator_, this);
1165 bignum* q_ = bignum_new_sign(numerator.untagged(), q_negative_p);
1166 data_root<bignum> q(q_, this);
1168 bignum_digit_type r = bignum_destructive_scale_down(q.untagged(), denominator);
1170 q = bignum_trim(q.untagged());
1172 if (remainder != ((bignum**)0))
1173 (*remainder) = bignum_digit_to_bignum(r, r_negative_p);
1175 (*quotient) = q.untagged();
1180 /* Given (denominator > 1), it is fairly easy to show that
1181 (quotient_high < BIGNUM_RADIX_ROOT), after which it is easy to see
1182 that all digits are < BIGNUM_RADIX. */
1184 bignum_digit_type factor_vm::bignum_destructive_scale_down(
1185 bignum* bn, bignum_digit_type denominator) {
1186 bignum_digit_type numerator;
1187 bignum_digit_type remainder = 0;
1188 bignum_digit_type two_digits;
1189 #define quotient_high remainder
1190 bignum_digit_type* start = (BIGNUM_START_PTR(bn));
1191 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(bn)));
1192 BIGNUM_ASSERT((denominator > 1) && (denominator < BIGNUM_RADIX_ROOT));
1193 while (start < scan) {
1194 two_digits = (*--scan);
1195 numerator = (HD_CONS(remainder, (HD_HIGH(two_digits))));
1196 quotient_high = (numerator / denominator);
1197 numerator = (HD_CONS((numerator % denominator), (HD_LOW(two_digits))));
1198 (*scan) = (HD_CONS(quotient_high, (numerator / denominator)));
1199 remainder = (numerator % denominator);
1202 #undef quotient_high
1205 /* Allocates memory */
1206 bignum* factor_vm::bignum_remainder_unsigned_small_denominator(
1207 bignum* n, bignum_digit_type d, int negative_p) {
1208 bignum_digit_type two_digits;
1209 bignum_digit_type* start = (BIGNUM_START_PTR(n));
1210 bignum_digit_type* scan = (start + (BIGNUM_LENGTH(n)));
1211 bignum_digit_type r = 0;
1212 BIGNUM_ASSERT((d > 1) && (d < BIGNUM_RADIX_ROOT));
1213 while (start < scan) {
1214 two_digits = (*--scan);
1215 r = ((HD_CONS(((HD_CONS(r, (HD_HIGH(two_digits)))) % d),
1216 (HD_LOW(two_digits)))) %
1219 return (bignum_digit_to_bignum(r, negative_p));
1222 /* Allocates memory */
1223 bignum* factor_vm::bignum_digit_to_bignum(bignum_digit_type digit,
1226 return (BIGNUM_ZERO());
1228 bignum* result = (allot_bignum(1, negative_p));
1229 (BIGNUM_REF(result, 0)) = digit;
1234 /* Allocates memory */
1235 bignum* factor_vm::allot_bignum(bignum_length_type length, int negative_p) {
1236 BIGNUM_ASSERT((length >= 0) || (length < BIGNUM_RADIX));
1237 bignum* result = allot_uninitialized_array<bignum>(length + 1);
1238 BIGNUM_SET_NEGATIVE_P(result, negative_p);
1242 /* Allocates memory */
1243 bignum* factor_vm::allot_bignum_zeroed(bignum_length_type length,
1245 bignum* result = allot_bignum(length, negative_p);
1246 bignum_digit_type* scan = (BIGNUM_START_PTR(result));
1247 bignum_digit_type* end = (scan + length);
1253 /* Allocates memory */
1254 bignum* factor_vm::bignum_shorten_length(bignum* bn,
1255 bignum_length_type length) {
1256 bignum_length_type current_length = (BIGNUM_LENGTH(bn));
1257 BIGNUM_ASSERT((length >= 0) || (length <= current_length));
1258 if (length < current_length) {
1259 bn = reallot_array(bn, length + 1);
1260 BIGNUM_SET_NEGATIVE_P(bn, (length != 0) && (BIGNUM_NEGATIVE_P(bn)));
1265 /* Allocates memory */
1266 bignum* factor_vm::bignum_trim(bignum* bn) {
1267 bignum_digit_type* start = (BIGNUM_START_PTR(bn));
1268 bignum_digit_type* end = (start + (BIGNUM_LENGTH(bn)));
1269 bignum_digit_type* scan = end;
1270 while ((start <= scan) && ((*--scan) == 0))
1274 bignum_length_type length = (scan - start);
1275 bn = reallot_array(bn, length + 1);
1276 BIGNUM_SET_NEGATIVE_P(bn, (length != 0) && (BIGNUM_NEGATIVE_P(bn)));
1283 /* Allocates memory */
1284 bignum* factor_vm::bignum_new_sign(bignum* x_, int negative_p) {
1285 data_root<bignum> x(x_, this);
1286 bignum* result = allot_bignum(BIGNUM_LENGTH(x), negative_p);
1287 bignum_destructive_copy(x.untagged(), result);
1291 /* Allocates memory */
1292 bignum* factor_vm::bignum_maybe_new_sign(bignum* x_, int negative_p) {
1293 if ((BIGNUM_NEGATIVE_P(x_)) ? negative_p : (!negative_p))
1296 return bignum_new_sign(x_, negative_p);
1300 void factor_vm::bignum_destructive_copy(bignum* source, bignum* target) {
1301 bignum_digit_type* scan_source = (BIGNUM_START_PTR(source));
1302 bignum_digit_type* end_source = (scan_source + (BIGNUM_LENGTH(source)));
1303 bignum_digit_type* scan_target = (BIGNUM_START_PTR(target));
1304 while (scan_source < end_source)
1305 (*scan_target++) = (*scan_source++);
1310 * Added bitwise operations (and oddp).
1313 /* Allocates memory */
1314 bignum* factor_vm::bignum_bitwise_not(bignum* x_) {
1317 bignum_length_type size = BIGNUM_LENGTH(x_);
1318 int is_negative = BIGNUM_NEGATIVE_P(x_);
1319 data_root<bignum> x(x_, this);
1320 data_root<bignum> y(allot_bignum(size, is_negative ? 0 : 1), this);
1322 bignum_digit_type* scan_x = BIGNUM_START_PTR(x);
1323 bignum_digit_type* end_x = scan_x + size;
1324 bignum_digit_type* scan_y = BIGNUM_START_PTR(y);
1327 while (scan_x < end_x) {
1329 *scan_y++ = BIGNUM_RADIX - 1;
1332 *scan_y++ = *scan_x++ - 1;
1338 while (scan_x < end_x) {
1339 if (*scan_x == (BIGNUM_RADIX - 1)) {
1343 *scan_y++ = *scan_x++ + 1;
1350 while (scan_x < end_x) {
1351 *scan_y++ = *scan_x++;
1355 bignum* ret = allot_bignum(size + 1, BIGNUM_NEGATIVE_P(y));
1356 bignum_destructive_copy(y.untagged(), ret);
1357 bignum_digit_type* ret_start = BIGNUM_START_PTR(ret);
1358 *(ret_start + size) = 1;
1361 return bignum_trim(y.untagged());
1365 /* Allocates memory */
1366 bignum* factor_vm::bignum_arithmetic_shift(bignum* arg1, fixnum n) {
1367 if (BIGNUM_NEGATIVE_P(arg1) && n < 0)
1368 return bignum_bitwise_not(
1369 bignum_magnitude_ash(bignum_bitwise_not(arg1), n));
1371 return bignum_magnitude_ash(arg1, n);
1378 /* Allocates memory */
1379 bignum* factor_vm::bignum_bitwise_and(bignum* arg1, bignum* arg2) {
1380 return ((BIGNUM_NEGATIVE_P(arg1)) ? (BIGNUM_NEGATIVE_P(arg2))
1381 ? bignum_negneg_bitwise_op(AND_OP, arg1, arg2)
1382 : bignum_posneg_bitwise_op(AND_OP, arg2, arg1)
1383 : (BIGNUM_NEGATIVE_P(arg2))
1384 ? bignum_posneg_bitwise_op(AND_OP, arg1, arg2)
1385 : bignum_pospos_bitwise_op(AND_OP, arg1, arg2));
1388 /* Allocates memory */
1389 bignum* factor_vm::bignum_bitwise_ior(bignum* arg1, bignum* arg2) {
1390 return ((BIGNUM_NEGATIVE_P(arg1)) ? (BIGNUM_NEGATIVE_P(arg2))
1391 ? bignum_negneg_bitwise_op(IOR_OP, arg1, arg2)
1392 : bignum_posneg_bitwise_op(IOR_OP, arg2, arg1)
1393 : (BIGNUM_NEGATIVE_P(arg2))
1394 ? bignum_posneg_bitwise_op(IOR_OP, arg1, arg2)
1395 : bignum_pospos_bitwise_op(IOR_OP, arg1, arg2));
1398 /* Allocates memory */
1399 bignum* factor_vm::bignum_bitwise_xor(bignum* arg1, bignum* arg2) {
1400 return ((BIGNUM_NEGATIVE_P(arg1)) ? (BIGNUM_NEGATIVE_P(arg2))
1401 ? bignum_negneg_bitwise_op(XOR_OP, arg1, arg2)
1402 : bignum_posneg_bitwise_op(XOR_OP, arg2, arg1)
1403 : (BIGNUM_NEGATIVE_P(arg2))
1404 ? bignum_posneg_bitwise_op(XOR_OP, arg1, arg2)
1405 : bignum_pospos_bitwise_op(XOR_OP, arg1, arg2));
1408 /* Allocates memory */
1409 /* ash for the magnitude */
1410 /* assume arg1 is a big number, n is a long */
1411 bignum* factor_vm::bignum_magnitude_ash(bignum* arg1_, fixnum n) {
1413 data_root<bignum> arg1(arg1_, this);
1415 bignum* result = NULL;
1416 bignum_digit_type* scan1;
1417 bignum_digit_type* scanr;
1418 bignum_digit_type* end;
1420 fixnum digit_offset, bit_offset;
1422 if (BIGNUM_ZERO_P(arg1))
1423 return arg1.untagged();
1426 digit_offset = n / BIGNUM_DIGIT_LENGTH;
1427 bit_offset = n % BIGNUM_DIGIT_LENGTH;
1429 result = allot_bignum_zeroed(BIGNUM_LENGTH(arg1) + digit_offset + 1,
1430 BIGNUM_NEGATIVE_P(arg1));
1432 scanr = BIGNUM_START_PTR(result) + digit_offset;
1433 scan1 = BIGNUM_START_PTR(arg1);
1434 end = scan1 + BIGNUM_LENGTH(arg1);
1436 while (scan1 < end) {
1437 *scanr = *scanr | (*scan1 & BIGNUM_DIGIT_MASK) << bit_offset;
1438 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1440 *scanr = *scan1++ >> (BIGNUM_DIGIT_LENGTH - bit_offset);
1441 *scanr = *scanr & BIGNUM_DIGIT_MASK;
1443 } else if (n < 0 && (-n >= (BIGNUM_LENGTH(arg1) * (bignum_length_type)
1444 BIGNUM_DIGIT_LENGTH))) {
1445 result = BIGNUM_ZERO();
1447 digit_offset = -n / BIGNUM_DIGIT_LENGTH;
1448 bit_offset = -n % BIGNUM_DIGIT_LENGTH;
1450 result = allot_bignum_zeroed(BIGNUM_LENGTH(arg1) - digit_offset,
1451 BIGNUM_NEGATIVE_P(arg1));
1453 scanr = BIGNUM_START_PTR(result);
1454 scan1 = BIGNUM_START_PTR(arg1) + digit_offset;
1455 end = scanr + BIGNUM_LENGTH(result) - 1;
1457 while (scanr < end) {
1458 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset;
1459 *scanr = (*scanr | *scan1 << (BIGNUM_DIGIT_LENGTH - bit_offset)) &
1463 *scanr = (*scan1++ & BIGNUM_DIGIT_MASK) >> bit_offset;
1464 } else if (n == 0) {
1465 result = arg1.untagged();
1468 return bignum_trim(result);
1471 /* Allocates memory */
1472 bignum* factor_vm::bignum_pospos_bitwise_op(int op, bignum* arg1_,
1474 data_root<bignum> arg1(arg1_, this);
1475 data_root<bignum> arg2(arg2_, this);
1477 bignum_length_type max_length;
1479 bignum_digit_type* scan1, *end1, digit1;
1480 bignum_digit_type* scan2, *end2, digit2;
1481 bignum_digit_type* scanr, *endr;
1484 (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2)) ? BIGNUM_LENGTH(arg1)
1485 : BIGNUM_LENGTH(arg2);
1487 bignum* result = allot_bignum(max_length, 0);
1489 scanr = BIGNUM_START_PTR(result);
1490 scan1 = BIGNUM_START_PTR(arg1);
1491 scan2 = BIGNUM_START_PTR(arg2);
1492 endr = scanr + max_length;
1493 end1 = scan1 + BIGNUM_LENGTH(arg1);
1494 end2 = scan2 + BIGNUM_LENGTH(arg2);
1496 while (scanr < endr) {
1497 digit1 = (scan1 < end1) ? *scan1++ : 0;
1498 digit2 = (scan2 < end2) ? *scan2++ : 0;
1500 (op == AND_OP) ? digit1 & digit2 : (op == IOR_OP) ? digit1 | digit2
1503 return bignum_trim(result);
1506 /* Allocates memory */
1507 bignum* factor_vm::bignum_posneg_bitwise_op(int op, bignum* arg1_,
1509 data_root<bignum> arg1(arg1_, this);
1510 data_root<bignum> arg2(arg2_, this);
1512 bignum_length_type max_length;
1514 bignum_digit_type* scan1, *end1, digit1;
1515 bignum_digit_type* scan2, *end2, digit2, carry2;
1516 bignum_digit_type* scanr, *endr;
1518 char neg_p = op == IOR_OP || op == XOR_OP;
1521 (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1) ? BIGNUM_LENGTH(arg1)
1522 : BIGNUM_LENGTH(arg2) + 1;
1524 bignum* result = allot_bignum(max_length, neg_p);
1526 scanr = BIGNUM_START_PTR(result);
1527 scan1 = BIGNUM_START_PTR(arg1);
1528 scan2 = BIGNUM_START_PTR(arg2);
1529 endr = scanr + max_length;
1530 end1 = scan1 + BIGNUM_LENGTH(arg1);
1531 end2 = scan2 + BIGNUM_LENGTH(arg2);
1535 while (scanr < endr) {
1536 digit1 = (scan1 < end1) ? *scan1++ : 0;
1537 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
1539 if (digit2 < BIGNUM_RADIX)
1542 digit2 = (digit2 - BIGNUM_RADIX);
1547 (op == AND_OP) ? digit1 & digit2 : (op == IOR_OP) ? digit1 | digit2
1552 bignum_negate_magnitude(result);
1554 return bignum_trim(result);
1557 /* Allocates memory */
1558 bignum* factor_vm::bignum_negneg_bitwise_op(int op, bignum* arg1_,
1560 data_root<bignum> arg1(arg1_, this);
1561 data_root<bignum> arg2(arg2_, this);
1563 bignum_length_type max_length;
1565 bignum_digit_type* scan1, *end1, digit1, carry1;
1566 bignum_digit_type* scan2, *end2, digit2, carry2;
1567 bignum_digit_type* scanr, *endr;
1569 char neg_p = op == AND_OP || op == IOR_OP;
1572 (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2)) ? BIGNUM_LENGTH(arg1) + 1
1573 : BIGNUM_LENGTH(arg2) + 1;
1575 bignum* result = allot_bignum(max_length, neg_p);
1577 scanr = BIGNUM_START_PTR(result);
1578 scan1 = BIGNUM_START_PTR(arg1);
1579 scan2 = BIGNUM_START_PTR(arg2);
1580 endr = scanr + max_length;
1581 end1 = scan1 + BIGNUM_LENGTH(arg1);
1582 end2 = scan2 + BIGNUM_LENGTH(arg2);
1587 while (scanr < endr) {
1588 digit1 = (~((scan1 < end1) ? *scan1++ : 0) & BIGNUM_DIGIT_MASK) + carry1;
1589 digit2 = (~((scan2 < end2) ? *scan2++ : 0) & BIGNUM_DIGIT_MASK) + carry2;
1591 if (digit1 < BIGNUM_RADIX)
1594 digit1 = (digit1 - BIGNUM_RADIX);
1598 if (digit2 < BIGNUM_RADIX)
1601 digit2 = (digit2 - BIGNUM_RADIX);
1606 (op == AND_OP) ? digit1 & digit2 : (op == IOR_OP) ? digit1 | digit2
1611 bignum_negate_magnitude(result);
1613 return bignum_trim(result);
1616 void factor_vm::bignum_negate_magnitude(bignum* arg) {
1617 bignum_digit_type* scan;
1618 bignum_digit_type* end;
1619 bignum_digit_type digit;
1620 bignum_digit_type carry;
1622 scan = BIGNUM_START_PTR(arg);
1623 end = scan + BIGNUM_LENGTH(arg);
1627 while (scan < end) {
1628 digit = (~ * scan & BIGNUM_DIGIT_MASK) + carry;
1630 if (digit < BIGNUM_RADIX)
1633 digit = (digit - BIGNUM_RADIX);
1641 /* Allocates memory */
1642 bignum* factor_vm::bignum_integer_length(bignum* x_) {
1643 data_root<bignum> x(x_, this);
1644 bignum_length_type index = ((BIGNUM_LENGTH(x)) - 1);
1645 bignum_digit_type digit = (BIGNUM_REF(x, index));
1646 bignum_digit_type carry = 0;
1654 if (index < BIGNUM_RADIX_ROOT) {
1655 result = allot_bignum(1, 0);
1656 (BIGNUM_REF(result, 0)) = (index * BIGNUM_DIGIT_LENGTH) + carry;
1658 result = allot_bignum(2, 0);
1659 (BIGNUM_REF(result, 0)) = index;
1660 (BIGNUM_REF(result, 1)) = 0;
1661 bignum_destructive_scale_up(result, BIGNUM_DIGIT_LENGTH);
1662 bignum_destructive_add(result, carry);
1664 return (bignum_trim(result));
1667 /* Allocates memory */
1668 int factor_vm::bignum_logbitp(int shift, bignum* arg) {
1669 return ((BIGNUM_NEGATIVE_P(arg))
1670 ? !bignum_unsigned_logbitp(shift, bignum_bitwise_not(arg))
1671 : bignum_unsigned_logbitp(shift, arg));
1674 int factor_vm::bignum_unsigned_logbitp(int shift, bignum* bn) {
1675 bignum_length_type len = (BIGNUM_LENGTH(bn));
1676 int index = shift / BIGNUM_DIGIT_LENGTH;
1679 bignum_digit_type digit = (BIGNUM_REF(bn, index));
1680 int p = shift % BIGNUM_DIGIT_LENGTH;
1681 bignum_digit_type mask = ((fixnum)1) << p;
1682 return (digit & mask) ? 1 : 0;
1686 /* Allocates memory. */
1687 bignum* factor_vm::bignum_gcd(bignum* a_, bignum* b_) {
1689 data_root<bignum> a(a_, this);
1690 data_root<bignum> b(b_, this);
1692 /* Copies of a and b with that are both positive. */
1693 data_root<bignum> ac(bignum_maybe_new_sign(a.untagged(), 0), this);
1694 data_root<bignum> bc(bignum_maybe_new_sign(b.untagged(), 0), this);
1696 if (bignum_compare(ac.untagged(), bc.untagged()) == bignum_comparison_less) {
1700 while (BIGNUM_LENGTH(bc) != 0) {
1701 data_root<bignum> d(bignum_remainder(ac.untagged(), bc.untagged()), this);
1702 if (d.untagged() == BIGNUM_OUT_OF_BAND) {
1703 return d.untagged();
1708 return ac.untagged();
1711 /* Allocates memory */
1712 bignum* factor_vm::bignum_gcd(bignum* a_, bignum* b_) {
1713 data_root<bignum> a(a_, this);
1714 data_root<bignum> b(b_, this);
1715 bignum_twodigit_type x, y, q, s, t, A, B, C, D;
1717 bignum_length_type size_a, size_b, size_c;
1718 bignum_digit_type* scan_a, *scan_b, *scan_c, *scan_d;
1719 bignum_digit_type* a_end, *b_end, *c_end;
1721 /* clone the bignums so we can modify them in-place */
1722 size_a = BIGNUM_LENGTH(a);
1723 data_root<bignum> c(allot_bignum(size_a, 0), this);
1724 // c = allot_bignum(size_a, 0);
1725 scan_a = BIGNUM_START_PTR(a);
1726 a_end = scan_a + size_a;
1727 scan_c = BIGNUM_START_PTR(c);
1728 while (scan_a < a_end)
1729 (*scan_c++) = (*scan_a++);
1731 size_b = BIGNUM_LENGTH(b);
1732 data_root<bignum> d(allot_bignum(size_b, 0), this);
1733 scan_b = BIGNUM_START_PTR(b);
1734 b_end = scan_b + size_b;
1735 scan_d = BIGNUM_START_PTR(d);
1736 while (scan_b < b_end)
1737 (*scan_d++) = (*scan_b++);
1740 /* Initial reduction: make sure that 0 <= b <= a. */
1741 if (bignum_compare(a.untagged(), b.untagged()) == bignum_comparison_less) {
1743 std::swap(size_a, size_b);
1746 while (size_a > 1) {
1747 nbits = log2(BIGNUM_REF(a, size_a - 1));
1748 x = ((BIGNUM_REF(a, size_a - 1) << (BIGNUM_DIGIT_LENGTH - nbits)) |
1749 (BIGNUM_REF(a, size_a - 2) >> nbits));
1750 y = ((size_b >= size_a - 1 ? BIGNUM_REF(b, size_a - 2) >> nbits : 0) |
1752 ? BIGNUM_REF(b, size_a - 1) << (BIGNUM_DIGIT_LENGTH - nbits)
1755 /* inner loop of Lehmer's algorithm; */
1764 q = (x + (A - 1)) / (y - C);
1784 /* no progress; do a Euclidean step */
1786 return bignum_trim(a.untagged());
1788 data_root<bignum> e(bignum_trim(a.untagged()), this);
1789 data_root<bignum> f(bignum_trim(b.untagged()), this);
1790 c = bignum_remainder(e.untagged(), f.untagged());
1791 if (c.untagged() == BIGNUM_OUT_OF_BAND) {
1792 return c.untagged();
1796 scan_a = BIGNUM_START_PTR(a);
1797 scan_b = BIGNUM_START_PTR(b);
1798 a_end = scan_a + size_a;
1799 b_end = scan_b + size_b;
1800 while (scan_b < b_end)
1801 *(scan_a++) = *(scan_b++);
1802 while (scan_a < a_end)
1807 scan_b = BIGNUM_START_PTR(b);
1808 scan_c = BIGNUM_START_PTR(c);
1809 size_c = BIGNUM_LENGTH(c);
1810 c_end = scan_c + size_c;
1811 while (scan_c < c_end)
1812 *(scan_b++) = *(scan_c++);
1813 while (scan_b < b_end)
1821 a, b = A*b - B*a, D*a - C*b if k is odd
1822 a, b = A*a - B*b, D*b - C*a if k is even
1824 scan_a = BIGNUM_START_PTR(a);
1825 scan_b = BIGNUM_START_PTR(b);
1828 a_end = scan_a + size_a;
1829 b_end = scan_b + size_b;
1833 while (scan_b < b_end) {
1834 s += (A * *scan_b) - (B * *scan_a);
1835 t += (D * *scan_a++) - (C * *scan_b++);
1836 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1837 *scan_d++ = (bignum_digit_type)(t & BIGNUM_DIGIT_MASK);
1838 s >>= BIGNUM_DIGIT_LENGTH;
1839 t >>= BIGNUM_DIGIT_LENGTH;
1841 while (scan_a < a_end) {
1843 t += (D * *scan_a++);
1844 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1845 //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1846 s >>= BIGNUM_DIGIT_LENGTH;
1847 t >>= BIGNUM_DIGIT_LENGTH;
1850 while (scan_b < b_end) {
1851 s += (A * *scan_a) - (B * *scan_b);
1852 t += (D * *scan_b++) - (C * *scan_a++);
1853 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1854 *scan_d++ = (bignum_digit_type)(t & BIGNUM_DIGIT_MASK);
1855 s >>= BIGNUM_DIGIT_LENGTH;
1856 t >>= BIGNUM_DIGIT_LENGTH;
1858 while (scan_a < a_end) {
1860 t -= (C * *scan_a++);
1861 *scan_c++ = (bignum_digit_type)(s & BIGNUM_DIGIT_MASK);
1862 //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK);
1863 s >>= BIGNUM_DIGIT_LENGTH;
1864 t >>= BIGNUM_DIGIT_LENGTH;
1867 BIGNUM_ASSERT(s == 0);
1868 BIGNUM_ASSERT(t == 0);
1870 // update size_a and size_b to remove any zeros at end
1871 while (size_a > 0 && *(--scan_a) == 0)
1873 while (size_b > 0 && *(--scan_b) == 0)
1876 BIGNUM_ASSERT(size_a >= size_b);
1879 /* a fits into a fixnum, so b must too */
1880 fixnum xx = bignum_to_fixnum(a.untagged());
1881 fixnum yy = bignum_to_fixnum(b.untagged());
1884 /* usual Euclidean algorithm for longs */
1891 return fixnum_to_bignum(xx);