diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2025-11-18 15:37:57 +0100 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2025-11-18 15:37:57 +0100 |
| commit | 56aab55d8250ee8191583d6b5e97eace89cfbef7 (patch) | |
| tree | f002236da77d904520112e2236d658cebd7149e1 | |
| parent | 784f320e12721761af494816cf07ed08d00deced (diff) | |
Fix #5931
Fix #5931 and add test case for it.
| -rw-r--r-- | core/math/big/internal.odin | 18 | ||||
| -rw-r--r-- | core/math/big/private.odin | 11 | ||||
| -rw-r--r-- | tests/core/math/big/test_core_math_big.odin | 21 |
3 files changed, 31 insertions, 19 deletions
diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index e22ea0ec7..b3e23da8c 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -746,19 +746,15 @@ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, a if (denominator.used > 2 * MUL_KARATSUBA_CUTOFF) && (denominator.used <= (numerator.used / 3) * 2) { assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set.") - err = _private_int_div_recursive(quotient, remainder, numerator, denominator) + return _private_int_div_recursive(quotient, remainder, numerator, denominator) } else { - when true { - err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator) - } else { - /* - NOTE(Jeroen): We no longer need or use `_private_int_div_small`. - We'll keep it around for a bit until we're reasonably certain div_school is bug free. - */ - err = _private_int_div_small(quotient, remainder, numerator, denominator) - } + return #force_inline _private_int_div_school(quotient, remainder, numerator, denominator) + /* + NOTE(Jeroen): We no longer need or use `_private_int_div_small`. + We'll keep it around for a bit until we're reasonably certain div_school is bug free. + */ + // err = _private_int_div_small(quotient, remainder, numerator, denominator) } - return } /* diff --git a/core/math/big/private.odin b/core/math/big/private.odin index fb517f0b7..4847b0074 100644 --- a/core/math/big/private.odin +++ b/core/math/big/private.odin @@ -1050,7 +1050,6 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In Normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT] */ norm := internal_count_bits(y) % _DIGIT_BITS - if norm < _DIGIT_BITS - 1 { norm = (_DIGIT_BITS - 1) - norm internal_shl(x, x, norm) or_return @@ -1070,33 +1069,29 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In y = y*b**{n-t} */ + _private_int_shl_leg(y, n - t) or_return - gte := internal_gte(x, y) - for gte { + for internal_gte(x, y) { q.digit[n - t] += 1 internal_sub(x, x, y) or_return - gte = internal_gte(x, y) } /* Reset y by shifting it back down. */ _private_int_shr_leg(y, n - t) - /* Step 3. for i from n down to (t + 1). */ #no_bounds_check for i := n; i >= (t + 1); i -= 1 { if i > x.used { continue } - /* step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ if x.digit[i] == y.digit[t] { - q.digit[(i - t) - 1] = 1 << (_DIGIT_BITS - 1) + q.digit[(i - t) - 1] = 1 << _DIGIT_BITS - 1 } else { - tmp := _WORD(x.digit[i]) << _DIGIT_BITS tmp |= _WORD(x.digit[i - 1]) tmp /= _WORD(y.digit[t]) diff --git a/tests/core/math/big/test_core_math_big.odin b/tests/core/math/big/test_core_math_big.odin index 42df7154f..766ff78b0 100644 --- a/tests/core/math/big/test_core_math_big.odin +++ b/tests/core/math/big/test_core_math_big.odin @@ -224,6 +224,27 @@ test_big_math_vectors :: proc(t: ^testing.T) { } } +@(test) +bug_5931 :: proc(t: ^testing.T) { + numerator, divisor, quotient, remainder: big.Int + defer big.destroy(&numerator, &divisor, "ient, &remainder) + + big.string_to_int(&numerator, "3351951982485649274893506249551461531869841455148098344430890360930192345844485855956241793418914802713278852793799976230545127411560969441984014513833901") + big.string_to_int(&divisor, "115792089237316195423570985008687907853269984665640564039457584007908834671663") + + big.int_divmod("ient, &remainder, &numerator, &divisor) + quo_str, _ := big.int_itoa_string("ient) + defer delete(quo_str) + assert(quo_str == "28948022309329048855892746252171976963317496166410141009864396001977208667923") + + rem_str, _ := big.int_itoa_string(&remainder) + defer delete(rem_str) + assert(rem_str == "28948022309329048855892746252171976963317496166410141009864396001977208667952") +} + + +// Test helpers + expect_a :: proc(t: ^testing.T, format: string, a, expected, res: ^big.Int, err: big.Error, loc := #caller_location) { if err != .Okay { return } |