mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-09 06:23:14 +00:00
Merge branch 'master' of https://github.com/weshardee/Odin
This commit is contained in:
@@ -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[:]
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
Little = -1,
|
||||
Platform = 0,
|
||||
Big = 1,
|
||||
}
|
||||
@@ -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
|
||||
|
||||
#no_bounds_check for src != 0 {
|
||||
dest.digit[dest.used] = DIGIT(src) & _MASK
|
||||
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 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,28 +2320,69 @@ 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.
|
||||
*/
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2633,37 +2687,6 @@ internal_int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.all
|
||||
}
|
||||
internal_shr :: proc { internal_int_shr, }
|
||||
|
||||
/*
|
||||
Shift right by `digits` * _DIGIT_BITS bits.
|
||||
*/
|
||||
internal_int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
|
||||
context.allocator = allocator
|
||||
|
||||
if digits <= 0 { return nil }
|
||||
|
||||
/*
|
||||
If digits > used simply zero and return.
|
||||
*/
|
||||
if digits > quotient.used { return internal_zero(quotient) }
|
||||
|
||||
/*
|
||||
Much like `int_shl_digit`, this is implemented using a sliding window,
|
||||
except the window goes the other way around.
|
||||
|
||||
b-2 | b-1 | b0 | b1 | b2 | ... | bb | ---->
|
||||
/\ | ---->
|
||||
\-------------------/ ---->
|
||||
*/
|
||||
|
||||
#no_bounds_check for x := 0; x < (quotient.used - digits); x += 1 {
|
||||
quotient.digit[x] = quotient.digit[x + digits]
|
||||
}
|
||||
quotient.used -= digits
|
||||
internal_zero_unused(quotient)
|
||||
return internal_clamp(quotient)
|
||||
}
|
||||
internal_shr_digit :: proc { internal_int_shr_digit, }
|
||||
|
||||
/*
|
||||
Shift right by a certain bit count with sign extension.
|
||||
*/
|
||||
@@ -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.
|
||||
|
||||
@@ -86,21 +86,6 @@ int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -
|
||||
}
|
||||
shr :: proc { int_shr, }
|
||||
|
||||
/*
|
||||
Shift right by `digits` * _DIGIT_BITS bits.
|
||||
*/
|
||||
int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
|
||||
/*
|
||||
Check that `quotient` is usable.
|
||||
*/
|
||||
assert_if_nil(quotient)
|
||||
context.allocator = allocator
|
||||
|
||||
internal_clear_if_uninitialized(quotient) or_return
|
||||
return #force_inline internal_int_shr_digit(quotient, digits)
|
||||
}
|
||||
shr_digit :: proc { int_shr_digit, }
|
||||
|
||||
/*
|
||||
Shift right by a certain bit count with sign extension.
|
||||
*/
|
||||
@@ -124,20 +109,4 @@ int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (
|
||||
internal_clear_if_uninitialized(dest, src) or_return
|
||||
return #force_inline internal_int_shl(dest, src, bits)
|
||||
}
|
||||
shl :: proc { int_shl, }
|
||||
|
||||
|
||||
/*
|
||||
Shift left by `digits` * _DIGIT_BITS bits.
|
||||
*/
|
||||
int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
|
||||
/*
|
||||
Check that `quotient` is usable.
|
||||
*/
|
||||
assert_if_nil(quotient)
|
||||
context.allocator = allocator
|
||||
|
||||
internal_clear_if_uninitialized(quotient) or_return
|
||||
return #force_inline internal_int_shl_digit(quotient, digits)
|
||||
}
|
||||
shl_digit :: proc { int_shl_digit, };
|
||||
shl :: proc { int_shl, }
|
||||
@@ -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 =======================
|
||||
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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[:]
|
||||
|
||||
@@ -2243,6 +2243,9 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||
error(e->token, "The 'static' attribute is not allowed to be applied to '_'");
|
||||
} else {
|
||||
e->flags |= EntityFlag_Static;
|
||||
if (ctx->in_defer) {
|
||||
error(e->token, "'static' variables cannot be declared within a defer statement");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ac.thread_local_model != "") {
|
||||
@@ -2251,9 +2254,13 @@ void check_stmt_internal(CheckerContext *ctx, Ast *node, u32 flags) {
|
||||
error(e->token, "The 'thread_local' attribute is not allowed to be applied to '_'");
|
||||
} else {
|
||||
e->flags |= EntityFlag_Static;
|
||||
if (ctx->in_defer) {
|
||||
error(e->token, "'thread_local' variables cannot be declared within a defer statement");
|
||||
}
|
||||
}
|
||||
e->Variable.thread_local_model = ac.thread_local_model;
|
||||
}
|
||||
|
||||
|
||||
if (ac.is_static && ac.thread_local_model != "") {
|
||||
error(e->token, "The 'static' attribute is not needed if 'thread_local' is applied");
|
||||
|
||||
@@ -48,12 +48,6 @@ LLVMBool lb_must_preserve_predicate_callback(LLVMValueRef value, void *user_data
|
||||
return LLVMIsAAllocaInst(value) != nullptr;
|
||||
}
|
||||
|
||||
void lb_add_must_preserve_predicate_pass(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) {
|
||||
if (false && optimization_level == 0 && m->debug_builder) {
|
||||
// LLVMAddInternalizePassWithMustPreservePredicate(fpm, m, lb_must_preserve_predicate_callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 12
|
||||
#define LLVM_ADD_CONSTANT_VALUE_PASS(fpm) LLVMAddConstantPropagationPass(fpm)
|
||||
@@ -61,7 +55,10 @@ void lb_add_must_preserve_predicate_pass(lbModule *m, LLVMPassManagerRef fpm, i3
|
||||
#define LLVM_ADD_CONSTANT_VALUE_PASS(fpm)
|
||||
#endif
|
||||
|
||||
void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm) {
|
||||
void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) {
|
||||
if (optimization_level == 0 && build_context.ODIN_DEBUG) {
|
||||
return;
|
||||
}
|
||||
LLVMAddPromoteMemoryToRegisterPass(fpm);
|
||||
LLVMAddMergedLoadStoreMotionPass(fpm);
|
||||
LLVM_ADD_CONSTANT_VALUE_PASS(fpm);
|
||||
@@ -78,14 +75,12 @@ void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool
|
||||
// TODO(bill): Determine which opt definitions should exist in the first place
|
||||
optimization_level = gb_clamp(optimization_level, 0, 2);
|
||||
|
||||
lb_add_must_preserve_predicate_pass(m, fpm, optimization_level);
|
||||
|
||||
if (ignore_memcpy_pass) {
|
||||
lb_basic_populate_function_pass_manager(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm, optimization_level);
|
||||
return;
|
||||
} else if (optimization_level == 0) {
|
||||
LLVMAddMemCpyOptPass(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm, optimization_level);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -96,7 +91,7 @@ void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool
|
||||
LLVMPassManagerBuilderPopulateFunctionPassManager(pmb, fpm);
|
||||
#else
|
||||
LLVMAddMemCpyOptPass(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm, optimization_level);
|
||||
|
||||
LLVMAddSCCPPass(fpm);
|
||||
|
||||
@@ -114,11 +109,9 @@ void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef
|
||||
// TODO(bill): Determine which opt definitions should exist in the first place
|
||||
optimization_level = gb_clamp(optimization_level, 0, 2);
|
||||
|
||||
lb_add_must_preserve_predicate_pass(m, fpm, optimization_level);
|
||||
|
||||
if (optimization_level == 0) {
|
||||
LLVMAddMemCpyOptPass(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm);
|
||||
lb_basic_populate_function_pass_manager(fpm, optimization_level);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -191,6 +184,9 @@ void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPa
|
||||
// NOTE(bill): Treat -opt:3 as if it was -opt:2
|
||||
// TODO(bill): Determine which opt definitions should exist in the first place
|
||||
optimization_level = gb_clamp(optimization_level, 0, 2);
|
||||
if (optimization_level == 0 && build_context.ODIN_DEBUG) {
|
||||
return;
|
||||
}
|
||||
|
||||
LLVMAddAlwaysInlinerPass(mpm);
|
||||
LLVMAddStripDeadPrototypesPass(mpm);
|
||||
|
||||
@@ -208,7 +208,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
|
||||
/*
|
||||
dest = shr_digit(src, digits)
|
||||
*/
|
||||
@export test_shr_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
|
||||
@export test_shr_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
|
||||
context = runtime.default_context()
|
||||
err: big.Error
|
||||
|
||||
@@ -216,7 +216,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
|
||||
defer big.internal_destroy(src)
|
||||
|
||||
if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(src):", err=err} }
|
||||
if err = #force_inline big.internal_shr_digit(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} }
|
||||
if err = #force_inline big._private_int_shr_leg(src, digits); err != nil { return PyRes{res=":shr_digit:shr_digit(src):", err=err} }
|
||||
|
||||
r := print_to_buffer(src)
|
||||
return PyRes{res = r, err = nil}
|
||||
@@ -225,7 +225,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
|
||||
/*
|
||||
dest = shl_digit(src, digits)
|
||||
*/
|
||||
@export test_shl_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
|
||||
@export test_shl_leg :: proc "c" (source: cstring, digits: int) -> (res: PyRes) {
|
||||
context = runtime.default_context()
|
||||
err: big.Error
|
||||
|
||||
@@ -233,7 +233,7 @@ print_to_buffer :: proc(val: ^big.Int) -> cstring {
|
||||
defer big.internal_destroy(src)
|
||||
|
||||
if err = big.atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(src):", err=err} }
|
||||
if err = #force_inline big.internal_shl_digit(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} }
|
||||
if err = #force_inline big._private_int_shl_leg(src, digits); err != nil { return PyRes{res=":shl_digit:shr_digit(src):", err=err} }
|
||||
|
||||
r := print_to_buffer(src)
|
||||
return PyRes{res = r, err = nil}
|
||||
|
||||
@@ -127,17 +127,22 @@ def we_iterate():
|
||||
# Error enum values
|
||||
#
|
||||
class Error(Enum):
|
||||
Okay = 0
|
||||
Out_Of_Memory = 1
|
||||
Invalid_Pointer = 2
|
||||
Invalid_Argument = 3
|
||||
Unknown_Error = 4
|
||||
Max_Iterations_Reached = 5
|
||||
Buffer_Overflow = 6
|
||||
Integer_Overflow = 7
|
||||
Division_by_Zero = 8
|
||||
Math_Domain_Error = 9
|
||||
Unimplemented = 127
|
||||
Okay = 0
|
||||
Out_Of_Memory = 1
|
||||
Invalid_Pointer = 2
|
||||
Invalid_Argument = 3
|
||||
Unknown_Error = 4
|
||||
Assignment_To_Immutable = 10
|
||||
Max_Iterations_Reached = 11
|
||||
Buffer_Overflow = 12
|
||||
Integer_Overflow = 13
|
||||
Integer_Underflow = 14
|
||||
Division_by_Zero = 30
|
||||
Math_Domain_Error = 31
|
||||
Cannot_Open_File = 50
|
||||
Cannot_Read_File = 51
|
||||
Cannot_Write_File = 52
|
||||
Unimplemented = 127
|
||||
|
||||
#
|
||||
# Disable garbage collection
|
||||
@@ -182,8 +187,8 @@ int_sqrt = load(l.test_sqrt, [c_char_p ], Res)
|
||||
int_root_n = load(l.test_root_n, [c_char_p, c_longlong], Res)
|
||||
|
||||
# Logical operations
|
||||
int_shl_digit = load(l.test_shl_digit, [c_char_p, c_longlong], Res)
|
||||
int_shr_digit = load(l.test_shr_digit, [c_char_p, c_longlong], Res)
|
||||
int_shl_leg = load(l.test_shl_leg, [c_char_p, c_longlong], Res)
|
||||
int_shr_leg = load(l.test_shr_leg, [c_char_p, c_longlong], Res)
|
||||
int_shl = load(l.test_shl, [c_char_p, c_longlong], Res)
|
||||
int_shr = load(l.test_shr, [c_char_p, c_longlong], Res)
|
||||
int_shr_signed = load(l.test_shr_signed, [c_char_p, c_longlong], Res)
|
||||
@@ -397,17 +402,17 @@ def test_root_n(number = 0, root = 0, expected_error = Error.Okay):
|
||||
|
||||
return test("test_root_n", res, [number, root], expected_error, expected_result)
|
||||
|
||||
def test_shl_digit(a = 0, digits = 0, expected_error = Error.Okay):
|
||||
def test_shl_leg(a = 0, digits = 0, expected_error = Error.Okay):
|
||||
args = [arg_to_odin(a), digits]
|
||||
res = int_shl_digit(*args)
|
||||
res = int_shl_leg(*args)
|
||||
expected_result = None
|
||||
if expected_error == Error.Okay:
|
||||
expected_result = a << (digits * 60)
|
||||
return test("test_shl_digit", res, [a, digits], expected_error, expected_result)
|
||||
return test("test_shl_leg", res, [a, digits], expected_error, expected_result)
|
||||
|
||||
def test_shr_digit(a = 0, digits = 0, expected_error = Error.Okay):
|
||||
def test_shr_leg(a = 0, digits = 0, expected_error = Error.Okay):
|
||||
args = [arg_to_odin(a), digits]
|
||||
res = int_shr_digit(*args)
|
||||
res = int_shr_leg(*args)
|
||||
expected_result = None
|
||||
if expected_error == Error.Okay:
|
||||
if a < 0:
|
||||
@@ -416,7 +421,7 @@ def test_shr_digit(a = 0, digits = 0, expected_error = Error.Okay):
|
||||
else:
|
||||
expected_result = a >> (digits * 60)
|
||||
|
||||
return test("test_shr_digit", res, [a, digits], expected_error, expected_result)
|
||||
return test("test_shr_leg", res, [a, digits], expected_error, expected_result)
|
||||
|
||||
def test_shl(a = 0, bits = 0, expected_error = Error.Okay):
|
||||
args = [arg_to_odin(a), bits]
|
||||
@@ -551,12 +556,12 @@ TESTS = {
|
||||
test_root_n: [
|
||||
[ 1298074214633706907132624082305024, 2, Error.Okay, ],
|
||||
],
|
||||
test_shl_digit: [
|
||||
test_shl_leg: [
|
||||
[ 3192, 1 ],
|
||||
[ 1298074214633706907132624082305024, 2 ],
|
||||
[ 1024, 3 ],
|
||||
],
|
||||
test_shr_digit: [
|
||||
test_shr_leg: [
|
||||
[ 3680125442705055547392, 1 ],
|
||||
[ 1725436586697640946858688965569256363112777243042596638790631055949824, 2 ],
|
||||
[ 219504133884436710204395031992179571, 2 ],
|
||||
@@ -614,10 +619,10 @@ total_failures = 0
|
||||
# test_shr_signed also tests shr, so we're not going to test shr randomly.
|
||||
#
|
||||
RANDOM_TESTS = [
|
||||
test_add, test_sub, test_mul, test_sqr, test_div,
|
||||
test_log, test_pow, test_sqrt, test_root_n,
|
||||
test_shl_digit, test_shr_digit, test_shl, test_shr_signed,
|
||||
test_gcd, test_lcm, test_is_square,
|
||||
test_add, test_sub, test_mul, test_sqr,
|
||||
test_log, test_pow, test_sqrt, test_root_n,
|
||||
test_shl_leg, test_shr_leg, test_shl, test_shr_signed,
|
||||
test_gcd, test_lcm, test_is_square, test_div,
|
||||
]
|
||||
SKIP_LARGE = [
|
||||
test_pow, test_root_n, # test_gcd,
|
||||
@@ -714,9 +719,9 @@ if __name__ == '__main__':
|
||||
a = randint(1, 1 << BITS)
|
||||
b = TEST_ROOT_N_PARAMS[index]
|
||||
index = (index + 1) % len(TEST_ROOT_N_PARAMS)
|
||||
elif test_proc == test_shl_digit:
|
||||
elif test_proc == test_shl_leg:
|
||||
b = randint(0, 10);
|
||||
elif test_proc == test_shr_digit:
|
||||
elif test_proc == test_shr_leg:
|
||||
a = abs(a)
|
||||
b = randint(0, 10);
|
||||
elif test_proc == test_shl:
|
||||
|
||||
10
vendor/wasm/WebGL/runtime.js
vendored
10
vendor/wasm/WebGL/runtime.js
vendored
@@ -416,7 +416,7 @@ class WebGLInterface {
|
||||
log = log.substring(0, n);
|
||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(log))
|
||||
|
||||
storeInt(length_ptr, n);
|
||||
this.mem.storeInt(length_ptr, n);
|
||||
}
|
||||
},
|
||||
GetShaderInfoLog: (shader, buf_ptr, buf_len, length_ptr) => {
|
||||
@@ -429,7 +429,7 @@ class WebGLInterface {
|
||||
log = log.substring(0, n);
|
||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(log))
|
||||
|
||||
storeInt(length_ptr, n);
|
||||
this.mem.storeInt(length_ptr, n);
|
||||
}
|
||||
},
|
||||
GetShaderiv: (shader, pname, p) => {
|
||||
@@ -439,11 +439,11 @@ class WebGLInterface {
|
||||
if (log === null) {
|
||||
log = "(unknown error)";
|
||||
}
|
||||
storeInt(p, log.length+1);
|
||||
this.mem.storeInt(p, log.length+1);
|
||||
} else if (pname == 35720) {
|
||||
let source = this.ctx.getShaderSource(this.shaders[shader]);
|
||||
let sourceLength = (source === null || source.length == 0) ? 0 : source.length+1;
|
||||
storeInt(p, sourceLength);
|
||||
this.mem.storeInt(p, sourceLength);
|
||||
} else {
|
||||
let param = this.ctx.getShaderParameter(this.shaders[shader], pname);
|
||||
this.mem.storeI32(p, param);
|
||||
@@ -994,7 +994,7 @@ class WebGLInterface {
|
||||
let n = Math.min(buf_len, name.length);
|
||||
name = name.substring(0, n);
|
||||
this.mem.loadBytes(buf_ptr, buf_len).set(new TextEncoder("utf-8").encode(name))
|
||||
storeInt(length_ptr, n);
|
||||
this.mem.storeInt(length_ptr, n);
|
||||
},
|
||||
UniformBlockBinding: (program, uniformBlockIndex, uniformBlockBinding) => {
|
||||
this.assertWebGL2();
|
||||
|
||||
Reference in New Issue
Block a user