From 38519eca27657e6e678b26fe4cd56c12691eb200 Mon Sep 17 00:00:00 2001 From: Mike <45243121+tankf33der@users.noreply.github.com> Date: Tue, 26 Aug 2025 04:06:07 +0300 Subject: [PATCH] math.big: remove Newton-raphson division, remove related tests (#25168) --- vlib/math/big/array_ops.v | 8 +--- vlib/math/big/special_array_ops.v | 51 --------------------- vlib/math/big/special_array_ops_test.v | 63 -------------------------- 3 files changed, 1 insertion(+), 121 deletions(-) diff --git a/vlib/math/big/array_ops.v b/vlib/math/big/array_ops.v index a13b86c46b..dc5f535d1a 100644 --- a/vlib/math/big/array_ops.v +++ b/vlib/math/big/array_ops.v @@ -239,15 +239,9 @@ fn divide_array_by_digit(operand_a []u64, divisor u64, mut quotient []u64, mut r shrink_tail_zeros(mut remainder) } -const newton_division_limit = 1_000_000 - @[inline] fn divide_array_by_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut remainder []u64) { - if operand_a.len >= newton_division_limit { - newton_divide_array_by_array(operand_a, operand_b, mut quotient, mut remainder) - } else { - binary_divide_array_by_array(operand_a, operand_b, mut quotient, mut remainder) - } + binary_divide_array_by_array(operand_a, operand_b, mut quotient, mut remainder) } // Shifts the contents of the original array by the given amount of bits to the left. diff --git a/vlib/math/big/special_array_ops.v b/vlib/math/big/special_array_ops.v index f86be3133f..dc3f261ce4 100644 --- a/vlib/math/big/special_array_ops.v +++ b/vlib/math/big/special_array_ops.v @@ -24,57 +24,6 @@ fn (i &Integer) shrink_tail_zeros() { } } -// suppose operand_a bigger than operand_b and both not null. -// Both quotient and remaider are already allocated but of length 0 -// TODO: the manualfree tag here is a workaround for compilation with -autofree. Remove it, when the -autofree bug is fixed. -@[manualfree] -fn newton_divide_array_by_array(operand_a []u64, operand_b []u64, mut quotient []u64, mut remainder []u64) { - // transform back to Integers (on the stack without allocation) - a := Integer{ - signum: 1 - digits: operand_a - } - b := Integer{ - signum: 1 - digits: operand_b - } - - k := a.bit_len() + b.bit_len() // a*b < 2**k - mut x := integer_from_int(2) // 0 < x < 2**(k+1)/b // initial guess for convergence - // https://en.wikipedia.org/wiki/Division_algorithm#Newton%E2%80%93Raphson_division - // use 48/17 - (32/17)*D (divisor) - // where D - Divisor B adjusted to fit 0.5-1 range by replacing the exponent field with 8'd126 - // 0x0f0f0f0f0f0f0f0f * 0x11 == 0xffffffff_ffffffff = -1 - // 0x0f0f0f0f0f0f0f0f = -1/17 - initial_guess := (((integer_from_int(48) - (integer_from_int(32) * b)) * integer_from_i64(0x0f0f0f0f0f0f0f0f)).right_shift(64)).neg() // / 17 == 0x11 - if initial_guess > zero_int { - x = initial_guess - } - mut lastx := integer_from_int(0) - pow2_k_plus_1 := pow2(k + 1) // outside of the loop to optimize allocatio - for lastx != x { // main loop - lastx = x - x = (x * (pow2_k_plus_1 - (x * b))).right_shift(u32(k)) - } - if x * b < pow2(k) { - x.inc() - } - mut q := (a * x).right_shift(u32(k)) - // possible adjustments. see literature - if q * b > a { - q.dec() - } - mut r := a - (q * b) - if r >= b { - q.inc() - r -= b - } - quotient = q.digits.clone() - remainder = r.digits.clone() - - shrink_tail_zeros(mut remainder) -} - // debug_u64_str output a `[]u64` @[direct_array_access] fn debug_u64_str(a []u64) string { diff --git a/vlib/math/big/special_array_ops_test.v b/vlib/math/big/special_array_ops_test.v index fe3f511864..d9d1b9b78a 100644 --- a/vlib/math/big/special_array_ops_test.v +++ b/vlib/math/big/special_array_ops_test.v @@ -128,66 +128,3 @@ fn test_multiply_karatsuba_05() { } assert c == expected.digits } - -fn test_newton_divide_03() { - a := [u64(0), 4] - b := [u64(0), 1] - mut q := []u64{cap: a.len - b.len + 1} - mut r := []u64{cap: a.len} - - newton_divide_array_by_array(a, b, mut q, mut r) - assert q == [u64(4)] - assert r == []u64{len: 0} -} - -fn test_newton_divide_04() { - a := [u64(2), 4] - b := [u64(0), 1] - mut q := []u64{cap: a.len - b.len + 1} - mut r := []u64{cap: a.len} - - newton_divide_array_by_array(a, b, mut q, mut r) - assert q == [u64(4)] - assert r == [u64(2)] -} - -fn test_newton_divide_05() { - a := [u64(2), 4, 5] - b := [u64(0), 1] - mut q := []u64{cap: a.len - b.len + 1} - mut r := []u64{cap: a.len} - - newton_divide_array_by_array(a, b, mut q, mut r) - assert q == [u64(4), 5] - assert r == [u64(2)] -} - -fn test_newton_divide_06() { - a := [u64(2), 4, 5, 3] - b := [u64(0), 0x8000] - mut q := []u64{cap: a.len - b.len + 1} - mut r := []u64{cap: a.len} - - newton_divide_array_by_array(a, b, mut q, mut r) - assert q == [u64(0xa000_0000_0000), 0x6000_0000_0000] - assert r == [u64(2), 4] -} - -fn test_newton_divide_07() { - a := integer_from_string('52348074924977237255285644820010078601114587486470740900886892189662650320988400136613780986308710610258879824881256666730655821800564143426560480113864123642197317383052431412305975584645367703594190956925565749714310612399025459615546540332117815550470167143256687163102859337019449165214274088466835988832405507818643018779158891710706073875995722420460085757') or { - panic(err) - } - b := integer_from_string('977091076523237491790970633699383779582771973038531457285598238843271083830214915826312193418602834034688531898668229388286706296786321423078510899614439367') or { - panic(err) - } - mut q := []u64{cap: a.digits.len - b.digits.len + 1} - mut r := []u64{cap: a.digits.len} - - newton_divide_array_by_array(a.digits, b.digits, mut q, mut r) - quotient := Integer{ - signum: 1 - digits: q - } - assert quotient.str() == '53575430359313366047421252453000090528070240585276680372187519418517552556246806124659918940784792906379733645877657341259357264284615702179922887873492874019672838874121154927105373025311855709389770910765' - assert r == [u64(2)] -}