diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 9498e473c..39aa3bbfd 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -149,7 +149,8 @@ internal_add_signed :: proc { internal_int_add_signed, }; `dest` and `a` != `nil` and have been initalized. `dest` is large enough (a.used + 1) to fit result. */ -internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) { +internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { + if err = internal_grow(dest, a.used + 1, false, allocator); err != nil { return err; } /* Fast paths for destination and input Int being the same. */ @@ -183,7 +184,7 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) { /* dest = |a| - digit */ - if err = #force_inline internal_int_add_digit(dest, a, digit); err != nil { + if err = #force_inline internal_int_add_digit(dest, a, digit, allocator); err != nil { /* Restore a's sign. */ @@ -367,7 +368,9 @@ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := conte `dest`, `number` != `nil` and have been initalized. `dest` is large enough (number.used + 1) to fit result. */ -internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT) -> (err: Error) { +internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { + if err = internal_grow(dest, number.used + 1, false, allocator); err != nil { return err; } + dest := dest; digit := digit; /* All parameters have been initialized. @@ -1630,7 +1633,7 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al src := src; if err = error_if_immutable(dest); err != nil { return err; } - if err = clear_if_uninitialized(dest); err != nil { return err; } + if err = internal_clear_if_uninitialized_single(dest); err != nil { return err; } dest.flags = {}; // We're not -Inf, Inf, NaN or Immutable. @@ -1659,7 +1662,7 @@ internal_int_copy :: proc(dest, src: ^Int, minimize := false, allocator := conte if (dest == src) { return nil; } if err = error_if_immutable(dest); err != nil { return err; } - if err = clear_if_uninitialized(src); err != nil { return err; } + if err = internal_clear_if_uninitialized_single(src); err != nil { return err; } /* Grow `dest` to fit `src`. @@ -1707,7 +1710,7 @@ internal_int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (er /* Check that src is usable. */ - if err = clear_if_uninitialized(src); err != nil { + if err = internal_clear_if_uninitialized_single(src); err != nil { return err; } /* @@ -1744,7 +1747,7 @@ internal_int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (er /* Check that src is usable. */ - if err = clear_if_uninitialized(src); err != nil { + if err = internal_clear_if_uninitialized_single(src); err != nil { return err; } /* @@ -1788,7 +1791,7 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR /* Check that `a` is usable. */ - if err = clear_if_uninitialized(a); err != nil { return 0, err; } + if err = internal_clear_if_uninitialized_single(a); err != nil { return 0, err; } /* Early out for single bit. */ @@ -2046,7 +2049,7 @@ internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intr internal_get :: proc { internal_int_get, }; internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { - if err = clear_if_uninitialized(a); err != nil { + if err = internal_clear_if_uninitialized_single(a); err != nil { return 0, err; } @@ -2062,11 +2065,410 @@ internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { return; } +/* + The `and`, `or` and `xor` binops differ in two lines only. + We could handle those with a switch, but that adds overhead. + + TODO: Implement versions that take a DIGIT immediate. +*/ + +/* + 2's complement `and`, returns `dest = a & b;` +*/ +internal_int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { + used := max(a.used, b.used) + 1; + /* + Grow the destination to accomodate the result. + */ + if err = internal_grow(dest, used, false, allocator); err != nil { return err; } + + neg_a, _ := is_neg(a); + neg_b, _ := is_neg(b); + neg := neg_a && neg_b; + + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + + for i := 0; i < used; i += 1 { + x, y: DIGIT; + + /* + Convert to 2's complement if negative. + */ + if neg_a { + ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); + x = ac & _MASK; + ac >>= _DIGIT_BITS; + } else { + x = 0 if i >= a.used else a.digit[i]; + } + + /* + Convert to 2's complement if negative. + */ + if neg_b { + bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); + y = bc & _MASK; + bc >>= _DIGIT_BITS; + } else { + y = 0 if i >= b.used else b.digit[i]; + } + + dest.digit[i] = x & y; + + /* + Convert to to sign-magnitude if negative. + */ + if neg { + cc += ~dest.digit[i] & _MASK; + dest.digit[i] = cc & _MASK; + cc >>= _DIGIT_BITS; + } + } + + dest.used = used; + dest.sign = .Negative if neg else .Zero_or_Positive; + return clamp(dest); +} +internal_and :: proc { internal_int_and, }; + +/* + 2's complement `or`, returns `dest = a | b;` +*/ +internal_int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { + used := max(a.used, b.used) + 1; + /* + Grow the destination to accomodate the result. + */ + if err = grow(dest, used, false, allocator); err != nil { return err; } + + neg_a, _ := is_neg(a); + neg_b, _ := is_neg(b); + neg := neg_a || neg_b; + + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + + for i := 0; i < used; i += 1 { + x, y: DIGIT; + + /* + Convert to 2's complement if negative. + */ + if neg_a { + ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); + x = ac & _MASK; + ac >>= _DIGIT_BITS; + } else { + x = 0 if i >= a.used else a.digit[i]; + } + + /* + Convert to 2's complement if negative. + */ + if neg_b { + bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); + y = bc & _MASK; + bc >>= _DIGIT_BITS; + } else { + y = 0 if i >= b.used else b.digit[i]; + } + + dest.digit[i] = x | y; + + /* + Convert to to sign-magnitude if negative. + */ + if neg { + cc += ~dest.digit[i] & _MASK; + dest.digit[i] = cc & _MASK; + cc >>= _DIGIT_BITS; + } + } + + dest.used = used; + dest.sign = .Negative if neg else .Zero_or_Positive; + return clamp(dest); +} +internal_or :: proc { internal_int_or, }; + +/* + 2's complement `xor`, returns `dest = a ~ b;` +*/ +internal_int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { + used := max(a.used, b.used) + 1; + /* + Grow the destination to accomodate the result. + */ + if err = grow(dest, used, false, allocator); err != nil { return err; } + + neg_a, _ := is_neg(a); + neg_b, _ := is_neg(b); + neg := neg_a != neg_b; + + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + + for i := 0; i < used; i += 1 { + x, y: DIGIT; + + /* + Convert to 2's complement if negative. + */ + if neg_a { + ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); + x = ac & _MASK; + ac >>= _DIGIT_BITS; + } else { + x = 0 if i >= a.used else a.digit[i]; + } + + /* + Convert to 2's complement if negative. + */ + if neg_b { + bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); + y = bc & _MASK; + bc >>= _DIGIT_BITS; + } else { + y = 0 if i >= b.used else b.digit[i]; + } + + dest.digit[i] = x ~ y; + + /* + Convert to to sign-magnitude if negative. + */ + if neg { + cc += ~dest.digit[i] & _MASK; + dest.digit[i] = cc & _MASK; + cc >>= _DIGIT_BITS; + } + } + + dest.used = used; + dest.sign = .Negative if neg else .Zero_or_Positive; + return clamp(dest); +} +internal_xor :: proc { internal_int_xor, }; + +/* + dest = ~src +*/ +internal_int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { + /* + Temporarily fix sign. + */ + old_sign := src.sign; + z, _ := is_zero(src); + + src.sign = .Negative if (src.sign == .Zero_or_Positive || z) else .Zero_or_Positive; + + err = internal_sub(dest, src, 1); + /* + Restore sign. + */ + src.sign = old_sign; + + return err; +} +internal_complement :: proc { internal_int_complement, }; + +/* + quotient, remainder := numerator >> bits; + `remainder` is allowed to be passed a `nil`, in which case `mod` won't be computed. +*/ +internal_int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + bits := bits; + if bits < 0 { return .Invalid_Argument; } + + if err = internal_copy(quotient, numerator, true, allocator); err != nil { return err; } + + /* + Shift right by a certain bit count (store quotient and optional remainder.) + `numerator` should not be used after this. + */ + if remainder != nil { + if err = mod_bits(remainder, numerator, bits); err != nil { return err; } + } + + /* + Shift by as many digits in the bit count. + */ + if bits >= _DIGIT_BITS { + if err = shr_digit(quotient, bits / _DIGIT_BITS); err != nil { return err; } + } + + /* + Shift any bit count < _DIGIT_BITS. + */ + bits %= _DIGIT_BITS; + if bits != 0 { + mask := DIGIT(1 << uint(bits)) - 1; + shift := DIGIT(_DIGIT_BITS - bits); + carry := DIGIT(0); + + for x := quotient.used - 1; x >= 0; x -= 1 { + /* + Get the lower bits of this word in a temp. + */ + fwd_carry := quotient.digit[x] & mask; + + /* + Shift the current word and mix in the carry bits from the previous word. + */ + quotient.digit[x] = (quotient.digit[x] >> uint(bits)) | (carry << shift); + + /* + Update carry from forward carry. + */ + carry = fwd_carry; + } + + } + return clamp(numerator); +} +internal_shrmod :: proc { internal_int_shrmod, }; + +internal_int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + return internal_shrmod(dest, nil, source, bits, allocator); +} +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) { + if digits <= 0 { return nil; } + + /* + If digits > used simply zero and return. + */ + if digits > quotient.used { + return internal_zero(quotient, true, allocator); + } + + /* + 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 | ----> + /\ | ----> + \-------------------/ ----> + */ + + for x := 0; x < (quotient.used - digits); x += 1 { + quotient.digit[x] = quotient.digit[x + digits]; + } + quotient.used -= digits; + zero_unused(quotient); + return clamp(quotient); +} +internal_shr_digit :: proc { internal_int_shr_digit, }; + +/* + Shift right by a certain bit count with sign extension. +*/ +internal_int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + if src.sign == .Zero_or_Positive { + return internal_shr(dest, src, bits, allocator); + } + if err = internal_int_add_digit(dest, src, DIGIT(1), allocator); err != nil { return err; } + + if err = internal_shr(dest, dest, bits, allocator); err != nil { return err; } + return internal_sub(dest, src, DIGIT(1), allocator); +} + +internal_shr_signed :: proc { internal_int_shr_signed, }; + +/* + Shift left by a certain bit count. +*/ +internal_int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + bits := bits; + + if bits < 0 { return .Invalid_Argument; } + + if err = copy(dest, src, false, allocator); err != nil { return err; } + + /* + Grow `dest` to accommodate the additional bits. + */ + digits_needed := dest.used + (bits / _DIGIT_BITS) + 1; + if err = grow(dest, digits_needed); err != nil { return err; } + dest.used = digits_needed; + /* + Shift by as many digits in the bit count as we have. + */ + if bits >= _DIGIT_BITS { + if err = shl_digit(dest, bits / _DIGIT_BITS); err != nil { return err; } + } + + /* + Shift any remaining bit count < _DIGIT_BITS + */ + bits %= _DIGIT_BITS; + if bits != 0 { + mask := (DIGIT(1) << uint(bits)) - DIGIT(1); + shift := DIGIT(_DIGIT_BITS - bits); + carry := DIGIT(0); + + for x:= 0; x < dest.used; x+= 1 { + fwd_carry := (dest.digit[x] >> shift) & mask; + dest.digit[x] = (dest.digit[x] << uint(bits) | carry) & _MASK; + carry = fwd_carry; + } + + /* + Use final carry. + */ + if carry != 0 { + dest.digit[dest.used] = carry; + dest.used += 1; + } + } + return clamp(dest); +} +internal_shl :: proc { internal_int_shl, }; + + +/* + Shift left by `digits` * _DIGIT_BITS bits. +*/ +internal_int_shl_digit :: proc(quotient: ^Int, digits: int) -> (err: Error) { + if digits <= 0 { return nil; } + + /* + No need to shift a zero. + */ + z: bool; + if z, err = is_zero(quotient); z || err != nil { return err; } + + /* + Resize `quotient` to accomodate extra digits. + */ + if err = grow(quotient, quotient.used + digits); err != nil { return err; } + + /* + 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. + */ + 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`. */ internal_count_bits :: proc(a: ^Int) -> (count: int, err: Error) { - if err = clear_if_uninitialized(a); err != nil { + if err = internal_clear_if_uninitialized_single(a); err != nil { return 0, err; } /* @@ -2092,7 +2494,7 @@ internal_count_bits :: proc(a: ^Int) -> (count: int, err: Error) { Differs from regular `ctz` in that 0 returns 0. */ internal_int_count_lsb :: proc(a: ^Int) -> (count: int, err: Error) { - if err = clear_if_uninitialized(a); err != nil { return -1, err; } + if err = internal_clear_if_uninitialized_single(a); err != nil { return -1, err; } _ctz :: intrinsics.count_trailing_zeros; /* @@ -2163,7 +2565,7 @@ internal_assert_initialized :: proc(a: ^Int, loc := #caller_location) { } internal_clear_if_uninitialized_single :: proc(arg: ^Int, allocator := context.allocator) -> (err: Error) { - if !internal_is_initialized(arg) { + if ! #force_inline internal_is_initialized(arg) { return #force_inline internal_grow(arg, _DEFAULT_DIGIT_COUNT, true, allocator); } return err; @@ -2171,7 +2573,7 @@ internal_clear_if_uninitialized_single :: proc(arg: ^Int, allocator := context.a internal_clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocator) -> (err: Error) { for i in args { - if !internal_is_initialized(i) { + if ! #force_inline internal_is_initialized(i) { e := #force_inline internal_grow(i, _DEFAULT_DIGIT_COUNT, true, allocator); if e != nil { err = e; } } @@ -2208,8 +2610,8 @@ internal_init_multi :: proc { internal_int_init_multi, }; _private_copy_digits :: proc(dest, src: ^Int, digits: int) -> (err: Error) { digits := digits; - if err = clear_if_uninitialized(src); err != nil { return err; } - if err = clear_if_uninitialized(dest); err != nil { return err; } + if err = internal_clear_if_uninitialized_single(src); err != nil { return err; } + if err = internal_clear_if_uninitialized_single(dest); err != nil { return err; } /* If dest == src, do nothing */ @@ -2229,7 +2631,7 @@ _private_copy_digits :: proc(dest, src: ^Int, digits: int) -> (err: Error) { Typically very fast. Also fixes the sign if there are no more leading digits. */ internal_clamp :: proc(a: ^Int) -> (err: Error) { - if err = internal_clear_if_uninitialized(a); err != nil { + if err = internal_clear_if_uninitialized_single(a); err != nil { return err; } for a.used > 0 && a.digit[a.used - 1] == 0 { diff --git a/core/math/big/logical.odin b/core/math/big/logical.odin index 0ab9e2f9b..57adf6f1e 100644 --- a/core/math/big/logical.odin +++ b/core/math/big/logical.odin @@ -23,210 +23,48 @@ import "core:mem" /* 2's complement `and`, returns `dest = a & b;` */ -int_and :: proc(dest, a, b: ^Int) -> (err: Error) { +int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, a, b); - if err = clear_if_uninitialized(a, b); err != nil { return err; } + if err = internal_clear_if_uninitialized(a, b); err != nil { return err; } - used := max(a.used, b.used) + 1; - /* - Grow the destination to accomodate the result. - */ - if err = grow(dest, used); err != nil { return err; } - - neg_a, _ := is_neg(a); - neg_b, _ := is_neg(b); - neg := neg_a && neg_b; - - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); - - for i := 0; i < used; i += 1 { - x, y: DIGIT; - - /* - Convert to 2's complement if negative. - */ - if neg_a { - ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); - x = ac & _MASK; - ac >>= _DIGIT_BITS; - } else { - x = 0 if i >= a.used else a.digit[i]; - } - - /* - Convert to 2's complement if negative. - */ - if neg_b { - bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); - y = bc & _MASK; - bc >>= _DIGIT_BITS; - } else { - y = 0 if i >= b.used else b.digit[i]; - } - - dest.digit[i] = x & y; - - /* - Convert to to sign-magnitude if negative. - */ - if neg { - cc += ~dest.digit[i] & _MASK; - dest.digit[i] = cc & _MASK; - cc >>= _DIGIT_BITS; - } - } - - dest.used = used; - dest.sign = .Negative if neg else .Zero_or_Positive; - return clamp(dest); + return #force_inline internal_int_and(dest, a, b, allocator); } -and :: proc { int_add, }; +and :: proc { int_and, }; /* 2's complement `or`, returns `dest = a | b;` */ -int_or :: proc(dest, a, b: ^Int) -> (err: Error) { - if err = clear_if_uninitialized(a, b); err != nil { return err; } - used := max(a.used, b.used) + 1; - /* - Grow the destination to accomodate the result. - */ - if err = grow(dest, used); err != nil { return err; } +int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { + assert_if_nil(dest, a, b); + if err = internal_clear_if_uninitialized(a, b); err != nil { return err; } - neg_a, _ := is_neg(a); - neg_b, _ := is_neg(b); - neg := neg_a || neg_b; - - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); - - for i := 0; i < used; i += 1 { - x, y: DIGIT; - - /* - Convert to 2's complement if negative. - */ - if neg_a { - ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); - x = ac & _MASK; - ac >>= _DIGIT_BITS; - } else { - x = 0 if i >= a.used else a.digit[i]; - } - - /* - Convert to 2's complement if negative. - */ - if neg_b { - bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); - y = bc & _MASK; - bc >>= _DIGIT_BITS; - } else { - y = 0 if i >= b.used else b.digit[i]; - } - - dest.digit[i] = x | y; - - /* - Convert to to sign-magnitude if negative. - */ - if neg { - cc += ~dest.digit[i] & _MASK; - dest.digit[i] = cc & _MASK; - cc >>= _DIGIT_BITS; - } - } - - dest.used = used; - dest.sign = .Negative if neg else .Zero_or_Positive; - return clamp(dest); + return #force_inline internal_int_or(dest, a, b, allocator); } or :: proc { int_or, }; /* - 2's complement `xor`, returns `dest = a ~ b;` + 2's complement `xor`, returns `dest = a ^ b;` */ -int_xor :: proc(dest, a, b: ^Int) -> (err: Error) { - if err = clear_if_uninitialized(a, b); err != nil { return err; } +int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { + assert_if_nil(dest, a, b); + if err = internal_clear_if_uninitialized(a, b); err != nil { return err; } - used := max(a.used, b.used) + 1; - /* - Grow the destination to accomodate the result. - */ - if err = grow(dest, used); err != nil { return err; } - - neg_a, _ := is_neg(a); - neg_b, _ := is_neg(b); - neg := neg_a != neg_b; - - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); - - for i := 0; i < used; i += 1 { - x, y: DIGIT; - - /* - Convert to 2's complement if negative. - */ - if neg_a { - ac += _MASK if i >= a.used else (~a.digit[i] & _MASK); - x = ac & _MASK; - ac >>= _DIGIT_BITS; - } else { - x = 0 if i >= a.used else a.digit[i]; - } - - /* - Convert to 2's complement if negative. - */ - if neg_b { - bc += _MASK if i >= b.used else (~b.digit[i] & _MASK); - y = bc & _MASK; - bc >>= _DIGIT_BITS; - } else { - y = 0 if i >= b.used else b.digit[i]; - } - - dest.digit[i] = x ~ y; - - /* - Convert to to sign-magnitude if negative. - */ - if neg { - cc += ~dest.digit[i] & _MASK; - dest.digit[i] = cc & _MASK; - cc >>= _DIGIT_BITS; - } - } - - dest.used = used; - dest.sign = .Negative if neg else .Zero_or_Positive; - return clamp(dest); + return #force_inline internal_int_xor(dest, a, b, allocator); } xor :: proc { int_xor, }; /* dest = ~src */ -int_complement :: proc(dest, src: ^Int) -> (err: Error) { +int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { /* - Check that src is usable. Dest will get checked by `sub`. + Check that `src` and `dest` are usable. */ - if err = clear_if_uninitialized(src); err != nil { return err; } + assert_if_nil(dest, src); + if err = internal_clear_if_uninitialized(dest, allocator); err != nil { return err; } + if err = internal_clear_if_uninitialized(src, allocator); err != nil { return err; } - /* - Temporarily fix sign. - */ - old_sign := src.sign; - z, _ := is_zero(src); - - src.sign = .Negative if (src.sign == .Zero_or_Positive || z) else .Zero_or_Positive; - - err = sub(dest, src, 1); - /* - Restore sign. - */ - src.sign = old_sign; - - return err; + return #force_inline internal_int_complement(dest, src); } complement :: proc { int_complement, }; @@ -234,115 +72,43 @@ complement :: proc { int_complement, }; quotient, remainder := numerator >> bits; `remainder` is allowed to be passed a `nil`, in which case `mod` won't be computed. */ -int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int) -> (err: Error) { - bits := bits; - if err = clear_if_uninitialized(quotient, numerator); err != nil { return err; } +int_shrmod :: proc(quotient, remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + assert_if_nil(quotient, numerator); + if err = internal_clear_if_uninitialized(quotient, allocator); err != nil { return err; } + if err = internal_clear_if_uninitialized(numerator, allocator); err != nil { return err; } - if bits < 0 { return .Invalid_Argument; } - - if err = copy(quotient, numerator); err != nil { return err; } - - /* - Shift right by a certain bit count (store quotient and optional remainder.) - `numerator` should not be used after this. - */ - if remainder != nil { - if err = mod_bits(remainder, numerator, bits); err != nil { return err; } - } - - /* - Shift by as many digits in the bit count. - */ - if bits >= _DIGIT_BITS { - if err = shr_digit(quotient, bits / _DIGIT_BITS); err != nil { return err; } - } - - /* - Shift any bit count < _DIGIT_BITS. - */ - bits %= _DIGIT_BITS; - if bits != 0 { - mask := DIGIT(1 << uint(bits)) - 1; - shift := DIGIT(_DIGIT_BITS - bits); - carry := DIGIT(0); - - for x := quotient.used - 1; x >= 0; x -= 1 { - /* - Get the lower bits of this word in a temp. - */ - fwd_carry := quotient.digit[x] & mask; - - /* - Shift the current word and mix in the carry bits from the previous word. - */ - quotient.digit[x] = (quotient.digit[x] >> uint(bits)) | (carry << shift); - - /* - Update carry from forward carry. - */ - carry = fwd_carry; - } - - } - return clamp(numerator); + return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits, allocator); } shrmod :: proc { int_shrmod, }; int_shr :: proc(dest, source: ^Int, bits: int) -> (err: Error) { - return shrmod(dest, nil, source, bits); + return #force_inline shrmod(dest, nil, source, bits); } shr :: proc { int_shr, }; /* Shift right by `digits` * _DIGIT_BITS bits. */ -int_shr_digit :: proc(quotient: ^Int, digits: int) -> (err: Error) { +int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) { /* Check that `quotient` is usable. */ - if err = clear_if_uninitialized(quotient); err != nil { return err; } + assert_if_nil(quotient); + if err = internal_clear_if_uninitialized(quotient, allocator); err != nil { return err; } - if digits <= 0 { return nil; } - - /* - If digits > used simply zero and return. - */ - if digits > quotient.used { - return 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 | ----> - /\ | ----> - \-------------------/ ----> - */ - - for x := 0; x < (quotient.used - digits); x += 1 { - quotient.digit[x] = quotient.digit[x + digits]; - } - quotient.used -= digits; - zero_unused(quotient); - return clamp(quotient); + return #force_inline internal_int_shr_digit(quotient, digits, allocator); } shr_digit :: proc { int_shr_digit, }; /* Shift right by a certain bit count with sign extension. */ -int_shr_signed :: proc(dest, src: ^Int, bits: int) -> (err: Error) { - if err = clear_if_uninitialized(src); err != nil { return err; } - if err = clear_if_uninitialized(dest); err != nil { return err; } +int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + assert_if_nil(dest, src); + if err = internal_clear_if_uninitialized(dest, allocator); err != nil { return err; } + if err = internal_clear_if_uninitialized(src, allocator); err != nil { return err; } - if src.sign == .Zero_or_Positive { - return shr(dest, src, bits); - } - if err = add(dest, src, DIGIT(1)); err != nil { return err; } - - if err = shr(dest, dest, bits); err != nil { return err; } - return sub(dest, src, DIGIT(1)); + return #force_inline internal_int_shr_signed(dest, src, bits); } shr_signed :: proc { int_shr_signed, }; @@ -350,53 +116,12 @@ shr_signed :: proc { int_shr_signed, }; /* Shift left by a certain bit count. */ -int_shl :: proc(dest, src: ^Int, bits: int) -> (err: Error) { - bits := bits; - if err = clear_if_uninitialized(src, dest); err != nil { return err; } +int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { + assert_if_nil(dest, src); + if err = internal_clear_if_uninitialized(dest, allocator); err != nil { return err; } + if err = internal_clear_if_uninitialized(src, allocator); err != nil { return err; } - if bits < 0 { - return .Invalid_Argument; - } - - if err = copy(dest, src); err != nil { return err; } - - /* - Grow `dest` to accommodate the additional bits. - */ - digits_needed := dest.used + (bits / _DIGIT_BITS) + 1; - if err = grow(dest, digits_needed); err != nil { return err; } - dest.used = digits_needed; - /* - Shift by as many digits in the bit count as we have. - */ - if bits >= _DIGIT_BITS { - if err = shl_digit(dest, bits / _DIGIT_BITS); err != nil { return err; } - } - - /* - Shift any remaining bit count < _DIGIT_BITS - */ - bits %= _DIGIT_BITS; - if bits != 0 { - mask := (DIGIT(1) << uint(bits)) - DIGIT(1); - shift := DIGIT(_DIGIT_BITS - bits); - carry := DIGIT(0); - - for x:= 0; x < dest.used; x+= 1 { - fwd_carry := (dest.digit[x] >> shift) & mask; - dest.digit[x] = (dest.digit[x] << uint(bits) | carry) & _MASK; - carry = fwd_carry; - } - - /* - Use final carry. - */ - if carry != 0 { - dest.digit[dest.used] = carry; - dest.used += 1; - } - } - return clamp(dest); + return #force_inline internal_int_shl(dest, src, bits); } shl :: proc { int_shl, }; @@ -408,35 +133,9 @@ int_shl_digit :: proc(quotient: ^Int, digits: int) -> (err: Error) { /* Check that `quotient` is usable. */ - if err = clear_if_uninitialized(quotient); err != nil { return err; } + assert_if_nil(quotient); + if err = internal_clear_if_uninitialized(quotient); err != nil { return err; } - if digits <= 0 { return nil; } - - /* - No need to shift a zero. - */ - z: bool; - if z, err = is_zero(quotient); z || err != nil { return err; } - - /* - Resize `quotient` to accomodate extra digits. - */ - if err = grow(quotient, quotient.used + digits); err != nil { return err; } - - /* - 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. - */ - 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; + return #force_inline internal_int_shl_digit(quotient, digits); } shl_digit :: proc { int_shl_digit, }; \ No newline at end of file diff --git a/core/math/big/prime.odin b/core/math/big/prime.odin index 355feecc2..7041b8c39 100644 --- a/core/math/big/prime.odin +++ b/core/math/big/prime.odin @@ -15,11 +15,13 @@ package big Determines if an Integer is divisible by one of the _PRIME_TABLE primes. Returns true if it is, false if not. */ -int_prime_is_divisible :: proc(a: ^Int) -> (res: bool, err: Error) { +int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) { + assert_if_nil(a); + if err = internal_clear_if_uninitialized(a, allocator); err != nil { return {}, err; } rem: DIGIT; for prime in _private_prime_table { - if rem, err = mod(a, prime); err != nil { return false, err; } + if rem, err = #force_inline int_mod_digit(a, prime); err != nil { return false, err; } if rem == 0 { return true, nil; } } /* diff --git a/core/math/big/public.odin b/core/math/big/public.odin index fdb7bcbd5..f5dbbe06d 100644 --- a/core/math/big/public.odin +++ b/core/math/big/public.odin @@ -22,7 +22,7 @@ package big */ int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, a, b); - if err = clear_if_uninitialized(dest, a, b); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, a, b); err != nil { return err; } /* All parameters have been initialized. */ @@ -37,7 +37,7 @@ int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error */ int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, a); - if err = clear_if_uninitialized(a); err != nil { return err; } + if err = internal_clear_if_uninitialized(a); err != nil { return err; } /* Grow destination as required. */ @@ -54,7 +54,7 @@ int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocato */ int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, number, decrease); - if err = clear_if_uninitialized(dest, number, decrease); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, number, decrease); err != nil { return err; } /* All parameters have been initialized. */ @@ -69,7 +69,7 @@ int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> */ int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, a); - if err = clear_if_uninitialized(a); err != nil { return err; } + if err = internal_clear_if_uninitialized(a); err != nil { return err; } /* Grow destination as required. */ @@ -87,7 +87,7 @@ int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocato */ int_halve :: proc(dest, src: ^Int) -> (err: Error) { assert_if_nil(dest, src); - if err = clear_if_uninitialized(dest, src); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; } /* Grow destination as required. */ @@ -104,7 +104,7 @@ shr1 :: halve; */ int_double :: proc(dest, src: ^Int) -> (err: Error) { assert_if_nil(dest, src); - if err = clear_if_uninitialized(dest, src); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; } /* Grow destination as required. */ @@ -120,7 +120,7 @@ shl1 :: double; */ int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, src); - if err = clear_if_uninitialized(src, dest); err != nil { return err; } + if err = internal_clear_if_uninitialized(src, dest); err != nil { return err; } return #force_inline internal_int_mul_digit(dest, src, multiplier, allocator); } @@ -130,7 +130,7 @@ int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.a */ int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) -> (err: Error) { assert_if_nil(dest, src, multiplier); - if err = clear_if_uninitialized(dest, src, multiplier); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, src, multiplier); err != nil { return err; } return #force_inline internal_int_mul(dest, src, multiplier, allocator); } @@ -148,14 +148,14 @@ int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: E Early out if neither of the results is wanted. */ if quotient == nil && remainder == nil { return nil; } - if err = clear_if_uninitialized(numerator, denominator); err != nil { return err; } + if err = internal_clear_if_uninitialized(numerator, denominator); err != nil { return err; } return #force_inline internal_divmod(quotient, remainder, numerator, denominator); } int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT) -> (remainder: DIGIT, err: Error) { assert_if_nil(quotient, numerator); - if err = clear_if_uninitialized(numerator); err != nil { return 0, err; } + if err = internal_clear_if_uninitialized(numerator); err != nil { return 0, err; } return #force_inline internal_divmod(quotient, numerator, denominator); } @@ -163,14 +163,14 @@ divmod :: proc{ int_divmod, int_divmod_digit, }; int_div :: proc(quotient, numerator, denominator: ^Int) -> (err: Error) { assert_if_nil(quotient, numerator, denominator); - if err = clear_if_uninitialized(numerator, denominator); err != nil { return err; } + if err = internal_clear_if_uninitialized(numerator, denominator); err != nil { return err; } return #force_inline internal_divmod(quotient, nil, numerator, denominator); } int_div_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT) -> (err: Error) { assert_if_nil(quotient, numerator); - if err = clear_if_uninitialized(numerator); err != nil { return err; } + if err = internal_clear_if_uninitialized(numerator); err != nil { return err; } remainder: DIGIT; remainder, err = #force_inline internal_divmod(quotient, numerator, denominator); @@ -185,7 +185,7 @@ div :: proc { int_div, int_div_digit, }; */ int_mod :: proc(remainder, numerator, denominator: ^Int) -> (err: Error) { assert_if_nil(remainder, numerator, denominator); - if err = clear_if_uninitialized(numerator, denominator); err != nil { return err; } + if err = internal_clear_if_uninitialized(numerator, denominator); err != nil { return err; } return #force_inline internal_int_mod(remainder, numerator, denominator); } @@ -201,7 +201,7 @@ mod :: proc { int_mod, int_mod_digit, }; */ int_addmod :: proc(remainder, number, addend, modulus: ^Int) -> (err: Error) { assert_if_nil(remainder, number, addend); - if err = clear_if_uninitialized(number, addend, modulus); err != nil { return err; } + if err = internal_clear_if_uninitialized(number, addend, modulus); err != nil { return err; } return #force_inline internal_addmod(remainder, number, addend, modulus); } @@ -212,7 +212,7 @@ addmod :: proc { int_addmod, }; */ int_submod :: proc(remainder, number, decrease, modulus: ^Int) -> (err: Error) { assert_if_nil(remainder, number, decrease); - if err = clear_if_uninitialized(number, decrease, modulus); err != nil { return err; } + if err = internal_clear_if_uninitialized(number, decrease, modulus); err != nil { return err; } return #force_inline internal_submod(remainder, number, decrease, modulus); } @@ -223,7 +223,7 @@ submod :: proc { int_submod, }; */ int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int) -> (err: Error) { assert_if_nil(remainder, number, multiplicand); - if err = clear_if_uninitialized(number, multiplicand, modulus); err != nil { return err; } + if err = internal_clear_if_uninitialized(number, multiplicand, modulus); err != nil { return err; } return #force_inline internal_mulmod(remainder, number, multiplicand, modulus); } @@ -234,7 +234,7 @@ mulmod :: proc { int_mulmod, }; */ int_sqrmod :: proc(remainder, number, modulus: ^Int) -> (err: Error) { assert_if_nil(remainder, number, modulus); - if err = clear_if_uninitialized(number, modulus); err != nil { return err; } + if err = internal_clear_if_uninitialized(number, modulus); err != nil { return err; } return #force_inline internal_sqrmod(remainder, number, modulus); } @@ -295,8 +295,8 @@ int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator if res_gcd == nil && res_lcm == nil { return nil; } assert_if_nil(a, b); - if err = clear_if_uninitialized(a, allocator); err != nil { return err; } - if err = clear_if_uninitialized(b, allocator); err != nil { return err; } + if err = internal_clear_if_uninitialized(a, allocator); err != nil { return err; } + if err = internal_clear_if_uninitialized(b, allocator); err != nil { return err; } return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b); } gcd_lcm :: proc { int_gcd_lcm, }; @@ -323,7 +323,7 @@ lcm :: proc { int_lcm, }; int_mod_bits :: proc(remainder, numerator: ^Int, bits: int) -> (err: Error) { assert_if_nil(remainder, numerator); - if err = clear_if_uninitialized(remainder, numerator); err != nil { return err; } + if err = internal_clear_if_uninitialized(remainder, numerator); err != nil { return err; } if bits < 0 { return .Invalid_Argument; } return #force_inline internal_int_mod_bits(remainder, numerator, bits); @@ -337,7 +337,7 @@ mod_bits :: proc { int_mod_bits, }; */ int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return 0, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return 0, err; } return #force_inline internal_int_log(a, base); } @@ -352,7 +352,7 @@ log :: proc { int_log, digit_log, }; */ int_pow :: proc(dest, base: ^Int, power: int) -> (err: Error) { assert_if_nil(dest, base); - if err = clear_if_uninitialized(dest, base); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, base); err != nil { return err; } return #force_inline internal_int_pow(dest, base, power); } @@ -378,7 +378,7 @@ small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) { */ int_sqrt :: proc(dest, src: ^Int) -> (err: Error) { assert_if_nil(dest, src); - if err = clear_if_uninitialized(dest, src); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; } return #force_inline internal_int_sqrt(dest, src); } @@ -402,7 +402,7 @@ int_root_n :: proc(dest, src: ^Int, n: int) -> (err: Error) { /* Initialize dest + src if needed. */ - if err = clear_if_uninitialized(dest, src); err != nil { return err; } + if err = internal_clear_if_uninitialized(dest, src); err != nil { return err; } return #force_inline internal_int_root_n(dest, src, n); } @@ -420,35 +420,35 @@ int_is_initialized :: proc(a: ^Int) -> bool { int_is_zero :: proc(a: ^Int) -> (zero: bool, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return false, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return false, err; } return #force_inline internal_is_zero(a), nil; } int_is_positive :: proc(a: ^Int) -> (positive: bool, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return false, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return false, err; } return #force_inline internal_is_positive(a), nil; } int_is_negative :: proc(a: ^Int) -> (negative: bool, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return false, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return false, err; } return #force_inline internal_is_negative(a), nil; } int_is_even :: proc(a: ^Int) -> (even: bool, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return false, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return false, err; } return #force_inline internal_is_even(a), nil; } int_is_odd :: proc(a: ^Int) -> (odd: bool, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return false, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return false, err; } return #force_inline internal_is_odd(a), nil; } @@ -459,7 +459,7 @@ platform_int_is_power_of_two :: #force_inline proc(a: int) -> bool { int_is_power_of_two :: proc(a: ^Int) -> (res: bool, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return false, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return false, err; } return #force_inline internal_is_power_of_two(a), nil; } @@ -469,7 +469,7 @@ int_is_power_of_two :: proc(a: ^Int) -> (res: bool, err: Error) { */ int_compare :: proc(a, b: ^Int) -> (comparison: int, err: Error) { assert_if_nil(a, b); - if err = clear_if_uninitialized(a, b); err != nil { return 0, err; } + if err = internal_clear_if_uninitialized(a, b); err != nil { return 0, err; } return #force_inline internal_cmp(a, b), nil; } @@ -480,7 +480,7 @@ int_cmp :: int_compare; */ int_compare_digit :: proc(a: ^Int, b: DIGIT) -> (comparison: int, err: Error) { assert_if_nil(a); - if err = clear_if_uninitialized(a); err != nil { return 0, err; } + if err = internal_clear_if_uninitialized(a); err != nil { return 0, err; } return #force_inline internal_cmp_digit(a, b), nil; } @@ -491,7 +491,7 @@ int_cmp_digit :: int_compare_digit; */ int_compare_magnitude :: proc(a, b: ^Int) -> (res: int, err: Error) { assert_if_nil(a, b); - if err = clear_if_uninitialized(a, b); err != nil { return 0, err; } + if err = internal_clear_if_uninitialized(a, b); err != nil { return 0, err; } return #force_inline internal_cmp_mag(a, b), nil; } \ No newline at end of file diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index eb1bb2dfb..28c5a2559 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -18,10 +18,10 @@ import "core:mem" This version of `itoa` allocates one behalf of the caller. The caller must free the string. */ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, allocator := context.allocator) -> (res: string, err: Error) { + assert_if_nil(a); + a := a; radix := radix; - if err = clear_if_uninitialized(a); err != nil { - return "", err; - } + if err = clear_if_uninitialized(a, allocator); err != nil { return "", err; } /* Radix defaults to 10. */ @@ -61,10 +61,10 @@ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, alloc This version of `itoa` allocates one behalf of the caller. The caller must free the string. */ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocator) -> (res: cstring, err: Error) { + assert_if_nil(a); + a := a; radix := radix; - if err = clear_if_uninitialized(a); err != nil { - return "", err; - } + if err = clear_if_uninitialized(a, allocator); err != nil { return "", err; } /* Radix defaults to 10. */ @@ -96,10 +96,9 @@ int_itoa_cstring :: proc(a: ^Int, radix := i8(-1), allocator := context.allocato and having to perform a buffer overflow check each character. */ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_terminate := false) -> (written: int, err: Error) { + assert_if_nil(a); a := a; radix := radix; size := size; - if err = clear_if_uninitialized(a); err != nil { - return 0, err; - } + if err = clear_if_uninitialized(a); err != nil { return 0, err; } /* Radix defaults to 10. */ @@ -237,27 +236,23 @@ int_to_cstring :: int_itoa_cstring; /* Read a string [ASCII] in a given radix. */ -int_atoi :: proc(res: ^Int, input: string, radix: i8) -> (err: Error) { +int_atoi :: proc(res: ^Int, input: string, radix: i8, allocator := context.allocator) -> (err: Error) { input := input; /* Make sure the radix is ok. */ - if radix < 2 || radix > 64 { - return .Invalid_Argument; - } + if radix < 2 || radix > 64 { return .Invalid_Argument; } /* Set the integer to the default of zero. */ - if err = zero(res); err != nil { return err; } + if err = zero(res, false, allocator); err != nil { return err; } /* We'll interpret an empty string as zero. */ - if len(input) == 0 { - return nil; - } + if len(input) == 0 { return nil; } /* If the leading digit is a minus set the sign to negative. @@ -297,8 +292,8 @@ int_atoi :: proc(res: ^Int, input: string, radix: i8) -> (err: Error) { break; } - if err = mul(res, res, DIGIT(radix)); err != nil { return err; } - if err = add(res, res, DIGIT(y)); err != nil { return err; } + if err = internal_mul(res, res, DIGIT(radix)); err != nil { return err; } + if err = internal_add(res, res, DIGIT(y)); err != nil { return err; } input = input[1:]; } diff --git a/core/math/big/test.odin b/core/math/big/test.odin index de536f521..4aa0b93bf 100644 --- a/core/math/big/test.odin +++ b/core/math/big/test.odin @@ -45,9 +45,9 @@ PyRes :: struct { if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":add:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":add:atoi(b):", err=err}; } if bb.used == 1 { - if err = add(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; } + if err = #force_inline internal_add(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; } } else { - if err = add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; } + if err = #force_inline internal_add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; } } r: cstring; @@ -66,9 +66,9 @@ PyRes :: struct { if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":sub:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":sub:atoi(b):", err=err}; } if bb.used == 1 { - if err = sub(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; } + if err = #force_inline internal_sub(sum, aa, bb.digit[0]); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; } } else { - if err = sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; } + if err = #force_inline internal_sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; } } r: cstring; @@ -86,7 +86,7 @@ PyRes :: struct { if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":mul:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":mul:atoi(b):", err=err}; } - if err = mul(product, aa, bb); err != nil { return PyRes{res=":mul:mul(product,a,b):", err=err}; } + if err = #force_inline internal_mul(product, aa, bb); err != nil { return PyRes{res=":mul:mul(product,a,b):", err=err}; } r: cstring; r, err = int_itoa_cstring(product, 16, context.temp_allocator); @@ -106,7 +106,7 @@ PyRes :: struct { if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":div:atoi(a):", err=err}; } if err = atoi(bb, string(b), 16); err != nil { return PyRes{res=":div:atoi(b):", err=err}; } - if err = div(quotient, aa, bb); err != nil { return PyRes{res=":div:div(quotient,a,b):", err=err}; } + if err = #force_inline internal_div(quotient, aa, bb); err != nil { return PyRes{res=":div:div(quotient,a,b):", err=err}; } r: cstring; r, err = int_itoa_cstring(quotient, 16, context.temp_allocator); @@ -127,9 +127,9 @@ PyRes :: struct { defer destroy(aa); if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":log:atoi(a):", err=err}; } - if l, err = log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err}; } + if l, err = #force_inline internal_log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err}; } - zero(aa); + #force_inline internal_zero(aa); aa.digit[0] = DIGIT(l) & _MASK; aa.digit[1] = DIGIT(l) >> _DIGIT_BITS; aa.used = 2; @@ -152,7 +152,7 @@ PyRes :: struct { defer destroy(dest, bb); if err = atoi(bb, string(base), 16); err != nil { return PyRes{res=":pow:atoi(base):", err=err}; } - if err = pow(dest, bb, power); err != nil { return PyRes{res=":pow:pow(dest, base, power):", err=err}; } + if err = #force_inline internal_pow(dest, bb, power); err != nil { return PyRes{res=":pow:pow(dest, base, power):", err=err}; } r: cstring; r, err = int_itoa_cstring(dest, 16, context.temp_allocator); @@ -171,7 +171,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":sqrt:atoi(src):", err=err}; } - if err = sqrt(src, src); err != nil { return PyRes{res=":sqrt:sqrt(src):", err=err}; } + if err = #force_inline internal_sqrt(src, src); err != nil { return PyRes{res=":sqrt:sqrt(src):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -190,7 +190,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":root_n:atoi(src):", err=err}; } - if err = root_n(src, src, power); err != nil { return PyRes{res=":root_n:root_n(src):", err=err}; } + if err = #force_inline internal_root_n(src, src, power); err != nil { return PyRes{res=":root_n:root_n(src):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -209,7 +209,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err}; } - if err = shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err}; } + if err = #force_inline internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -228,7 +228,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err}; } - if err = shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err}; } + if err = #force_inline internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -247,7 +247,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr:atoi(src):", err=err}; } - if err = shr(src, src, bits); err != nil { return PyRes{res=":shr:shr(src, bits):", err=err}; } + if err = #force_inline internal_shr(src, src, bits); err != nil { return PyRes{res=":shr:shr(src, bits):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -266,7 +266,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_signed:atoi(src):", err=err}; } - if err = shr_signed(src, src, bits); err != nil { return PyRes{res=":shr_signed:shr_signed(src, bits):", err=err}; } + if err = #force_inline internal_shr_signed(src, src, bits); err != nil { return PyRes{res=":shr_signed:shr_signed(src, bits):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -285,7 +285,7 @@ PyRes :: struct { defer destroy(src); if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl:atoi(src):", err=err}; } - if err = shl(src, src, bits); err != nil { return PyRes{res=":shl:shl(src, bits):", err=err}; } + if err = #force_inline internal_shl(src, src, bits); err != nil { return PyRes{res=":shl:shl(src, bits):", err=err}; } r: cstring; r, err = int_itoa_cstring(src, 16, context.temp_allocator); @@ -303,7 +303,7 @@ PyRes :: struct { dest := &Int{}; defer destroy(dest); - if err = factorial(dest, n); err != nil { return PyRes{res=":factorial:factorial(n):", err=err}; } + if err = #force_inline factorial(dest, n); err != nil { return PyRes{res=":factorial:factorial(n):", err=err}; } r: cstring; r, err = int_itoa_cstring(dest, 16, context.temp_allocator); @@ -323,7 +323,7 @@ PyRes :: struct { if err = atoi(ai, string(a), 16); err != nil { return PyRes{res=":gcd:atoi(a):", err=err}; } if err = atoi(bi, string(b), 16); err != nil { return PyRes{res=":gcd:atoi(b):", err=err}; } - if err = gcd(dest, ai, bi); err != nil { return PyRes{res=":gcd:gcd(a, b):", err=err}; } + if err = #force_inline gcd(dest, ai, bi); err != nil { return PyRes{res=":gcd:gcd(a, b):", err=err}; } r: cstring; r, err = int_itoa_cstring(dest, 16, context.temp_allocator); @@ -343,7 +343,7 @@ PyRes :: struct { if err = atoi(ai, string(a), 16); err != nil { return PyRes{res=":lcm:atoi(a):", err=err}; } if err = atoi(bi, string(b), 16); err != nil { return PyRes{res=":lcm:atoi(b):", err=err}; } - if err = lcm(dest, ai, bi); err != nil { return PyRes{res=":lcm:lcm(a, b):", err=err}; } + if err = #force_inline lcm(dest, ai, bi); err != nil { return PyRes{res=":lcm:lcm(a, b):", err=err}; } r: cstring; r, err = int_itoa_cstring(dest, 16, context.temp_allocator);