diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 69497b150..437f6e5fc 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -2648,7 +2648,7 @@ internal_int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, all Shift by as many digits in the bit count. */ if bits >= _DIGIT_BITS { - internal_shr_digit(quotient, bits / _DIGIT_BITS) or_return + _private_int_shr_leg(quotient, bits / _DIGIT_BITS) or_return } /* @@ -2687,37 +2687,6 @@ internal_int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.all } internal_shr :: proc { internal_int_shr, } -/* - Shift right by `digits` * _DIGIT_BITS bits. -*/ -internal_int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator - - if digits <= 0 { return nil } - - /* - If digits > used simply zero and return. - */ - if digits > quotient.used { return internal_zero(quotient) } - - /* - Much like `int_shl_digit`, this is implemented using a sliding window, - except the window goes the other way around. - - b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> - /\ | ----> - \-------------------/ ----> - */ - - #no_bounds_check for x := 0; x < (quotient.used - digits); x += 1 { - quotient.digit[x] = quotient.digit[x + digits] - } - quotient.used -= digits - internal_zero_unused(quotient) - return internal_clamp(quotient) -} -internal_shr_digit :: proc { internal_int_shr_digit, } - /* Shift right by a certain bit count with sign extension. */ @@ -2756,7 +2725,7 @@ internal_int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.alloca Shift by as many digits in the bit count as we have. */ if bits >= _DIGIT_BITS { - internal_shl_digit(dest, bits / _DIGIT_BITS) or_return + _private_int_shl_leg(dest, bits / _DIGIT_BITS) or_return } /* @@ -2786,45 +2755,6 @@ internal_int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.alloca } internal_shl :: proc { internal_int_shl, } - -/* - Shift left by `digits` * _DIGIT_BITS bits. -*/ -internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator - - if digits <= 0 { return nil } - - /* - No need to shift a zero. - */ - if #force_inline internal_is_zero(quotient) { - return nil - } - - /* - Resize `quotient` to accomodate extra digits. - */ - #force_inline internal_grow(quotient, quotient.used + digits) or_return - - /* - Increment the used by the shift amount then copy upwards. - */ - - /* - Much like `int_shr_digit`, this is implemented using a sliding window, - except the window goes the other way around. - */ - #no_bounds_check for x := quotient.used; x > 0; x -= 1 { - quotient.digit[x+digits-1] = quotient.digit[x-1] - } - - quotient.used += digits - mem.zero_slice(quotient.digit[:digits]) - return nil -} -internal_shl_digit :: proc { internal_int_shl_digit, } - /* Count bits in an `Int`. Assumes `a` not to be `nil` and to have been initialized. diff --git a/core/math/big/logical.odin b/core/math/big/logical.odin index dbcf566c8..e7e55cc47 100644 --- a/core/math/big/logical.odin +++ b/core/math/big/logical.odin @@ -86,21 +86,6 @@ int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) - } shr :: proc { int_shr, } -/* - Shift right by `digits` * _DIGIT_BITS bits. -*/ -int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { - /* - Check that `quotient` is usable. - */ - assert_if_nil(quotient) - context.allocator = allocator - - internal_clear_if_uninitialized(quotient) or_return - return #force_inline internal_int_shr_digit(quotient, digits) -} -shr_digit :: proc { int_shr_digit, } - /* Shift right by a certain bit count with sign extension. */ @@ -124,20 +109,4 @@ int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> ( internal_clear_if_uninitialized(dest, src) or_return return #force_inline internal_int_shl(dest, src, bits) } -shl :: proc { int_shl, } - - -/* - Shift left by `digits` * _DIGIT_BITS bits. -*/ -int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { - /* - Check that `quotient` is usable. - */ - assert_if_nil(quotient) - context.allocator = allocator - - internal_clear_if_uninitialized(quotient) or_return - return #force_inline internal_int_shl_digit(quotient, digits) -} -shl_digit :: proc { int_shl_digit, }; \ No newline at end of file +shl :: proc { int_shl, } \ No newline at end of file diff --git a/core/math/big/private.odin b/core/math/big/private.odin index 14a27f600..9989a208a 100644 --- a/core/math/big/private.odin +++ b/core/math/big/private.odin @@ -211,12 +211,12 @@ _private_int_mul_toom :: proc(dest, a, b: ^Int, allocator := context.allocator) /* P = b1*x^4+ S2*x^3+ S1*x^2+ a1*x + a0; */ - internal_shl_digit(b1, 4 * B) or_return - internal_shl_digit(S2, 3 * B) or_return + _private_int_shl_leg(b1, 4 * B) or_return + _private_int_shl_leg(S2, 3 * B) or_return internal_add(b1, b1, S2) or_return - internal_shl_digit(S1, 2 * B) or_return + _private_int_shl_leg(S1, 2 * B) or_return internal_add(b1, b1, S1) or_return - internal_shl_digit(a1, 1 * B) or_return + _private_int_shl_leg(a1, 1 * B) or_return internal_add(b1, b1, a1) or_return internal_add(dest, b1, a0) or_return @@ -317,8 +317,8 @@ _private_int_mul_karatsuba :: proc(dest, a, b: ^Int, allocator := context.alloca /* shift by B. */ - internal_shl_digit(t1, B) or_return /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<= n then x = x - n @@ -2026,7 +2026,7 @@ _private_int_reduce :: proc(x, m, mu: ^Int, allocator := context.allocator) -> ( /* q1 = x / b**(k-1) */ - internal_shr_digit(q, um - 1) + _private_int_shr_leg(q, um - 1) /* According to HAC this optimization is ok. @@ -2040,7 +2040,7 @@ _private_int_reduce :: proc(x, m, mu: ^Int, allocator := context.allocator) -> ( /* q3 = q2 / b**(k+1) */ - internal_shr_digit(q, um + 1) + _private_int_shr_leg(q, um + 1) /* x = x mod b**(k+1), quick (no division) @@ -2062,7 +2062,7 @@ _private_int_reduce :: proc(x, m, mu: ^Int, allocator := context.allocator) -> ( */ if internal_is_negative(x) { internal_set(q, 1) or_return - internal_shl_digit(q, um + 1) or_return + _private_int_shl_leg(q, um + 1) or_return internal_add(x, x, q) or_return } @@ -3192,6 +3192,74 @@ _private_copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0)) -> return nil } + +/* + Shift left by `digits` * _DIGIT_BITS bits. +*/ +_private_int_shl_leg :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { + context.allocator = allocator + + if digits <= 0 { return nil } + + /* + No need to shift a zero. + */ + if #force_inline internal_is_zero(quotient) { + return nil + } + + /* + Resize `quotient` to accomodate extra digits. + */ + #force_inline internal_grow(quotient, quotient.used + digits) or_return + + /* + Increment the used by the shift amount then copy upwards. + */ + + /* + Much like `_private_int_shr_leg`, this is implemented using a sliding window, + except the window goes the other way around. + */ + #no_bounds_check for x := quotient.used; x > 0; x -= 1 { + quotient.digit[x+digits-1] = quotient.digit[x-1] + } + + quotient.used += digits + mem.zero_slice(quotient.digit[:digits]) + return nil +} + +/* + Shift right by `digits` * _DIGIT_BITS bits. +*/ +_private_int_shr_leg :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { + context.allocator = allocator + + if digits <= 0 { return nil } + + /* + If digits > used simply zero and return. + */ + if digits > quotient.used { return internal_zero(quotient) } + + /* + Much like `int_shl_digit`, this is implemented using a sliding window, + except the window goes the other way around. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + + #no_bounds_check for x := 0; x < (quotient.used - digits); x += 1 { + quotient.digit[x] = quotient.digit[x + digits] + } + quotient.used -= digits + internal_zero_unused(quotient) + return internal_clamp(quotient) +} + /* ======================== End of private procedures ======================= diff --git a/tests/core/math/big/test.odin b/tests/core/math/big/test.odin index 07fa0364b..81f1956dc 100644 --- a/tests/core/math/big/test.odin +++ b/tests/core/math/big/test.odin @@ -208,7 +208,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring { /* dest = shr_digit(src, digits) */ -@export test_shr_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { +@export test_shr_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { context = runtime.default_context() err: big.Error @@ -216,7 +216,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring { defer big.internal_destroy(src) if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err} } - if err = #force_inline big.internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} } + if err = #force_inline big._private_int_shr_leg(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} } r := print_to_buffer(src) return PyRes{res = r, err = nil} @@ -225,7 +225,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring { /* dest = shl_digit(src, digits) */ -@export test_shl_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { +@export test_shl_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { context = runtime.default_context() err: big.Error @@ -233,7 +233,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring { defer big.internal_destroy(src) if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err} } - if err = #force_inline big.internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} } + if err = #force_inline big._private_int_shl_leg(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} } r := print_to_buffer(src) return PyRes{res = r, err = nil} diff --git a/tests/core/math/big/test.py b/tests/core/math/big/test.py index 629e76e6e..d292a3ff4 100644 --- a/tests/core/math/big/test.py +++ b/tests/core/math/big/test.py @@ -187,8 +187,8 @@ int_sqrt = load(l.test_sqrt, [c_char_p ], Res) int_root_n = load(l.test_root_n, [c_char_p, c_longlong], Res) # Logical operations -int_shl_digit = load(l.test_shl_digit, [c_char_p, c_longlong], Res) -int_shr_digit = load(l.test_shr_digit, [c_char_p, c_longlong], Res) +int_shl_leg = load(l.test_shl_leg, [c_char_p, c_longlong], Res) +int_shr_leg = load(l.test_shr_leg, [c_char_p, c_longlong], Res) int_shl = load(l.test_shl, [c_char_p, c_longlong], Res) int_shr = load(l.test_shr, [c_char_p, c_longlong], Res) int_shr_signed = load(l.test_shr_signed, [c_char_p, c_longlong], Res) @@ -402,17 +402,17 @@ def test_root_n(number = 0, root = 0, expected_error = Error.Okay): return test("test_root_n", res, [number, root], expected_error, expected_result) -def test_shl_digit(a = 0, digits = 0, expected_error = Error.Okay): +def test_shl_leg(a = 0, digits = 0, expected_error = Error.Okay): args = [arg_to_odin(a), digits] - res = int_shl_digit(*args) + res = int_shl_leg(*args) expected_result = None if expected_error == Error.Okay: expected_result = a << (digits * 60) - return test("test_shl_digit", res, [a, digits], expected_error, expected_result) + return test("test_shl_leg", res, [a, digits], expected_error, expected_result) -def test_shr_digit(a = 0, digits = 0, expected_error = Error.Okay): +def test_shr_leg(a = 0, digits = 0, expected_error = Error.Okay): args = [arg_to_odin(a), digits] - res = int_shr_digit(*args) + res = int_shr_leg(*args) expected_result = None if expected_error == Error.Okay: if a < 0: @@ -421,7 +421,7 @@ def test_shr_digit(a = 0, digits = 0, expected_error = Error.Okay): else: expected_result = a >> (digits * 60) - return test("test_shr_digit", res, [a, digits], expected_error, expected_result) + return test("test_shr_leg", res, [a, digits], expected_error, expected_result) def test_shl(a = 0, bits = 0, expected_error = Error.Okay): args = [arg_to_odin(a), bits] @@ -556,12 +556,12 @@ TESTS = { test_root_n: [ [ 1298074214633706907132624082305024, 2, Error.Okay, ], ], - test_shl_digit: [ + test_shl_leg: [ [ 3192, 1 ], [ 1298074214633706907132624082305024, 2 ], [ 1024, 3 ], ], - test_shr_digit: [ + test_shr_leg: [ [ 3680125442705055547392, 1 ], [ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ], [ 219504133884436710204395031992179571, 2 ], @@ -619,10 +619,10 @@ total_failures = 0 # test_shr_signed also tests shr, so we're not going to test shr randomly. # RANDOM_TESTS = [ - test_add, test_sub, test_mul, test_sqr, test_div, - test_log, test_pow, test_sqrt, test_root_n, - test_shl_digit, test_shr_digit, test_shl, test_shr_signed, - test_gcd, test_lcm, test_is_square, + test_add, test_sub, test_mul, test_sqr, + test_log, test_pow, test_sqrt, test_root_n, + test_shl_leg, test_shr_leg, test_shl, test_shr_signed, + test_gcd, test_lcm, test_is_square, test_div, ] SKIP_LARGE = [ test_pow, test_root_n, # test_gcd, @@ -719,9 +719,9 @@ if __name__ == '__main__': a = randint(1, 1 << BITS) b = TEST_ROOT_N_PARAMS[index] index = (index + 1) % len(TEST_ROOT_N_PARAMS) - elif test_proc == test_shl_digit: + elif test_proc == test_shl_leg: b = randint(0, 10); - elif test_proc == test_shr_digit: + elif test_proc == test_shr_leg: a = abs(a) b = randint(0, 10); elif test_proc == test_shl: