diff --git a/vm/bignum.cpp b/vm/bignum.cpp index cb51af5463..e2c2efc41e 100755 --- a/vm/bignum.cpp +++ b/vm/bignum.cpp @@ -1720,225 +1720,225 @@ int factor_vm::bignum_unsigned_logbitp(int shift, bignum * bignum) /* Allocates memory */ bignum * factor_vm::bignum_gcd(bignum * a, bignum * b) { - GC_BIGNUM(a); - GC_BIGNUM(b); - bignum * d; - bignum_length_type size_a, size_b; - bignum_digit_type * scan_a, * scan_b, * scan_d, * a_end, * b_end; + GC_BIGNUM(a); + GC_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)) { - size_a = BIGNUM_LENGTH (a); - d = allot_bignum (size_a, 0); - scan_d = BIGNUM_START_PTR (d); - scan_a = BIGNUM_START_PTR (a); - a_end = scan_a + size_a; - while (scan_a < a_end) - (*scan_d++) = (*scan_a++); - a = d; - } + if (BIGNUM_NEGATIVE_P (a)) { + size_a = BIGNUM_LENGTH (a); + d = allot_bignum (size_a, 0); + scan_d = BIGNUM_START_PTR (d); + scan_a = BIGNUM_START_PTR (a); + a_end = scan_a + size_a; + while (scan_a < a_end) + (*scan_d++) = (*scan_a++); + a = d; + } - if (BIGNUM_NEGATIVE_P (b)) { - size_b = BIGNUM_LENGTH (b); - d = allot_bignum (size_b, 0); - scan_d = BIGNUM_START_PTR (d); - scan_b = BIGNUM_START_PTR (b); - b_end = scan_b + size_b; - while (scan_b < b_end) - (*scan_d++) = (*scan_b++); - b = d; - } + if (BIGNUM_NEGATIVE_P (b)) { + size_b = BIGNUM_LENGTH (b); + d = allot_bignum (size_b, 0); + scan_d = BIGNUM_START_PTR (d); + scan_b = BIGNUM_START_PTR (b); + b_end = scan_b + size_b; + while (scan_b < b_end) + (*scan_d++) = (*scan_b++); + b = d; + } - if (bignum_compare(a, b) == bignum_comparison_less) { - std::swap(a, b); - } + if (bignum_compare(a, b) == bignum_comparison_less) { + std::swap(a, b); + } - while (BIGNUM_LENGTH (b) != 0) { - d = bignum_remainder (a, b); - GC_BIGNUM(d); - if (d == BIGNUM_OUT_OF_BAND) { - return d; - } - a = b; - b = d; - } + while (BIGNUM_LENGTH (b) != 0) { + d = bignum_remainder (a, b); + GC_BIGNUM(d); + if (d == BIGNUM_OUT_OF_BAND) { + return d; + } + a = b; + b = d; + } - return a; + return a; } #else /* Allocates memory */ bignum * factor_vm::bignum_gcd(bignum * a, bignum * b) { - GC_BIGNUM(a); - GC_BIGNUM(b); - bignum *c, *d, *e, *f; - bignum_twodigit_type x, y, q, s, t, A, B, C, D; - int nbits, k; - bignum_length_type size_a, size_b, size_c; - bignum_digit_type *scan_a, *scan_b, *scan_c, *scan_d; - bignum_digit_type *a_end, *b_end, *c_end; + GC_BIGNUM(a); + GC_BIGNUM(b); + bignum *c, *d, *e, *f; + bignum_twodigit_type x, y, q, s, t, A, B, C, D; + int nbits, k; + bignum_length_type size_a, size_b, size_c; + bignum_digit_type *scan_a, *scan_b, *scan_c, *scan_d; + bignum_digit_type *a_end, *b_end, *c_end; - /* clone the bignums so we can modify them in-place */ - size_a = BIGNUM_LENGTH (a); - c = allot_bignum (size_a, 0); - scan_a = BIGNUM_START_PTR (a); - a_end = scan_a + size_a; - GC_BIGNUM(c); - scan_c = BIGNUM_START_PTR (c); - while (scan_a < a_end) - (*scan_c++) = (*scan_a++); - a = c; - size_b = BIGNUM_LENGTH (b); - d = allot_bignum (size_b, 0); - scan_b = BIGNUM_START_PTR (b); - b_end = scan_b + size_b; - GC_BIGNUM(d); - scan_d = BIGNUM_START_PTR (d); - while (scan_b < b_end) - (*scan_d++) = (*scan_b++); - b = d; + /* clone the bignums so we can modify them in-place */ + size_a = BIGNUM_LENGTH (a); + c = allot_bignum (size_a, 0); + scan_a = BIGNUM_START_PTR (a); + a_end = scan_a + size_a; + GC_BIGNUM(c); + scan_c = BIGNUM_START_PTR (c); + while (scan_a < a_end) + (*scan_c++) = (*scan_a++); + a = c; + size_b = BIGNUM_LENGTH (b); + d = allot_bignum (size_b, 0); + scan_b = BIGNUM_START_PTR (b); + b_end = scan_b + size_b; + GC_BIGNUM(d); + scan_d = BIGNUM_START_PTR (d); + while (scan_b < b_end) + (*scan_d++) = (*scan_b++); + b = d; - /* Initial reduction: make sure that 0 <= b <= a. */ - if (bignum_compare(a, b) == bignum_comparison_less) { - std::swap(a, b); - std::swap(size_a, size_b); - } + /* Initial reduction: make sure that 0 <= b <= a. */ + if (bignum_compare(a, b) == bignum_comparison_less) { + std::swap(a, b); + std::swap(size_a, size_b); + } - while (size_a > 1) { - nbits = log2 (BIGNUM_REF (a, size_a-1)); - x = ((BIGNUM_REF (a, size_a-1) << (BIGNUM_DIGIT_LENGTH - nbits)) | - (BIGNUM_REF (a, size_a-2) >> nbits)); - y = ((size_b >= size_a - 1 ? BIGNUM_REF (b, size_a-2) >> nbits : 0) | - (size_b >= size_a ? BIGNUM_REF (b, size_a-1) << (BIGNUM_DIGIT_LENGTH - nbits) : 0)); + while (size_a > 1) { + nbits = log2 (BIGNUM_REF (a, size_a-1)); + x = ((BIGNUM_REF (a, size_a-1) << (BIGNUM_DIGIT_LENGTH - nbits)) | + (BIGNUM_REF (a, size_a-2) >> nbits)); + y = ((size_b >= size_a - 1 ? BIGNUM_REF (b, size_a-2) >> nbits : 0) | + (size_b >= size_a ? BIGNUM_REF (b, size_a-1) << (BIGNUM_DIGIT_LENGTH - nbits) : 0)); /* inner loop of Lehmer's algorithm; */ - A = 1; B = 0; C = 0; D = 1; - for (k=0 ;; k++) { - if (y - C == 0) - break; + A = 1; B = 0; C = 0; D = 1; + for (k=0 ;; k++) { + if (y - C == 0) + break; - q = (x + (A - 1)) / (y - C); + q = (x + (A - 1)) / (y - C); - s = B + (q * D); - t = x - (q * y); + s = B + (q * D); + t = x - (q * y); - if (s > t) - break; + if (s > t) + break; - x = y; - y = t; + x = y; + 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; + } - if (k == 0) { - /* no progress; do a Euclidean step */ - if (size_b == 0) { - return bignum_trim (a); - } - e = bignum_trim (a); - GC_BIGNUM(e); - f = bignum_trim (b); - GC_BIGNUM(f); - c = bignum_remainder (e, f); - GC_BIGNUM (c); - if (c == BIGNUM_OUT_OF_BAND) { - return c; - } + if (k == 0) { + /* no progress; do a Euclidean step */ + if (size_b == 0) { + return bignum_trim (a); + } + e = bignum_trim (a); + GC_BIGNUM(e); + f = bignum_trim (b); + GC_BIGNUM(f); + c = bignum_remainder (e, f); + GC_BIGNUM (c); + if (c == BIGNUM_OUT_OF_BAND) { + return c; + } - // copy 'b' to 'a' - scan_a = BIGNUM_START_PTR (a); - scan_b = BIGNUM_START_PTR (b); - a_end = scan_a + size_a; - b_end = scan_b + size_b; - while (scan_b < b_end) *(scan_a++) = *(scan_b++); - while (scan_a < a_end) *(scan_a++) = 0; - size_a = size_b; + // copy 'b' to 'a' + scan_a = BIGNUM_START_PTR (a); + scan_b = BIGNUM_START_PTR (b); + a_end = scan_a + size_a; + b_end = scan_b + size_b; + while (scan_b < b_end) *(scan_a++) = *(scan_b++); + while (scan_a < a_end) *(scan_a++) = 0; + size_a = size_b; - // copy 'c' to 'b' - scan_b = BIGNUM_START_PTR (b); - scan_c = BIGNUM_START_PTR (c); - size_c = BIGNUM_LENGTH (c); - c_end = scan_c + size_c; - while (scan_c < c_end) *(scan_b++) = *(scan_c++); - while (scan_b < b_end) *(scan_b++) = 0; - size_b = size_c; + // copy 'c' to 'b' + scan_b = BIGNUM_START_PTR (b); + scan_c = BIGNUM_START_PTR (c); + size_c = BIGNUM_LENGTH (c); + c_end = scan_c + size_c; + while (scan_c < c_end) *(scan_b++) = *(scan_c++); + while (scan_b < b_end) *(scan_b++) = 0; + size_b = size_c; - continue; - } + continue; + } - /* - a, b = A*b - B*a, D*a - C*b if k is odd - a, b = A*a - B*b, D*b - C*a if k is even - */ - scan_a = BIGNUM_START_PTR (a); - scan_b = BIGNUM_START_PTR (b); - scan_c = scan_a; - scan_d = scan_b; - a_end = scan_a + size_a; - b_end = scan_b + size_b; - s = 0; - t = 0; - if (k & 1) { - while (scan_b < b_end) { - s += (A * *scan_b) - (B * *scan_a); - t += (D * *scan_a++) - (C * *scan_b++); - *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); - *scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); - s >>= BIGNUM_DIGIT_LENGTH; - t >>= BIGNUM_DIGIT_LENGTH; - } - while (scan_a < a_end) { - s -= (B * *scan_a); - t += (D * *scan_a++); - *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); - //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); - s >>= BIGNUM_DIGIT_LENGTH; - t >>= BIGNUM_DIGIT_LENGTH; - } - } - else { - while (scan_b < b_end) { - s += (A * *scan_a) - (B * *scan_b); - t += (D * *scan_b++) - (C * *scan_a++); - *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); - *scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); - s >>= BIGNUM_DIGIT_LENGTH; - t >>= BIGNUM_DIGIT_LENGTH; - } - while (scan_a < a_end) { - s += (A * *scan_a); - t -= (C * *scan_a++); - *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); - //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); - s >>= BIGNUM_DIGIT_LENGTH; - t >>= BIGNUM_DIGIT_LENGTH; - } - } - BIGNUM_ASSERT (s == 0); - BIGNUM_ASSERT (t == 0); + /* + a, b = A*b - B*a, D*a - C*b if k is odd + a, b = A*a - B*b, D*b - C*a if k is even + */ + scan_a = BIGNUM_START_PTR (a); + scan_b = BIGNUM_START_PTR (b); + scan_c = scan_a; + scan_d = scan_b; + a_end = scan_a + size_a; + b_end = scan_b + size_b; + s = 0; + t = 0; + if (k & 1) { + while (scan_b < b_end) { + s += (A * *scan_b) - (B * *scan_a); + t += (D * *scan_a++) - (C * *scan_b++); + *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); + *scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); + s >>= BIGNUM_DIGIT_LENGTH; + t >>= BIGNUM_DIGIT_LENGTH; + } + while (scan_a < a_end) { + s -= (B * *scan_a); + t += (D * *scan_a++); + *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); + //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); + s >>= BIGNUM_DIGIT_LENGTH; + t >>= BIGNUM_DIGIT_LENGTH; + } + } + else { + while (scan_b < b_end) { + s += (A * *scan_a) - (B * *scan_b); + t += (D * *scan_b++) - (C * *scan_a++); + *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); + *scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); + s >>= BIGNUM_DIGIT_LENGTH; + t >>= BIGNUM_DIGIT_LENGTH; + } + while (scan_a < a_end) { + s += (A * *scan_a); + t -= (C * *scan_a++); + *scan_c++ = (bignum_digit_type) (s & BIGNUM_DIGIT_MASK); + //*scan_d++ = (bignum_digit_type) (t & BIGNUM_DIGIT_MASK); + s >>= BIGNUM_DIGIT_LENGTH; + t >>= BIGNUM_DIGIT_LENGTH; + } + } + BIGNUM_ASSERT (s == 0); + BIGNUM_ASSERT (t == 0); - // update size_a and size_b to remove any zeros at end - while (size_a > 0 && *(--scan_a) == 0) size_a--; - while (size_b > 0 && *(--scan_b) == 0) size_b--; + // update size_a and size_b to remove any zeros at end + while (size_a > 0 && *(--scan_a) == 0) size_a--; + while (size_b > 0 && *(--scan_b) == 0) size_b--; - BIGNUM_ASSERT (size_a >= size_b); - } + BIGNUM_ASSERT (size_a >= size_b); + } - /* a fits into a fixnum, so b must too */ - fixnum xx = bignum_to_fixnum (a); - fixnum yy = bignum_to_fixnum (b); - fixnum tt; + /* a fits into a fixnum, so b must too */ + fixnum xx = bignum_to_fixnum (a); + fixnum yy = bignum_to_fixnum (b); + fixnum tt; - /* usual Euclidean algorithm for longs */ - while (yy != 0) { - tt = yy; - yy = xx % yy; - xx = tt; - } + /* usual Euclidean algorithm for longs */ + while (yy != 0) { + tt = yy; + yy = xx % yy; + xx = tt; + } - return fixnum_to_bignum (xx); + return fixnum_to_bignum (xx); } #endif