}
enum bignum_comparison factor_vm::bignum_compare(bignum* x, bignum* y) {
- return ((BIGNUM_ZERO_P(x)) ? ((BIGNUM_ZERO_P(y)) ? bignum_comparison_equal
+ return ((BIGNUM_ZERO_P(x)) ? ((BIGNUM_ZERO_P(y)) ? BIGNUM_COMPARISON_EQUAL
: (BIGNUM_NEGATIVE_P(y))
- ? bignum_comparison_greater
- : bignum_comparison_less)
+ ? BIGNUM_COMPARISON_GREATER
+ : BIGNUM_COMPARISON_LESS)
: (BIGNUM_ZERO_P(y))
- ? ((BIGNUM_NEGATIVE_P(x)) ? bignum_comparison_less
- : bignum_comparison_greater)
+ ? ((BIGNUM_NEGATIVE_P(x)) ? BIGNUM_COMPARISON_LESS
+ : BIGNUM_COMPARISON_GREATER)
: (BIGNUM_NEGATIVE_P(x))
? ((BIGNUM_NEGATIVE_P(y)) ? (bignum_compare_unsigned(y, x))
- : (bignum_comparison_less))
- : ((BIGNUM_NEGATIVE_P(y)) ? (bignum_comparison_greater)
+ : (BIGNUM_COMPARISON_LESS))
+ : ((BIGNUM_NEGATIVE_P(y)) ? (BIGNUM_COMPARISON_GREATER)
: (bignum_compare_unsigned(x, y))));
}
int q_negative_p =
((BIGNUM_NEGATIVE_P(denominator)) ? (!r_negative_p) : r_negative_p);
switch (bignum_compare_unsigned(numerator, denominator)) {
- case bignum_comparison_equal: {
+ case BIGNUM_COMPARISON_EQUAL: {
(*quotient) = (BIGNUM_ONE(q_negative_p));
(*remainder) = (BIGNUM_ZERO());
break;
}
- case bignum_comparison_less: {
+ case BIGNUM_COMPARISON_LESS: {
(*quotient) = (BIGNUM_ZERO());
(*remainder) = numerator;
break;
}
- case bignum_comparison_greater: {
+ case BIGNUM_COMPARISON_GREATER: {
if ((BIGNUM_LENGTH(denominator)) == 1) {
bignum_digit_type digit = (BIGNUM_REF(denominator, 0));
if (digit == 1) {
((BIGNUM_NEGATIVE_P(denominator)) ? (!(BIGNUM_NEGATIVE_P(numerator)))
: (BIGNUM_NEGATIVE_P(numerator)));
switch (bignum_compare_unsigned(numerator, denominator)) {
- case bignum_comparison_equal:
+ case BIGNUM_COMPARISON_EQUAL:
return (BIGNUM_ONE(q_negative_p));
- case bignum_comparison_less:
+ case BIGNUM_COMPARISON_LESS:
return (BIGNUM_ZERO());
- case bignum_comparison_greater:
+ case BIGNUM_COMPARISON_GREATER:
default: // to appease gcc -Wall
{
bignum* quotient;
if (BIGNUM_ZERO_P(numerator))
return numerator;
switch (bignum_compare_unsigned(numerator, denominator)) {
- case bignum_comparison_equal:
+ case BIGNUM_COMPARISON_EQUAL:
return (BIGNUM_ZERO());
- case bignum_comparison_less:
+ case BIGNUM_COMPARISON_LESS:
return numerator;
- case bignum_comparison_greater:
+ case BIGNUM_COMPARISON_GREATER:
default: // to appease gcc -Wall
{
bignum* remainder;
// cell_to_bignum, fixnum_to_bignum, long_long_to_bignum, ulong_long_to_bignum
// Allocates memory
-#define FOO_TO_BIGNUM(name, type, stype, utype) \
+#define FOO_TO_BIGNUM_SIGNED(name, type, utype) \
bignum* factor_vm::name##_to_bignum(type n) { \
int negative_p; \
/* Special cases win when these small constants are cached. */ \
return (BIGNUM_ZERO()); \
if (n == 1) \
return (BIGNUM_ONE(0)); \
- if (n < (type) 0 && n == (type) - 1) \
+ if (n < (type) 0 && n == (type) -1) \
return (BIGNUM_ONE(1)); \
{ \
utype accumulator = \
- ((negative_p = (n < (type) 0)) ? ((type)(-(stype) n)) : n); \
+ ((negative_p = n < (type) 0) ? -n : n); \
if (accumulator < BIGNUM_RADIX) \
{ \
bignum* result = allot_bignum(1, negative_p); \
} \
}
-FOO_TO_BIGNUM(cell, cell, fixnum, cell)
-FOO_TO_BIGNUM(fixnum, fixnum, fixnum, cell)
-FOO_TO_BIGNUM(long_long, int64_t, int64_t, uint64_t)
-FOO_TO_BIGNUM(ulong_long, uint64_t, int64_t, uint64_t)
+// Allocates memory
+#define FOO_TO_BIGNUM_UNSIGNED(name, type, utype) \
+ bignum* factor_vm::name##_to_bignum(type n) { \
+ /* Special cases win when these small constants are cached. */ \
+ if (n == 0) \
+ return (BIGNUM_ZERO()); \
+ if (n == 1) \
+ return (BIGNUM_ONE(0)); \
+ { \
+ utype accumulator = n; \
+ if (accumulator < BIGNUM_RADIX) \
+ { \
+ bignum* result = allot_bignum(1, false); \
+ bignum_digit_type* scan = (BIGNUM_START_PTR(result)); \
+ *scan = (accumulator & BIGNUM_DIGIT_MASK); \
+ return (result); \
+ } else { \
+ bignum_digit_type result_digits[BIGNUM_DIGITS_FOR(type)]; \
+ bignum_digit_type* end_digits = result_digits; \
+ do { \
+ (*end_digits++) = (accumulator & BIGNUM_DIGIT_MASK); \
+ accumulator >>= BIGNUM_DIGIT_LENGTH; \
+ } while (accumulator != 0); \
+ bignum* result = \
+ (allot_bignum((end_digits - result_digits), false)); \
+ bignum_digit_type* scan_digits = result_digits; \
+ bignum_digit_type* scan_result = (BIGNUM_START_PTR(result)); \
+ while (scan_digits < end_digits) \
+ (*scan_result++) = (*scan_digits++); \
+ return (result); \
+ } \
+ } \
+ }
+
+FOO_TO_BIGNUM_SIGNED(fixnum, fixnum, cell)
+FOO_TO_BIGNUM_UNSIGNED(cell, cell, cell)
+FOO_TO_BIGNUM_SIGNED(long_long, int64_t, uint64_t)
+FOO_TO_BIGNUM_UNSIGNED(ulong_long, uint64_t, uint64_t)
// cannot allocate memory
// bignum_to_cell, fixnum_to_cell, long_long_to_cell, ulong_long_to_cell
bignum_length_type x_length = (BIGNUM_LENGTH(x));
bignum_length_type y_length = (BIGNUM_LENGTH(y));
if (x_length < y_length)
- return (bignum_comparison_less);
+ return BIGNUM_COMPARISON_LESS;
if (x_length > y_length)
- return (bignum_comparison_greater);
+ return BIGNUM_COMPARISON_GREATER;
{
bignum_digit_type* start_x = (BIGNUM_START_PTR(x));
bignum_digit_type* scan_x = (start_x + x_length);
bignum_digit_type digit_x = (*--scan_x);
bignum_digit_type digit_y = (*--scan_y);
if (digit_x < digit_y)
- return (bignum_comparison_less);
+ return BIGNUM_COMPARISON_LESS;
if (digit_x > digit_y)
- return (bignum_comparison_greater);
+ return BIGNUM_COMPARISON_GREATER;
}
}
- return (bignum_comparison_equal);
+ return BIGNUM_COMPARISON_EQUAL;
}
// Addition
int negative_p = 0;
switch (bignum_compare_unsigned(x.untagged(), y.untagged())) {
- case bignum_comparison_equal:
+ case BIGNUM_COMPARISON_EQUAL:
return (BIGNUM_ZERO());
- case bignum_comparison_less:
+ case BIGNUM_COMPARISON_LESS:
swap(x, y);
negative_p = 1;
break;
- case bignum_comparison_greater:
+ case BIGNUM_COMPARISON_GREATER:
negative_p = 0;
break;
}
bignum_destructive_unnormalization(u.untagged(), shift);
}
- q = bignum_trim(q.untagged());
+ q.set_untagged(bignum_trim(q.untagged()));
*quotient = q.untagged();
} else {
}
}
- u = bignum_trim(u.untagged());
+ u.set_untagged(bignum_trim(u.untagged()));
if (remainder != NULL)
*remainder = u.untagged();
}
(*scan) = qj;
}
- q = bignum_trim(q.untagged());
+ q.set_untagged(bignum_trim(q.untagged()));
if (remainder != ((bignum**)0)) {
if (shift != 0)
bignum_digit_type r = bignum_destructive_scale_down(q.untagged(), denominator);
- q = bignum_trim(q.untagged());
+ q.set_untagged(bignum_trim(q.untagged()));
if (remainder != ((bignum**)0))
(*remainder) = bignum_digit_to_bignum(r, r_negative_p);
data_root<bignum> ac(bignum_maybe_new_sign(a.untagged(), 0), this);
data_root<bignum> bc(bignum_maybe_new_sign(b.untagged(), 0), this);
- if (bignum_compare(ac.untagged(), bc.untagged()) == bignum_comparison_less) {
+ if (bignum_compare(ac.untagged(), bc.untagged()) == BIGNUM_COMPARISON_LESS) {
swap(ac, bc);
}
data_root<bignum> a(a_, this);
data_root<bignum> b(b_, this);
bignum_twodigit_type x, y, q, s, t, A, B, C, D;
- int nbits, k;
+ unsigned long nbits;
+ int 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;
b = d;
// Initial reduction: make sure that 0 <= b <= a.
- if (bignum_compare(a.untagged(), b.untagged()) == bignum_comparison_less) {
+ if (bignum_compare(a.untagged(), b.untagged()) == BIGNUM_COMPARISON_LESS) {
swap(a, b);
std::swap(size_a, size_b);
}
}
data_root<bignum> e(bignum_trim(a.untagged()), this);
data_root<bignum> f(bignum_trim(b.untagged()), this);
- c = bignum_remainder(e.untagged(), f.untagged());
+ c.set_untagged(bignum_remainder(e.untagged(), f.untagged()));
if (c.untagged() == BIGNUM_OUT_OF_BAND) {
return c.untagged();
}