From 8c1e43f001161771cb21b44583dcc35c5e3a4067 Mon Sep 17 00:00:00 2001 From: jangko Date: Thu, 22 Jun 2023 16:43:31 +0700 Subject: [PATCH] fix shlAddMod SIGFPE bug --- stint/private/uint_div.nim | 25 +++++++++++++++++-------- tests/test_uint_divmod.nim | 13 ++++++++++++- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/stint/private/uint_div.nim b/stint/private/uint_div.nim index 34d2061..fb54ebf 100644 --- a/stint/private/uint_div.nim +++ b/stint/private/uint_div.nim @@ -141,17 +141,26 @@ func shlAddMod(a: var openArray[Word], c: Word, # And normalize (a * 2^64 + c) by R as well to maintain the result # This ensures that (a0, a1)/p0 fits in a limb. let R = mBits and (WordBitWidth - 1) - let clz = WordBitWidth-R # (hi, lo) = a * 2^64 + c - let hi = (a[0] shl clz) or (c shr R) - let lo = c shl clz - let m0 = M[0] shl clz + if R == 0: + # We can delegate this R == 0 case to the + # shlAddMod_multi, with the same result. + # But isn't it faster to handle it here? + var q, r: Word + div2n1n(q, r, a[0], c, M[0]) + a[0] = r + return q + else: + let clz = WordBitWidth-R + let hi = (a[0] shl clz) or (c shr R) + let lo = c shl clz + let m0 = M[0] shl clz - var q, r: Word - div2n1n(q, r, hi, lo, m0) - a[0] = r shr clz - return q + var q, r: Word + div2n1n(q, r, hi, lo, m0) + a[0] = r shr clz + return q else: return shlAddMod_multi(a, c, M, mBits) diff --git a/tests/test_uint_divmod.nim b/tests/test_uint_divmod.nim index 1a8ce04..ba7fc55 100644 --- a/tests/test_uint_divmod.nim +++ b/tests/test_uint_divmod.nim @@ -60,7 +60,7 @@ template testdivmod(chk, tst: untyped) = chkDivMod(chk, "FFFFFFFFFFFFFFFF", "27", "690690690690690", "F", 128) chkDivMod(chk, "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "27", "6906906906906906906906906906906", "15", 128) -static: +#[static: testdivmod(ctCheck, ctTest) suite "Wider unsigned int muldiv coverage": @@ -101,6 +101,7 @@ suite "Testing unsigned int division and modulo implementation": check: q == 123456789123456789'u64.u256 r == 0'u64.u256 +]# suite "Testing specific failures highlighted by property-based testing": test "Modulo: 65696211516342324 mod 174261910798982": @@ -127,3 +128,13 @@ suite "Testing specific failures highlighted by property-based testing": let tz = a mod b check z.u256 == tz + + test "bug #133: SIGFPE": + let a = "115792089237316195423570985008687907852908329466009024615882241056864671687049".u256 + let b = "15030568110056696491".u256 + let q = a div b + let r = a mod b + check q == "7703773296489151700480904010733627392011592199037677352760".u256 + let w = q * b + r + check w == a +