aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorWes Hardee <weshardee@gmail.com>2021-12-18 12:43:33 -0600
committerWes Hardee <weshardee@gmail.com>2021-12-18 12:43:33 -0600
commit92ce7defb12436b81eb1f2c19fa1e01be4a8ead3 (patch)
tree75a9b9c9ad10d7a2b39b05afba2fd88a7a185f0f /core
parenta48317deee95b956430ace83f0db3e34bef590dd (diff)
parent0548db423067bce16d45af651819bf56feb5d411 (diff)
Merge branch 'master' of https://github.com/weshardee/Odin
Diffstat (limited to 'core')
-rw-r--r--core/bytes/bytes.odin2
-rw-r--r--core/math/big/common.odin23
-rw-r--r--core/math/big/internal.odin168
-rw-r--r--core/math/big/logical.odin33
-rw-r--r--core/math/big/private.odin118
-rw-r--r--core/math/big/rat.odin10
-rw-r--r--core/math/math.odin1
-rw-r--r--core/runtime/internal.odin14
-rw-r--r--core/runtime/procs_wasm32.odin41
-rw-r--r--core/strconv/strconv.odin4
-rw-r--r--core/strings/strings.odin6
11 files changed, 236 insertions, 184 deletions
diff --git a/core/bytes/bytes.odin b/core/bytes/bytes.odin
index cbc1e2506..1e83b93c8 100644
--- a/core/bytes/bytes.odin
+++ b/core/bytes/bytes.odin
@@ -1143,7 +1143,7 @@ fields_proc :: proc(s: []byte, f: proc(rune) -> bool, allocator := context.alloc
}
if start >= 0 {
- append(&subslices, s[start : end])
+ append(&subslices, s[start : len(s)])
}
return subslices[:]
diff --git a/core/math/big/common.odin b/core/math/big/common.odin
index 5b7d162bc..31ad54b14 100644
--- a/core/math/big/common.odin
+++ b/core/math/big/common.odin
@@ -158,13 +158,14 @@ Error :: enum int {
Invalid_Pointer = 2,
Invalid_Argument = 3,
- Assignment_To_Immutable = 4,
- Max_Iterations_Reached = 5,
- Buffer_Overflow = 6,
- Integer_Overflow = 7,
+ Assignment_To_Immutable = 10,
+ Max_Iterations_Reached = 11,
+ Buffer_Overflow = 12,
+ Integer_Overflow = 13,
+ Integer_Underflow = 14,
- Division_by_Zero = 8,
- Math_Domain_Error = 9,
+ Division_by_Zero = 30,
+ Math_Domain_Error = 31,
Cannot_Open_File = 50,
Cannot_Read_File = 51,
@@ -215,7 +216,7 @@ _MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS)
/*
Maximum number of digits.
- Must be small enough such that `_bit_count` does not overflow.
- - Must be small enough such that `_radix_size` for base 2 does not overflow.
+ - Must be small enough such that `_radix_size` for base 2 does not overflow.
`_radix_size` needs two additional bytes for zero termination and sign.
*/
_MAX_BIT_COUNT :: (max(int) - 2)
@@ -251,7 +252,7 @@ Order :: enum i8 {
}
Endianness :: enum i8 {
- Little = -1,
- Platform = 0,
- Big = 1,
-}; \ No newline at end of file
+ Little = -1,
+ Platform = 0,
+ Big = 1,
+} \ No newline at end of file
diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin
index 4702e76a3..437f6e5fc 100644
--- a/core/math/big/internal.odin
+++ b/core/math/big/internal.odin
@@ -34,6 +34,7 @@ package math_big
import "core:mem"
import "core:intrinsics"
import rnd "core:math/rand"
+import "core:builtin"
/*
Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7.
@@ -1880,8 +1881,6 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al
where intrinsics.type_is_integer(T) {
context.allocator = allocator
- src := src
-
internal_error_if_immutable(dest) or_return
/*
Most internal procs asssume an Int to have already been initialize,
@@ -1892,13 +1891,27 @@ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, al
dest.flags = {} // We're not -Inf, Inf, NaN or Immutable.
dest.used = 0
- dest.sign = .Zero_or_Positive if src >= 0 else .Negative
- src = internal_abs(src)
+ dest.sign = .Negative if src < 0 else .Zero_or_Positive
+
+ temp := src
+
+ is_maximally_negative := src == min(T)
+ if is_maximally_negative {
+ /*
+ Prevent overflow on abs()
+ */
+ temp += 1
+ }
+ temp = -temp if temp < 0 else temp
- #no_bounds_check for src != 0 {
- dest.digit[dest.used] = DIGIT(src) & _MASK
+ #no_bounds_check for temp != 0 {
+ dest.digit[dest.used] = DIGIT(temp) & _MASK
dest.used += 1
- src >>= _DIGIT_BITS
+ temp >>= _DIGIT_BITS
+ }
+
+ if is_maximally_negative {
+ return internal_sub(dest, dest, 1)
}
internal_zero_unused(dest)
return nil
@@ -2307,29 +2320,70 @@ internal_int_get_i32 :: proc(a: ^Int) -> (res: i32, err: Error) {
}
internal_get_i32 :: proc { internal_int_get_i32, }
+internal_get_low_u32 :: proc(a: ^Int) -> u32 #no_bounds_check {
+ if a == nil {
+ return 0
+ }
+
+ if a.used == 0 {
+ return 0
+ }
+
+ return u32(a.digit[0])
+}
+internal_get_low_u64 :: proc(a: ^Int) -> u64 #no_bounds_check {
+ if a == nil {
+ return 0
+ }
+
+ if a.used == 0 {
+ return 0
+ }
+
+ v := u64(a.digit[0])
+ when size_of(DIGIT) == 4 {
+ if a.used > 1 {
+ return u64(a.digit[1])<<32 | v
+ }
+ }
+ return v
+}
+
/*
TODO: Think about using `count_bits` to check if the value could be returned completely,
and maybe return max(T), .Integer_Overflow if not?
*/
internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intrinsics.type_is_integer(T) {
- size_in_bits := int(size_of(T) * 8)
- i := int((size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS)
- i = min(int(a.used), i)
-
- #no_bounds_check for ; i >= 0; i -= 1 {
- res <<= uint(0) if size_in_bits <= _DIGIT_BITS else _DIGIT_BITS
- res |= T(a.digit[i])
- if size_in_bits <= _DIGIT_BITS {
- break
+ /*
+ Calculate target bit size.
+ */
+ target_bit_size := int(size_of(T) * 8)
+ when !intrinsics.type_is_unsigned(T) {
+ if a.sign == .Zero_or_Positive {
+ target_bit_size -= 1
+ }
+ } else {
+ if a.sign == .Negative {
+ return 0, .Integer_Underflow
+ }
+ }
+
+ bits_used := internal_count_bits(a)
+
+ if bits_used > target_bit_size {
+ if a.sign == .Negative {
+ return min(T), .Integer_Underflow
}
+ return max(T), .Integer_Overflow
+ }
+
+ for i := a.used; i > 0; i -= 1 {
+ res <<= _DIGIT_BITS
+ res |= T(a.digit[i - 1])
}
when !intrinsics.type_is_unsigned(T) {
/*
- Mask off sign bit.
- */
- res ~= 1 << uint(size_in_bits - 1)
- /*
Set the sign.
*/
if a.sign == .Negative { res = -res }
@@ -2594,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
}
/*
@@ -2634,37 +2688,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.
*/
internal_int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
@@ -2702,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
}
/*
@@ -2732,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
@@ -87,21 +87,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.
*/
int_shr_signed :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
@@ -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))<<B */
- internal_shl_digit(x1y1, B * 2) or_return /* x1y1 = x1y1 << 2*B */
+ _private_int_shl_leg(t1, B) or_return /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
+ _private_int_shl_leg(x1y1, B * 2) or_return /* x1y1 = x1y1 << 2*B */
internal_add(t1, x0y0, t1) or_return /* t1 = x0y0 + t1 */
internal_add(dest, t1, x1y1) or_return /* t1 = x0y0 + t1 + x1y1 */
@@ -588,7 +588,7 @@ _private_int_mul_balance :: proc(dest, a, b: ^Int, allocator := context.allocato
/*
Shift `tmp` to the correct position.
*/
- internal_shl_digit(tmp, b_size * i) or_return
+ _private_int_shl_leg(tmp, b_size * i) or_return
/*
Add to output. No carry needed.
@@ -606,7 +606,7 @@ _private_int_mul_balance :: proc(dest, a, b: ^Int, allocator := context.allocato
internal_clamp(a0)
internal_mul(tmp, a0, b) or_return
- internal_shl_digit(tmp, b_size * i) or_return
+ _private_int_shl_leg(tmp, b_size * i) or_return
internal_add(r, r, tmp) or_return
}
@@ -840,8 +840,8 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat
/*
Shift by B.
*/
- internal_shl_digit(t1, B) or_return
- internal_shl_digit(x1x1, B * 2) or_return
+ _private_int_shl_leg(t1, B) or_return
+ _private_int_shl_leg(x1x1, B * 2) or_return
internal_add(t1, t1, x0x0) or_return
internal_add(dest, t1, x1x1) or_return
@@ -942,10 +942,10 @@ _private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) -
internal_sub(dest, dest, S0) or_return
/** \\P = S4*x^4 + S3*x^3 + S2*x^2 + S1*x + S0; */
/** P = a2*x^4 + a1*x^3 + b*x^2 + a0*x + S0; */
- internal_shl_digit( a2, 4 * B) or_return
- internal_shl_digit( a1, 3 * B) or_return
- internal_shl_digit(dest, 2 * B) or_return
- internal_shl_digit( a0, 1 * B) or_return
+ _private_int_shl_leg( a2, 4 * B) or_return
+ _private_int_shl_leg( a1, 3 * B) or_return
+ _private_int_shl_leg(dest, 2 * B) or_return
+ _private_int_shl_leg( a0, 1 * B) or_return
internal_add(a2, a2, a1) or_return
internal_add(dest, dest, a2) or_return
@@ -1069,7 +1069,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
y = y*b**{n-t}
*/
- internal_shl_digit(y, n - t) or_return
+ _private_int_shl_leg(y, n - t) or_return
gte := internal_gte(x, y)
for gte {
@@ -1081,7 +1081,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
/*
Reset y by shifting it back down.
*/
- internal_shr_digit(y, n - t)
+ _private_int_shr_leg(y, n - t)
/*
Step 3. for i from n down to (t + 1).
@@ -1146,7 +1146,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
Step 3.3 x = x - q{i-t-1} * y * b**{i-t-1}
*/
int_mul_digit(t1, y, q.digit[(i - t) - 1]) or_return
- internal_shl_digit(t1, (i - t) - 1) or_return
+ _private_int_shl_leg(t1, (i - t) - 1) or_return
internal_sub(x, x, t1) or_return
/*
@@ -1154,7 +1154,7 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In
*/
if x.sign == .Negative {
internal_copy(t1, y) or_return
- internal_shl_digit(t1, (i - t) - 1) or_return
+ _private_int_shl_leg(t1, (i - t) - 1) or_return
internal_add(x, x, t1) or_return
q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK
@@ -1220,7 +1220,7 @@ _private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := con
/*
A1 = (R1 * beta^(2k)) + (A % beta^(2k)) - (Q1 * B0 * beta^k)
*/
- internal_shl_digit(R1, 2 * k) or_return
+ _private_int_shl_leg(R1, 2 * k) or_return
internal_add(A1, R1, t) or_return
internal_mul(t, Q1, B0) or_return
@@ -1246,7 +1246,7 @@ _private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := con
/*
A2 = (R0*beta^k) + (A1 % beta^k) - (Q0*B0)
*/
- internal_shl_digit(R0, k) or_return
+ _private_int_shl_leg(R0, k) or_return
internal_add(A2, R0, t) or_return
internal_mul(t, Q0, B0) or_return
internal_sub(A2, A2, t) or_return
@@ -1262,7 +1262,7 @@ _private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := con
/*
Return q = (Q1*beta^k) + Q0, r = A2.
*/
- internal_shl_digit(Q1, k) or_return
+ _private_int_shl_leg(Q1, k) or_return
internal_add(quotient, Q1, Q0) or_return
return internal_copy(remainder, A2)
@@ -1923,7 +1923,7 @@ _private_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := cont
x = x/b**n.used.
*/
internal_clamp(x)
- internal_shr_digit(x, n.used)
+ _private_int_shr_leg(x, n.used)
/*
if x >= 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/core/math/big/rat.odin b/core/math/big/rat.odin
index 837af6fd3..c3efc30aa 100644
--- a/core/math/big/rat.odin
+++ b/core/math/big/rat.odin
@@ -42,9 +42,9 @@ rat_set_f64 :: proc(dst: ^Rat, f: f64, allocator := context.allocator) -> (err:
dst.a.sign = .Negative if f < 0 else .Zero_or_Positive
if shift > 0 {
- internal_int_shl_digit(&dst.b, shift) or_return
+ internal_int_shl(&dst.b, &dst.b, shift) or_return
} else {
- internal_int_shl_digit(&dst.a, -shift) or_return
+ internal_int_shl(&dst.a, &dst.a, -shift) or_return
}
return internal_rat_norm(dst)
@@ -389,9 +389,9 @@ internal_rat_to_float :: proc($T: typeid, z: ^Rat, allocator := context.allocato
internal_int_abs(b2, b) or_return
if shift := MSIZE2 - exp; shift > 0 {
- internal_int_shl_digit(a2, shift) or_return
- } else {
- internal_int_shl_digit(b2, -shift) or_return
+ internal_int_shl(a2, a2, shift) or_return
+ } else if shift < 0 {
+ internal_int_shl(b2, b2, -shift) or_return
}
q, r := &Int{}, &Int{}
diff --git a/core/math/math.odin b/core/math/math.odin
index caaa6f51b..b81598da9 100644
--- a/core/math/math.odin
+++ b/core/math/math.odin
@@ -1196,6 +1196,7 @@ sum :: proc "contextless" (x: $T/[]$E) -> (res: E)
prod :: proc "contextless" (x: $T/[]$E) -> (res: E)
where intrinsics.type_is_numeric(E) {
+ res = 1
for i in x {
res *= i
}
diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin
index ed58f4318..6498c4db7 100644
--- a/core/runtime/internal.odin
+++ b/core/runtime/internal.odin
@@ -2,13 +2,15 @@ package runtime
import "core:intrinsics"
+@(private="file")
+IS_WASM :: ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64"
+
@(private)
RUNTIME_LINKAGE :: "strong" when (
(ODIN_USE_SEPARATE_MODULES ||
ODIN_BUILD_MODE == "dynamic" ||
!ODIN_NO_CRT) &&
- !(ODIN_ARCH == "wasm32" ||
- ODIN_ARCH == "wasm64")) else "internal"
+ !IS_WASM) else "internal"
RUNTIME_REQUIRE :: true
@@ -752,6 +754,9 @@ extendhfsf2 :: proc "c" (value: u16) -> f32 {
@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
floattidf :: proc "c" (a: i128) -> f64 {
+when IS_WASM {
+ return 0
+} else {
DBL_MANT_DIG :: 53
if a == 0 {
return 0.0
@@ -791,10 +796,14 @@ floattidf :: proc "c" (a: i128) -> f64 {
fb[0] = u32(a) // mantissa-low
return transmute(f64)fb
}
+}
@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
floattidf_unsigned :: proc "c" (a: u128) -> f64 {
+when IS_WASM {
+ return 0
+} else {
DBL_MANT_DIG :: 53
if a == 0 {
return 0.0
@@ -832,6 +841,7 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 {
fb[0] = u32(a) // mantissa-low
return transmute(f64)fb
}
+}
diff --git a/core/runtime/procs_wasm32.odin b/core/runtime/procs_wasm32.odin
index 5caf6d2f8..2a4210c1e 100644
--- a/core/runtime/procs_wasm32.odin
+++ b/core/runtime/procs_wasm32.odin
@@ -1,23 +1,40 @@
//+build wasm32
package runtime
+@(private="file")
+ti_int :: struct #raw_union {
+ using s: struct { lo, hi: u64 },
+ all: i128,
+}
+
@(link_name="__ashlti3", linkage="strong")
-__ashlti3 :: proc "c" (a: i64, b_: i32) -> i64 {
- /*
+__ashlti3 :: proc "c" (a: i128, b_: u32) -> i128 {
+ bits_in_dword :: size_of(u32)*8
b := u32(b_)
- input := transmute([2]i32)a
- result: [2]i32
- if b & 32 != 0 {
- result[0] = 0
- result[1] = input[0] << (b - 32)
+
+ input, result: ti_int
+ input.all = a
+ if b & bits_in_dword != 0 {
+ result.lo = 0
+ result.hi = input.lo << (b-bits_in_dword)
} else {
if b == 0 {
return a
}
- result[0] = input[0]<<b
- result[1] = (input[1]<<b) | (input[0]>>(32-b))
+ result.lo = input.lo<<b
+ result.hi = (input.hi<<b) | (input.lo>>(bits_in_dword-b))
}
- return transmute(i64)result
- */
- return 0
+ return result.all
+}
+
+
+@(link_name="__multi3", linkage="strong")
+__multi3 :: proc "c" (a, b: i128) -> i128 {
+ x, y, r: ti_int
+
+ x.all = a
+ y.all = b
+ r.all = i128(x.lo * y.lo) // TODO this is incorrect
+ r.hi += x.hi*y.lo + x.lo*y.hi
+ return r.all
} \ No newline at end of file
diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin
index 6b3a91b4c..6ea8b39e6 100644
--- a/core/strconv/strconv.odin
+++ b/core/strconv/strconv.odin
@@ -882,7 +882,9 @@ unquote_string :: proc(lit: string, allocator := context.allocator) -> (res: str
return -1
}
- assert(len(lit) >= 2)
+ if len(lit) < 2 {
+ return
+ }
if lit[0] == '`' {
return lit[1:len(lit)-1], false, true
}
diff --git a/core/strings/strings.odin b/core/strings/strings.odin
index a8199e0cf..3f703372f 100644
--- a/core/strings/strings.odin
+++ b/core/strings/strings.odin
@@ -504,8 +504,8 @@ index_any :: proc(s, chars: string) -> int {
}
}
- for c in chars {
- if i := index_rune(s, c); i >= 0 {
+ for c, i in s {
+ if index_rune(chars, c) >= 0 {
return i
}
}
@@ -1288,7 +1288,7 @@ fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.alloc
}
if start >= 0 {
- append(&substrings, s[start : end])
+ append(&substrings, s[start : len(s)])
}
return substrings[:]