|
@@ -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 {
|