From dcbc9e0b9b1c893bb8b75a4dcdc426b289ce69b1 Mon Sep 17 00:00:00 2001 From: phoebe Date: Sat, 22 Jul 2023 08:20:45 +0200 Subject: [PATCH] math.big: add `isqrt_checked` and standardize error format (#18939) --- vlib/math/big/division_array_ops_test.v | 2 +- vlib/math/big/integer.v | 19 ++++++++++++++----- vlib/math/big/special_array_ops_test.v | 16 ++++++++-------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/vlib/math/big/division_array_ops_test.v b/vlib/math/big/division_array_ops_test.v index c6f122c65bfbdf..de8e0bb10b3d8d 100644 --- a/vlib/math/big/division_array_ops_test.v +++ b/vlib/math/big/division_array_ops_test.v @@ -146,6 +146,6 @@ fn random_number(length int) Integer { nr := numbers[i] stri = stri + nr.ascii_str() } - res := integer_from_string(stri) or { panic('error in random_number') } + res := integer_from_string(stri) or { panic(err) } return res } diff --git a/vlib/math/big/integer.v b/vlib/math/big/integer.v index e7fe59fecbdc2a..42b8c13bc2aaf3 100644 --- a/vlib/math/big/integer.v +++ b/vlib/math/big/integer.v @@ -158,7 +158,7 @@ pub fn integer_from_string(characters string) !Integer { // integer_from_radix creates a new `big.Integer` from the given string and radix. pub fn integer_from_radix(all_characters string, radix u32) !Integer { if radix < 2 || radix > 36 { - return error('Radix must be between 2 and 36 (inclusive)') + return error('math.big: Radix must be between 2 and 36 (inclusive)') } characters := all_characters.to_lower() validate_string(characters, radix)! @@ -186,10 +186,10 @@ fn validate_string(characters string, radix u32) ! { value := big.digit_array.index(digit) if value == -1 { - return error('Invalid character ${digit}') + return error('math.big: Invalid character ${digit}') } if value >= radix { - return error('Invalid character ${digit} for base ${radix}') + return error('math.big: Invalid character ${digit} for base ${radix}') } } } @@ -972,10 +972,19 @@ pub fn (a Integer) factorial() Integer { return product } -// isqrt returns the closest integer square root of the given integer. +// isqrt returns the closest integer square root of the integer `a`. +// +// WARNING: this method will panic if `a < 0`. Refer to isqrt_checked for a safer version. +[inline] pub fn (a Integer) isqrt() Integer { + return a.isqrt_checked() or { panic(err) } +} + +// isqrt returns the closest integer square root of the integer `a`. +// An error is returned if `a < 0`. +pub fn (a Integer) isqrt_checked() !Integer { if a.signum < 0 { - panic('Cannot obtain square root of negative integer') + return error('math.big: Cannot calculate square root of negative integer') } if a.signum == 0 { return a diff --git a/vlib/math/big/special_array_ops_test.v b/vlib/math/big/special_array_ops_test.v index 08b7244a3071bf..f7c49dee0c3c94 100644 --- a/vlib/math/big/special_array_ops_test.v +++ b/vlib/math/big/special_array_ops_test.v @@ -67,25 +67,25 @@ fn test_multiply_karatsuba_01() { karatsuba_multiply_digit_array(a, b, mut c) assert c == [u32(0xcaf2722e), 0x55eb2c5a, 0x3dc] - a_operand := integer_from_string('95484736384949495947362') or { panic('error') } - b_operand := integer_from_string('39474638493') or { panic('error') } + a_operand := integer_from_string('95484736384949495947362') or { panic(err) } + b_operand := integer_from_string('39474638493') or { panic(err) } c = []u32{len: a_operand.digits.len + b_operand.digits.len, init: 0} karatsuba_multiply_digit_array(a_operand.digits, b_operand.digits, mut c) - expected := integer_from_string('3769225450395285038584683507005466') or { panic('error') } + expected := integer_from_string('3769225450395285038584683507005466') or { panic(err) } assert c == expected.digits } fn test_multiply_karatsuba_02() { a := integer_from_string('53575430359313366047421252453000090528070240585276680372187519418517552556246806124659918940784792906379733645877657341259357264284615702179922887873492874019672838874121154927105373025311855709389770910765') or { - panic('error') + panic(err) } b := integer_from_string('977091076523237491790970633699383779582771973038531457285598238843271083830214915826312193418602834034688531898668229388286706296786321423078510899614439367') or { - panic('error') + panic(err) } mut c := []u32{len: a.digits.len + b.digits.len + 1, init: 0} karatsuba_multiply_digit_array(a.digits, b.digits, mut c) expected := integer_from_string('52348074924977237255285644820010078601114587486470740900886892189662650320988400136613780986308710610258879824881256666730655821800564143426560480113864123642197317383052431412305975584645367703594190956925565749714310612399025459615546540332117815550470167143256687163102859337019449165214274088466835988832405507818643018779158891710706073875995722420460085755') or { - panic('error') + panic(err) } } @@ -135,10 +135,10 @@ fn test_newton_divide_06() { fn test_newton_divide_07() { a := integer_from_string('52348074924977237255285644820010078601114587486470740900886892189662650320988400136613780986308710610258879824881256666730655821800564143426560480113864123642197317383052431412305975584645367703594190956925565749714310612399025459615546540332117815550470167143256687163102859337019449165214274088466835988832405507818643018779158891710706073875995722420460085757') or { - panic('error') + panic(err) } b := integer_from_string('977091076523237491790970633699383779582771973038531457285598238843271083830214915826312193418602834034688531898668229388286706296786321423078510899614439367') or { - panic('error') + panic(err) } mut q := []u32{cap: a.digits.len - b.digits.len + 1} mut r := []u32{cap: a.digits.len}