mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-bigint: remove broken MSVC _umul128 optimization path
The MSVC _umul128 code path was designed for 64-bit limbs but mruby's bigint implementation uses 32-bit limbs even on 64-bit builds. This fundamental mismatch caused incorrect bigint calculations on VC 64-bit builds, producing results like "100000000000000000000" -> "1661992960". Removed the MSVC optimization to fall back to the portable double-limb arithmetic which correctly handles 32-bit limbs. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -784,97 +784,6 @@ limb_addmul_1(mp_limb *rp, const mp_limb *s1p, size_t n, mp_limb limb)
|
||||
|
||||
return (mp_limb)acc;
|
||||
|
||||
#elif defined(_MSC_VER) && defined(MRB_64BIT) && !defined(MRB_NO_MPZ64BIT)
|
||||
/* 64-bit limbs on MSVC with 6x unrolling: use _umul128 */
|
||||
unsigned long long carry = 0;
|
||||
size_t i;
|
||||
|
||||
/* 6x unrolled loop for large operands */
|
||||
for (i = 0; i + 6 <= n; i += 6) {
|
||||
unsigned long long hi, lo, sum;
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val = (unsigned long long)rp[i];
|
||||
unsigned long long temp = rp_val + lo;
|
||||
sum = temp + carry;
|
||||
rp[i] = (mp_limb)sum;
|
||||
carry = hi + (temp < rp_val) + (sum < temp);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+1], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val1 = (unsigned long long)rp[i+1];
|
||||
unsigned long long temp1 = rp_val1 + lo;
|
||||
sum = temp1 + carry;
|
||||
rp[i+1] = (mp_limb)sum;
|
||||
carry = hi + (temp1 < rp_val1) + (sum < temp1);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+2], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val2 = (unsigned long long)rp[i+2];
|
||||
unsigned long long temp2 = rp_val2 + lo;
|
||||
sum = temp2 + carry;
|
||||
rp[i+2] = (mp_limb)sum;
|
||||
carry = hi + (temp2 < rp_val2) + (sum < temp2);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+3], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val3 = (unsigned long long)rp[i+3];
|
||||
unsigned long long temp3 = rp_val3 + lo;
|
||||
sum = temp3 + carry;
|
||||
rp[i+3] = (mp_limb)sum;
|
||||
carry = hi + (temp3 < rp_val3) + (sum < temp3);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+4], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val4 = (unsigned long long)rp[i+4];
|
||||
unsigned long long temp4 = rp_val4 + lo;
|
||||
sum = temp4 + carry;
|
||||
rp[i+4] = (mp_limb)sum;
|
||||
carry = hi + (temp4 < rp_val4) + (sum < temp4);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+5], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val5 = (unsigned long long)rp[i+5];
|
||||
unsigned long long temp5 = rp_val5 + lo;
|
||||
sum = temp5 + carry;
|
||||
rp[i+5] = (mp_limb)sum;
|
||||
carry = hi + (temp5 < rp_val5) + (sum < temp5);
|
||||
}
|
||||
|
||||
/* 3x unrolled loop for medium operands */
|
||||
for (; i + 3 <= n; i += 3) {
|
||||
unsigned long long hi, lo, sum;
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val = (unsigned long long)rp[i];
|
||||
unsigned long long temp = rp_val + lo;
|
||||
sum = temp + carry;
|
||||
rp[i] = (mp_limb)sum;
|
||||
carry = hi + (temp < rp_val) + (sum < temp);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+1], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val1 = (unsigned long long)rp[i+1];
|
||||
unsigned long long temp1 = rp_val1 + lo;
|
||||
sum = temp1 + carry;
|
||||
rp[i+1] = (mp_limb)sum;
|
||||
carry = hi + (temp1 < rp_val1) + (sum < temp1);
|
||||
|
||||
lo = _umul128((unsigned long long)s1p[i+2], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val2 = (unsigned long long)rp[i+2];
|
||||
unsigned long long temp2 = rp_val2 + lo;
|
||||
sum = temp2 + carry;
|
||||
rp[i+2] = (mp_limb)sum;
|
||||
carry = hi + (temp2 < rp_val2) + (sum < temp2);
|
||||
}
|
||||
|
||||
/* Handle remaining elements */
|
||||
for (; i < n; i++) {
|
||||
unsigned long long hi, lo;
|
||||
lo = _umul128((unsigned long long)s1p[i], (unsigned long long)limb, &hi);
|
||||
unsigned long long rp_val = (unsigned long long)rp[i];
|
||||
unsigned long long temp = rp_val + lo;
|
||||
unsigned long long sum = temp + carry;
|
||||
rp[i] = (mp_limb)sum;
|
||||
carry = hi + (temp < rp_val) + (sum < temp);
|
||||
}
|
||||
|
||||
return (mp_limb)carry;
|
||||
|
||||
#else
|
||||
/* Portable double-limb path with 4x unrolling */
|
||||
mp_dbl_limb acc = 0;
|
||||
|
||||
Reference in New Issue
Block a user