vm: adding a fast path for bignum sq.
parent
a992963f44
commit
6c703bbd6c
|
@ -107,8 +107,65 @@ bignum* factor_vm::bignum_subtract(bignum* x, bignum* y) {
|
|||
: (bignum_subtract_unsigned(x, y))))));
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
bignum *factor_vm::bignum_square(bignum * x)
|
||||
{
|
||||
return bignum_multiply(x, x);
|
||||
}
|
||||
#else
|
||||
/* Allocates memory */
|
||||
bignum *factor_vm::bignum_square(bignum * x)
|
||||
{
|
||||
GC_BIGNUM(x);
|
||||
|
||||
bignum_length_type length = (BIGNUM_LENGTH (x));
|
||||
bignum * z = (allot_bignum_zeroed ((length + length), 0));
|
||||
|
||||
bignum_digit_type * scan_z = BIGNUM_START_PTR (z);
|
||||
bignum_digit_type * scan_x = BIGNUM_START_PTR (x);
|
||||
bignum_digit_type * end_x = scan_x + length;
|
||||
|
||||
for (int i = 0; i < length; ++i) {
|
||||
bignum_twodigit_type carry;
|
||||
bignum_twodigit_type f = BIGNUM_REF (x, i);
|
||||
bignum_digit_type *pz = scan_z + (i << 1);
|
||||
bignum_digit_type *px = scan_x + i + 1;
|
||||
|
||||
carry = *pz + f * f;
|
||||
*pz++ = carry & BIGNUM_DIGIT_MASK;
|
||||
carry >>= BIGNUM_DIGIT_LENGTH;
|
||||
BIGNUM_ASSERT (carry <= BIGNUM_DIGIT_MASK);
|
||||
|
||||
f <<= 1;
|
||||
while (px < end_x)
|
||||
{
|
||||
carry += *pz + *px++ * f;
|
||||
*pz++ = carry & BIGNUM_DIGIT_MASK;
|
||||
carry >>= BIGNUM_DIGIT_LENGTH;
|
||||
BIGNUM_ASSERT (carry <= (BIGNUM_DIGIT_MASK << 1));
|
||||
}
|
||||
if (carry) {
|
||||
carry += *pz;
|
||||
*pz++ = carry & BIGNUM_DIGIT_MASK;
|
||||
carry >>= BIGNUM_DIGIT_LENGTH;
|
||||
}
|
||||
if (carry)
|
||||
*pz += carry & BIGNUM_DIGIT_MASK;
|
||||
BIGNUM_ASSERT ((carry >> BIGNUM_DIGIT_LENGTH) == 0);
|
||||
}
|
||||
return (bignum_trim (z));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Allocates memory */
|
||||
bignum* factor_vm::bignum_multiply(bignum* x, bignum* y) {
|
||||
|
||||
#ifndef _WIN64
|
||||
if (x == y) {
|
||||
return bignum_square(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
bignum_length_type x_length = (BIGNUM_LENGTH(x));
|
||||
bignum_length_type y_length = (BIGNUM_LENGTH(y));
|
||||
int negative_p = ((BIGNUM_NEGATIVE_P(x)) ? (!(BIGNUM_NEGATIVE_P(y)))
|
||||
|
|
|
@ -232,6 +232,7 @@ struct factor_vm {
|
|||
enum bignum_comparison bignum_compare(bignum* x, bignum* y);
|
||||
bignum* bignum_add(bignum* x, bignum* y);
|
||||
bignum* bignum_subtract(bignum* x, bignum* y);
|
||||
bignum* bignum_square(bignum* x);
|
||||
bignum* bignum_multiply(bignum* x, bignum* y);
|
||||
void bignum_divide(bignum* numerator, bignum* denominator, bignum** quotient,
|
||||
bignum** remainder);
|
||||
|
|
Loading…
Reference in New Issue