vm: use euclid gcd on win64 until we find a better way to do the 128-bit math.

db4
John Benediktsson 2012-04-06 11:42:59 -07:00
parent eb556bfb06
commit 5794ab46a0
2 changed files with 57 additions and 3 deletions

View File

@ -1709,8 +1709,55 @@ int factor_vm::bignum_unsigned_logbitp(int shift, bignum * bignum)
return (digit & mask) ? 1 : 0; return (digit & mask) ? 1 : 0;
} }
#
#ifdef _WIN64
/* Allocates memory */
bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
{
bignum * d;
bignum_length_type size_a, size_b;
bignum_digit_type * scan_a, * scan_b, * scan_d, * a_end, * b_end;
if (BIGNUM_NEGATIVE_P (a)) {
scan_a = BIGNUM_START_PTR (a);
size_a = BIGNUM_LENGTH (a);
a_end = scan_a + size_a;
d = allot_bignum (size_a, 0);
scan_d = BIGNUM_START_PTR (d);
while (scan_a < a_end)
(*scan_d++) = (*scan_a++);
a = d;
}
if (BIGNUM_NEGATIVE_P (b)) {
scan_b = BIGNUM_START_PTR (b);
size_b = BIGNUM_LENGTH (b);
b_end = scan_b + size_b;
d = allot_bignum (size_b, 0);
scan_d = BIGNUM_START_PTR (d);
while (scan_b < b_end)
(*scan_d++) = (*scan_b++);
b = d;
}
if (bignum_compare(a, b) == bignum_comparison_less) {
d = a;
a = b;
b = d;
}
while (BIGNUM_LENGTH (b) != 0) {
d = bignum_remainder (a, b);
if (d == BIGNUM_OUT_OF_BAND) {
return d;
}
a = b;
b = d;
}
return a;
}
#else
/* Allocates memory */ /* Allocates memory */
bignum * factor_vm::bignum_gcd(bignum * a, bignum * b) bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
{ {
@ -1739,8 +1786,6 @@ bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
b = d; b = d;
/* Initial reduction: make sure that 0 <= b <= a. */ /* Initial reduction: make sure that 0 <= b <= a. */
BIGNUM_SET_NEGATIVE_P (a, 0);
BIGNUM_SET_NEGATIVE_P (b, 0);
if (bignum_compare(a, b) == bignum_comparison_less) { if (bignum_compare(a, b) == bignum_comparison_less) {
d = a; d = a;
a = b; a = b;
@ -1760,14 +1805,20 @@ bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
for (k=0 ;; k++) { for (k=0 ;; k++) {
if (y - C == 0) if (y - C == 0)
break; break;
q = (x + (A - 1)) / (y - C); q = (x + (A - 1)) / (y - C);
s = B + (q * D); s = B + (q * D);
t = x - (q * y); t = x - (q * y);
if (s > t) if (s > t)
break; break;
x = y; x = y;
y = t; y = t;
t = A + (q * C); t = A + (q * C);
A = D; B = C; C = s; D = t; A = D; B = C; C = s; D = t;
} }
@ -1854,5 +1905,6 @@ bignum * factor_vm::bignum_gcd(bignum * a, bignum * b)
return fixnum_to_bignum (xx); return fixnum_to_bignum (xx);
} }
#endif
} }

View File

@ -48,11 +48,13 @@ namespace factor
typedef fixnum bignum_digit_type; typedef fixnum bignum_digit_type;
typedef fixnum bignum_length_type; typedef fixnum bignum_length_type;
#ifndef _WIN64
#ifdef FACTOR_64 #ifdef FACTOR_64
typedef __int128_t bignum_twodigit_type; typedef __int128_t bignum_twodigit_type;
#else #else
typedef s64 bignum_twodigit_type; typedef s64 bignum_twodigit_type;
#endif #endif
#endif
/* BIGNUM_TO_POINTER casts a bignum object to a digit array pointer. */ /* BIGNUM_TO_POINTER casts a bignum object to a digit array pointer. */
#define BIGNUM_TO_POINTER(bignum) ((bignum_digit_type *)(bignum + 1)) #define BIGNUM_TO_POINTER(bignum) ((bignum_digit_type *)(bignum + 1))