diff options
| author | gingerBill <bill@gingerbill.org> | 2021-08-31 22:21:13 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2021-08-31 22:21:13 +0100 |
| commit | 251da264ed6e0f039931683c7b0d4b97e88c8d99 (patch) | |
| tree | c7a9a088477d2452c2cf850458c62d994a211df6 /core/math | |
| parent | b176af27427a6c39448a71a8023e4a9877f0a51c (diff) | |
Remove unneeded semicolons from the core library
Diffstat (limited to 'core/math')
25 files changed, 8191 insertions, 8191 deletions
diff --git a/core/math/big/api.odin b/core/math/big/api.odin index 1f2eab8d7..1c7833730 100644 --- a/core/math/big/api.odin +++ b/core/math/big/api.odin @@ -31,7 +31,7 @@ add :: proc { int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) */ int_add_digit, -}; +} /* err = sub(dest, a, b); @@ -45,7 +45,7 @@ sub :: proc { int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) */ int_sub_digit, -}; +} /* === === === === === === === === === === === === === === === === === === === === === === === === @@ -59,44 +59,44 @@ is_initialized :: proc { int_is_initialized :: proc(a: ^Int) -> bool */ int_is_initialized, -}; +} is_zero :: proc { /* int_is_zero :: proc(a: ^Int) -> bool */ int_is_zero, -}; +} is_positive :: proc { /* int_is_positive :: proc(a: ^Int) -> bool */ int_is_positive, -}; -is_pos :: is_positive; +} +is_pos :: is_positive is_negative :: proc { /* int_is_negative :: proc(a: ^Int) -> bool */ int_is_negative, -}; -is_neg :: is_negative; +} +is_neg :: is_negative is_even :: proc { /* int_is_even :: proc(a: ^Int) -> bool */ int_is_even, -}; +} is_odd :: proc { /* int_is_odd :: proc(a: ^Int) -> bool */ int_is_odd, -}; +} is_power_of_two :: proc { /* @@ -107,7 +107,7 @@ is_power_of_two :: proc { int_is_power_of_two :: proc(a: ^Int) -> (res: bool) */ int_is_power_of_two, -}; +} compare :: proc { /* @@ -122,16 +122,16 @@ compare :: proc { int_compare_digit :: proc(a: ^Int, u: DIGIT) -> Comparison_Flag */ int_compare_digit, -}; -cmp :: compare; +} +cmp :: compare compare_magnitude :: proc { /* Compare the magnitude of two `Int`s, unsigned. */ int_compare_magnitude, -}; -cmp_mag :: compare_magnitude; +} +cmp_mag :: compare_magnitude /* === === === === === === === === === === === === === === === === === === === === === === === === @@ -147,6 +147,6 @@ destroy :: proc { int_destroy :: proc(integers: ..^Int) */ int_destroy, -}; +} diff --git a/core/math/big/common.odin b/core/math/big/common.odin index ce1f7d77f..f23754e89 100644 --- a/core/math/big/common.odin +++ b/core/math/big/common.odin @@ -33,15 +33,15 @@ import "core:intrinsics" To allow tests to run we add `-define:MATH_BIG_EXE=false` to hardcode the cutoffs for now. */ when #config(MATH_BIG_EXE, true) { - MUL_KARATSUBA_CUTOFF := initialize_constants(); - SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF; - MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF; - SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF; + MUL_KARATSUBA_CUTOFF := initialize_constants() + SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF + MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF + SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF } else { - MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF; - SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF; - MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF; - SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF; + MUL_KARATSUBA_CUTOFF := _DEFAULT_MUL_KARATSUBA_CUTOFF + SQR_KARATSUBA_CUTOFF := _DEFAULT_SQR_KARATSUBA_CUTOFF + MUL_TOOM_CUTOFF := _DEFAULT_MUL_TOOM_CUTOFF + SQR_TOOM_CUTOFF := _DEFAULT_SQR_TOOM_CUTOFF } /* @@ -57,24 +57,24 @@ when #config(MATH_BIG_EXE, true) { debugged where necessary. */ -_DEFAULT_MUL_KARATSUBA_CUTOFF :: #config(MUL_KARATSUBA_CUTOFF, 80); -_DEFAULT_SQR_KARATSUBA_CUTOFF :: #config(SQR_KARATSUBA_CUTOFF, 120); -_DEFAULT_MUL_TOOM_CUTOFF :: #config(MUL_TOOM_CUTOFF, 350); -_DEFAULT_SQR_TOOM_CUTOFF :: #config(SQR_TOOM_CUTOFF, 400); +_DEFAULT_MUL_KARATSUBA_CUTOFF :: #config(MUL_KARATSUBA_CUTOFF, 80) +_DEFAULT_SQR_KARATSUBA_CUTOFF :: #config(SQR_KARATSUBA_CUTOFF, 120) +_DEFAULT_MUL_TOOM_CUTOFF :: #config(MUL_TOOM_CUTOFF, 350) +_DEFAULT_SQR_TOOM_CUTOFF :: #config(SQR_TOOM_CUTOFF, 400) -MAX_ITERATIONS_ROOT_N := 500; +MAX_ITERATIONS_ROOT_N := 500 /* Largest `N` for which we'll compute `N!` */ -FACTORIAL_MAX_N := 1_000_000; +FACTORIAL_MAX_N := 1_000_000 /* Cutoff to switch to int_factorial_binary_split, and its max recursion level. */ -FACTORIAL_BINARY_SPLIT_CUTOFF := 6100; -FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS := 100; +FACTORIAL_BINARY_SPLIT_CUTOFF := 6100 +FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS := 100 /* @@ -85,15 +85,15 @@ FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS := 100; 2) Optimizations thanks to precomputed masks wouldn't work. */ -MATH_BIG_FORCE_64_BIT :: #config(MATH_BIG_FORCE_64_BIT, false); -MATH_BIG_FORCE_32_BIT :: #config(MATH_BIG_FORCE_32_BIT, false); +MATH_BIG_FORCE_64_BIT :: #config(MATH_BIG_FORCE_64_BIT, false) +MATH_BIG_FORCE_32_BIT :: #config(MATH_BIG_FORCE_32_BIT, false) when (MATH_BIG_FORCE_32_BIT && MATH_BIG_FORCE_64_BIT) { #panic("Cannot force 32-bit and 64-bit big backend simultaneously."); }; -_LOW_MEMORY :: #config(BIGINT_SMALL_MEMORY, false); +_LOW_MEMORY :: #config(BIGINT_SMALL_MEMORY, false) when _LOW_MEMORY { - _DEFAULT_DIGIT_COUNT :: 8; + _DEFAULT_DIGIT_COUNT :: 8 } else { - _DEFAULT_DIGIT_COUNT :: 32; + _DEFAULT_DIGIT_COUNT :: 32 } /* @@ -103,22 +103,22 @@ when _LOW_MEMORY { Sign :: enum u8 { Zero_or_Positive = 0, Negative = 1, -}; +} Int :: struct { used: int, digit: [dynamic]DIGIT, sign: Sign, flags: Flags, -}; +} Flag :: enum u8 { NaN, Inf, Immutable, -}; +} -Flags :: bit_set[Flag; u8]; +Flags :: bit_set[Flag; u8] /* Errors are a strict superset of runtime.Allocation_Error. @@ -138,7 +138,7 @@ Error :: enum int { Math_Domain_Error = 9, Unimplemented = 127, -}; +} Error_String :: #partial [Error]string{ .Out_Of_Memory = "Out of memory", @@ -154,14 +154,14 @@ Error_String :: #partial [Error]string{ .Math_Domain_Error = "Math domain error", .Unimplemented = "Unimplemented", -}; +} Primality_Flag :: enum u8 { Blum_Blum_Shub = 0, /* BBS style prime */ Safe = 1, /* Safe prime (p-1)/2 == prime */ Second_MSB_On = 3, /* force 2nd MSB to 1 */ -}; -Primality_Flags :: bit_set[Primality_Flag; u8]; +} +Primality_Flags :: bit_set[Primality_Flag; u8] /* How do we store the Ints? @@ -171,7 +171,7 @@ Primality_Flags :: bit_set[Primality_Flag; u8]; - Must be large enough such that `init_integer` can store `u128` in the `Int` without growing. */ -_MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS); +_MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS) #assert(_DEFAULT_DIGIT_COUNT >= _MIN_DIGIT_COUNT); /* @@ -180,36 +180,36 @@ _MIN_DIGIT_COUNT :: max(3, ((size_of(u128) + _DIGIT_BITS) - 1) / _DIGIT_BITS); - 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); -_MAX_DIGIT_COUNT :: _MAX_BIT_COUNT / _DIGIT_BITS; +_MAX_BIT_COUNT :: (max(int) - 2) +_MAX_DIGIT_COUNT :: _MAX_BIT_COUNT / _DIGIT_BITS when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* We can use u128 as an intermediary. */ - DIGIT :: distinct u64; - _WORD :: distinct u128; + DIGIT :: distinct u64 + _WORD :: distinct u128 } else { - DIGIT :: distinct u32; - _WORD :: distinct u64; + DIGIT :: distinct u32 + _WORD :: distinct u64 } #assert(size_of(_WORD) == 2 * size_of(DIGIT)); -_DIGIT_TYPE_BITS :: 8 * size_of(DIGIT); -_WORD_TYPE_BITS :: 8 * size_of(_WORD); +_DIGIT_TYPE_BITS :: 8 * size_of(DIGIT) +_WORD_TYPE_BITS :: 8 * size_of(_WORD) -_DIGIT_BITS :: _DIGIT_TYPE_BITS - 4; -_WORD_BITS :: 2 * _DIGIT_BITS; +_DIGIT_BITS :: _DIGIT_TYPE_BITS - 4 +_WORD_BITS :: 2 * _DIGIT_BITS -_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1); -_DIGIT_MAX :: _MASK; -_MAX_COMBA :: 1 << (_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) ; -_WARRAY :: 1 << ((_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) + 1); +_MASK :: (DIGIT(1) << DIGIT(_DIGIT_BITS)) - DIGIT(1) +_DIGIT_MAX :: _MASK +_MAX_COMBA :: 1 << (_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) +_WARRAY :: 1 << ((_WORD_TYPE_BITS - (2 * _DIGIT_BITS)) + 1) Order :: enum i8 { LSB_First = -1, MSB_First = 1, -}; +} Endianness :: enum i8 { Little = -1, diff --git a/core/math/big/example.odin b/core/math/big/example.odin index 4542e9e15..d764ad940 100644 --- a/core/math/big/example.odin +++ b/core/math/big/example.odin @@ -47,186 +47,186 @@ MAX_ITERATIONS_ROOT_N, FACTORIAL_MAX_N, FACTORIAL_BINARY_SPLIT_CUTOFF, FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS, -); +) } print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) { - assert_if_nil(a); + assert_if_nil(a) - as, err := itoa(a, base); - defer delete(as); + as, err := itoa(a, base) + defer delete(as) - cb := internal_count_bits(a); + cb := internal_count_bits(a) if print_name { - fmt.printf("%v", name); + fmt.printf("%v", name) } if err != nil { - fmt.printf("%v (error: %v | %v)", name, err, a); + fmt.printf("%v (error: %v | %v)", name, err, a) } - fmt.printf("%v", as); + fmt.printf("%v", as) if print_extra_info { - fmt.printf(" (base: %v, bits: %v (digits: %v), flags: %v)", base, cb, a.used, a.flags); + fmt.printf(" (base: %v, bits: %v (digits: %v), flags: %v)", base, cb, a.used, a.flags) } if newline { - fmt.println(); + fmt.println() } } int_to_byte :: proc(v: ^Int) { - err: Error; - size: int; - print("v: ", v); - fmt.println(); + err: Error + size: int + print("v: ", v) + fmt.println() - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b1 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big(v, b1); - int_from_bytes_big(t, b1); - fmt.printf("big: %v | err: %v\n", b1, err); + b1 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big(v, b1) + int_from_bytes_big(t, b1) + fmt.printf("big: %v | err: %v\n", b1, err) - int_from_bytes_big(t, b1); + int_from_bytes_big(t, b1) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b2 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big_python(v, b2); - fmt.printf("big python: %v | err: %v\n", b2, err); + b2 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big_python(v, b2) + fmt.printf("big python: %v | err: %v\n", b2, err) if err == nil { - int_from_bytes_big_python(t, b2); + int_from_bytes_big_python(t, b2) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b3 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big(v, b3, true); - fmt.printf("big signed: %v | err: %v\n", b3, err); + b3 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big(v, b3, true) + fmt.printf("big signed: %v | err: %v\n", b3, err) - int_from_bytes_big(t, b3, true); + int_from_bytes_big(t, b3, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b4 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_big_python(v, b4, true); - fmt.printf("big signed python: %v | err: %v\n", b4, err); + b4 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_big_python(v, b4, true) + fmt.printf("big signed python: %v | err: %v\n", b4, err) - int_from_bytes_big_python(t, b4, true); + int_from_bytes_big_python(t, b4, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } int_to_byte_little :: proc(v: ^Int) { - err: Error; - size: int; - print("v: ", v); - fmt.println(); + err: Error + size: int + print("v: ", v) + fmt.println() - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b1 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little(v, b1); - fmt.printf("little: %v | err: %v\n", b1, err); + b1 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little(v, b1) + fmt.printf("little: %v | err: %v\n", b1, err) - int_from_bytes_little(t, b1); + int_from_bytes_little(t, b1) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b2 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little_python(v, b2); - fmt.printf("little python: %v | err: %v\n", b2, err); + b2 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little_python(v, b2) + fmt.printf("little python: %v | err: %v\n", b2, err) if err == nil { - int_from_bytes_little_python(t, b2); + int_from_bytes_little_python(t, b2) if internal_cmp_mag(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b3 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little(v, b3, true); - fmt.printf("little signed: %v | err: %v\n", b3, err); + b3 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little(v, b3, true) + fmt.printf("little signed: %v | err: %v\n", b3, err) - int_from_bytes_little(t, b3, true); + int_from_bytes_little(t, b3, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } if size, err = int_to_bytes_size(v, true); err != nil { - fmt.printf("int_to_bytes_size returned: %v\n", err); - return; + fmt.printf("int_to_bytes_size returned: %v\n", err) + return } - b4 := make([]u8, size, context.temp_allocator); - err = int_to_bytes_little_python(v, b4, true); - fmt.printf("little signed python: %v | err: %v\n", b4, err); + b4 := make([]u8, size, context.temp_allocator) + err = int_to_bytes_little_python(v, b4, true) + fmt.printf("little signed python: %v | err: %v\n", b4, err) - int_from_bytes_little_python(t, b4, true); + int_from_bytes_little_python(t, b4, true) if internal_cmp(t, v) != 0 { - print("\tError parsing t: ", t); + print("\tError parsing t: ", t) } } demo :: proc() { - a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}; - defer destroy(a, b, c, d, e, f); + a, b, c, d, e, f := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{} + defer destroy(a, b, c, d, e, f) } main :: proc() { - ta := mem.Tracking_Allocator{}; - mem.tracking_allocator_init(&ta, context.allocator); - context.allocator = mem.tracking_allocator(&ta); + ta := mem.Tracking_Allocator{} + mem.tracking_allocator_init(&ta, context.allocator) + context.allocator = mem.tracking_allocator(&ta) - demo(); + demo() - print_configation(); + print_configation() - print_timings(); + print_timings() if len(ta.allocation_map) > 0 { for _, v in ta.allocation_map { - fmt.printf("Leaked %v bytes @ %v\n", v.size, v.location); + fmt.printf("Leaked %v bytes @ %v\n", v.size, v.location) } } if len(ta.bad_free_array) > 0 { - fmt.println("Bad frees:"); + fmt.println("Bad frees:") for v in ta.bad_free_array { - fmt.println(v); + fmt.println(v) } } }
\ No newline at end of file diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index 8ce1b2811..5138dd77d 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -22,10 +22,10 @@ import rnd "core:math/rand" Deallocates the backing memory of one or more `Int`s. */ int_destroy :: proc(integers: ..^Int) { - integers := integers; + integers := integers for a in &integers { - assert_if_nil(a); + assert_if_nil(a) } #force_inline internal_int_destroy(..integers); } @@ -35,19 +35,19 @@ int_destroy :: proc(integers: ..^Int) { */ int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, allocator := context.allocator) -> (err: Error) where intrinsics.type_is_integer(T) { - context.allocator = allocator; - src := src; + context.allocator = allocator + src := src /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest); + assert_if_nil(dest) #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_set_from_integer(dest, src, minimize); + return #force_inline internal_int_set_from_integer(dest, src, minimize) } -set :: proc { int_set_from_integer, int_copy, int_atoi, }; +set :: proc { int_set_from_integer, int_copy, int_atoi, } /* Copy one `Int` to another. @@ -61,15 +61,15 @@ int_copy :: proc(dest, src: ^Int, minimize := false, allocator := context.alloca /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(src) or_return; #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_copy(dest, src, minimize); + return #force_inline internal_int_copy(dest, src, minimize) } -copy :: proc { int_copy, }; +copy :: proc { int_copy, } /* In normal code, you can also write `a, b = b, a`. @@ -77,10 +77,10 @@ copy :: proc { int_copy, }; This helper swaps completely. */ int_swap :: proc(a, b: ^Int) { - assert_if_nil(a, b); + assert_if_nil(a, b) #force_inline internal_swap(a, b); } -swap :: proc { int_swap, }; +swap :: proc { int_swap, } /* Set `dest` to |`src`|. @@ -89,19 +89,19 @@ int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(src) or_return; #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_abs(dest, src); + return #force_inline internal_int_abs(dest, src) } platform_abs :: proc(n: $T) -> T where intrinsics.type_is_integer(T) { - return n if n >= 0 else -n; + return n if n >= 0 else -n } -abs :: proc{ int_abs, platform_abs, }; +abs :: proc{ int_abs, platform_abs, } /* Set `dest` to `-src`. @@ -110,32 +110,32 @@ int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(src) or_return; #force_inline internal_error_if_immutable(dest) or_return; - return #force_inline internal_int_neg(dest, src); + return #force_inline internal_int_neg(dest, src) } -neg :: proc { int_neg, }; +neg :: proc { int_neg, } /* Helpers to extract values from the `Int`. */ int_bitfield_extract_single :: proc(a: ^Int, offset: int, allocator := context.allocator) -> (bit: _WORD, err: Error) { - return #force_inline int_bitfield_extract(a, offset, 1, allocator); + return #force_inline int_bitfield_extract(a, offset, 1, allocator) } int_bitfield_extract :: proc(a: ^Int, offset, count: int, allocator := context.allocator) -> (res: _WORD, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(a) or_return; - return #force_inline internal_int_bitfield_extract(a, offset, count); + return #force_inline internal_int_bitfield_extract(a, offset, count) } /* @@ -145,21 +145,21 @@ shrink :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator #force_inline internal_clear_if_uninitialized(a) or_return; - return #force_inline internal_shrink(a); + return #force_inline internal_shrink(a) } int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_int_grow(a, digits, allow_shrink, allocator); + assert_if_nil(a) + return #force_inline internal_int_grow(a, digits, allow_shrink, allocator) } -grow :: proc { int_grow, }; +grow :: proc { int_grow, } /* Clear `Int` and resize it to the default size. @@ -168,11 +168,11 @@ int_clear :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_int_clear(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_int_clear(a, minimize, allocator) } -clear :: proc { int_clear, }; -zero :: clear; +clear :: proc { int_clear, } +zero :: clear /* Set the `Int` to 1 and optionally shrink it to the minimum backing size. @@ -181,10 +181,10 @@ int_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> ( /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_one(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_one(a, minimize, allocator) } -one :: proc { int_one, }; +one :: proc { int_one, } /* Set the `Int` to -1 and optionally shrink it to the minimum backing size. @@ -193,10 +193,10 @@ int_minus_one :: proc(a: ^Int, minimize := false, allocator := context.allocator /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_minus_one(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_minus_one(a, minimize, allocator) } -minus_one :: proc { int_minus_one, }; +minus_one :: proc { int_minus_one, } /* Set the `Int` to Inf and optionally shrink it to the minimum backing size. @@ -205,10 +205,10 @@ int_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> ( /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_inf(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_inf(a, minimize, allocator) } -inf :: proc { int_inf, }; +inf :: proc { int_inf, } /* Set the `Int` to -Inf and optionally shrink it to the minimum backing size. @@ -217,10 +217,10 @@ int_minus_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_minus_inf(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_minus_inf(a, minimize, allocator) } -minus_inf :: proc { int_inf, }; +minus_inf :: proc { int_inf, } /* Set the `Int` to NaN and optionally shrink it to the minimum backing size. @@ -229,72 +229,72 @@ int_nan :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> ( /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_nan(a, minimize, allocator); + assert_if_nil(a) + return #force_inline internal_nan(a, minimize, allocator) } -nan :: proc { int_nan, }; +nan :: proc { int_nan, } power_of_two :: proc(a: ^Int, power: int, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return #force_inline internal_int_power_of_two(a, power, allocator); + assert_if_nil(a) + return #force_inline internal_int_power_of_two(a, power, allocator) } int_get_u128 :: proc(a: ^Int, allocator := context.allocator) -> (res: u128, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, u128, allocator); + assert_if_nil(a) + return int_get(a, u128, allocator) } -get_u128 :: proc { int_get_u128, }; +get_u128 :: proc { int_get_u128, } int_get_i128 :: proc(a: ^Int, allocator := context.allocator) -> (res: i128, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, i128, allocator); + assert_if_nil(a) + return int_get(a, i128, allocator) } -get_i128 :: proc { int_get_i128, }; +get_i128 :: proc { int_get_i128, } int_get_u64 :: proc(a: ^Int, allocator := context.allocator) -> (res: u64, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, u64, allocator); + assert_if_nil(a) + return int_get(a, u64, allocator) } -get_u64 :: proc { int_get_u64, }; +get_u64 :: proc { int_get_u64, } int_get_i64 :: proc(a: ^Int, allocator := context.allocator) -> (res: i64, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, i64, allocator); + assert_if_nil(a) + return int_get(a, i64, allocator) } -get_i64 :: proc { int_get_i64, }; +get_i64 :: proc { int_get_i64, } int_get_u32 :: proc(a: ^Int, allocator := context.allocator) -> (res: u32, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, u32, allocator); + assert_if_nil(a) + return int_get(a, u32, allocator) } -get_u32 :: proc { int_get_u32, }; +get_u32 :: proc { int_get_u32, } int_get_i32 :: proc(a: ^Int, allocator := context.allocator) -> (res: i32, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); - return int_get(a, i32, allocator); + assert_if_nil(a) + return int_get(a, i32, allocator) } -get_i32 :: proc { int_get_i32, }; +get_i32 :: proc { int_get_i32, } /* TODO: Think about using `count_bits` to check if the value could be returned completely, @@ -304,19 +304,19 @@ int_get :: proc(a: ^Int, $T: typeid, allocator := context.allocator) -> (res: T, /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_int_get(a, T); + return #force_inline internal_int_get(a, T) } -get :: proc { int_get, }; +get :: proc { int_get, } int_get_float :: proc(a: ^Int, allocator := context.allocator) -> (res: f64, err: Error) { /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_int_get_float(a); + return #force_inline internal_int_get_float(a) } /* @@ -326,9 +326,9 @@ count_bits :: proc(a: ^Int, allocator := context.allocator) -> (count: int, err: /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_count_bits(a), nil; + return #force_inline internal_count_bits(a), nil } /* @@ -339,109 +339,109 @@ int_count_lsb :: proc(a: ^Int, allocator := context.allocator) -> (count: int, e /* Check that `a` is usable. */ - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - return #force_inline internal_int_count_lsb(a); + return #force_inline internal_int_count_lsb(a) } platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) { - return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0; + return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0 } -count_lsb :: proc { int_count_lsb, platform_count_lsb, }; +count_lsb :: proc { int_count_lsb, platform_count_lsb, } int_random_digit :: proc(r: ^rnd.Rand = nil) -> (res: DIGIT) { when _DIGIT_BITS == 60 { // DIGIT = u64 - return DIGIT(rnd.uint64(r)) & _MASK; + return DIGIT(rnd.uint64(r)) & _MASK } else when _DIGIT_BITS == 28 { // DIGIT = u32 - return DIGIT(rnd.uint32(r)) & _MASK; + return DIGIT(rnd.uint32(r)) & _MASK } else { - panic("Unsupported DIGIT size."); + panic("Unsupported DIGIT size.") } - return 0; // We shouldn't get here. + return 0 // We shouldn't get here. } int_rand :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator := context.allocator) -> (err: Error) { /* Check that `a` is usable. */ - assert_if_nil(dest); - return #force_inline internal_int_rand(dest, bits, r, allocator); + assert_if_nil(dest) + return #force_inline internal_int_rand(dest, bits, r, allocator) } -rand :: proc { int_rand, }; +rand :: proc { int_rand, } /* Internal helpers. */ assert_initialized :: proc(a: ^Int, loc := #caller_location) { - assert_if_nil(a); - assert(is_initialized(a), "`Int` was not properly initialized.", loc); + assert_if_nil(a) + assert(is_initialized(a), "`Int` was not properly initialized.", loc) } zero_unused :: proc(dest: ^Int, old_used := -1) { - assert_if_nil(dest); + assert_if_nil(dest) if ! #force_inline is_initialized(dest) { return; } #force_inline internal_zero_unused(dest, old_used); } clear_if_uninitialized_single :: proc(arg: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(arg); - return #force_inline internal_clear_if_uninitialized_single(arg, allocator); + assert_if_nil(arg) + return #force_inline internal_clear_if_uninitialized_single(arg, allocator) } clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocator) -> (err: Error) { - args := args; - assert_if_nil(..args); + args := args + assert_if_nil(..args) for i in &args { #force_inline internal_clear_if_uninitialized_single(i, allocator) or_return; } - return err; + return err } -clear_if_uninitialized :: proc {clear_if_uninitialized_single, clear_if_uninitialized_multi, }; +clear_if_uninitialized :: proc {clear_if_uninitialized_single, clear_if_uninitialized_multi, } error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) { if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable; } - return nil; + return nil } error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) { for i in args { if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable; } } - return nil; + return nil } -error_if_immutable :: proc {error_if_immutable_single, error_if_immutable_multi, }; +error_if_immutable :: proc {error_if_immutable_single, error_if_immutable_multi, } /* Allocates several `Int`s at once. */ int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(..integers); + assert_if_nil(..integers) - integers := integers; + integers := integers for a in &integers { #force_inline internal_clear(a, true, allocator) or_return; } - return nil; + return nil } -init_multi :: proc { int_init_multi, }; +init_multi :: proc { int_init_multi, } copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0), allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Check that `src` is usable and `dest` isn't immutable. */ - assert_if_nil(dest, src); + assert_if_nil(dest, src) #force_inline internal_clear_if_uninitialized(src) or_return; - return #force_inline internal_copy_digits(dest, src, digits, offset); + return #force_inline internal_copy_digits(dest, src, digits, offset) } /* @@ -451,17 +451,17 @@ copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0), allocator := Typically very fast. Also fixes the sign if there are no more leading digits. */ clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; for a.used > 0 && a.digit[a.used - 1] == 0 { - a.used -= 1; + a.used -= 1 } if z, _ := is_zero(a); z { - a.sign = .Zero_or_Positive; + a.sign = .Zero_or_Positive } - return nil; + return nil } @@ -469,15 +469,15 @@ clamp :: proc(a: ^Int, allocator := context.allocator) -> (err: Error) { Size binary representation */ int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocator) -> (size_in_bytes: int, err: Error) { - assert_if_nil(a); + assert_if_nil(a) #force_inline internal_clear_if_uninitialized(a, allocator) or_return; - size_in_bits := internal_count_bits(a); + size_in_bits := internal_count_bits(a) - size_in_bytes = (size_in_bits / 8); - size_in_bytes += 0 if size_in_bits % 8 == 0 else 1; - size_in_bytes += 1 if signed else 0; - return; + size_in_bytes = (size_in_bits / 8) + size_in_bytes += 0 if size_in_bits % 8 == 0 else 1 + size_in_bytes += 1 if signed else 0 + return } /* @@ -485,22 +485,22 @@ int_to_bytes_size :: proc(a: ^Int, signed := false, allocator := context.allocat If `a` is negative and we ask for the default unsigned representation, we return abs(a). */ int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; - l := len(buf); + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return + l := len(buf) if size_in_bytes > l { return .Buffer_Overflow; } - size_in_bits := internal_count_bits(a); - i := 0; + size_in_bits := internal_count_bits(a) + i := 0 if signed { - buf[l - 1] = 1 if a.sign == .Negative else 0; + buf[l - 1] = 1 if a.sign == .Negative else 0 } for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(a, offset, 8); - buf[i] = u8(bits & 255); i += 1; + bits, _ := internal_int_bitfield_extract(a, offset, 8) + buf[i] = u8(bits & 255); i += 1 } - return; + return } /* @@ -508,23 +508,23 @@ int_to_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := co If `a` is negative and we ask for the default unsigned representation, we return abs(a). */ int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; - l := len(buf); + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return + l := len(buf) if size_in_bytes > l { return .Buffer_Overflow; } - size_in_bits := internal_count_bits(a); - i := l - 1; + size_in_bits := internal_count_bits(a) + i := l - 1 if signed { - buf[0] = 1 if a.sign == .Negative else 0; + buf[0] = 1 if a.sign == .Negative else 0 } for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(a, offset, 8); - buf[i] = u8(bits & 255); i -= 1; + bits, _ := internal_int_bitfield_extract(a, offset, 8) + buf[i] = u8(bits & 255); i -= 1 } - return; + return } /* @@ -532,35 +532,35 @@ int_to_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := conte If `a` is negative when asking for an unsigned number, we return an error like Python does. */ int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) if !signed && a.sign == .Negative { return .Invalid_Argument; } - l := len(buf); - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; + l := len(buf) + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return if size_in_bytes > l { return .Buffer_Overflow; } if a.sign == .Negative { - t := &Int{}; - defer destroy(t); - internal_complement(t, a, allocator) or_return; + t := &Int{} + defer destroy(t) + internal_complement(t, a, allocator) or_return - size_in_bits := internal_count_bits(t); - i := 0; + size_in_bits := internal_count_bits(t) + i := 0 for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(t, offset, 8); - buf[i] = 255 - u8(bits & 255); i += 1; + bits, _ := internal_int_bitfield_extract(t, offset, 8) + buf[i] = 255 - u8(bits & 255); i += 1 } - buf[l-1] = 255; + buf[l-1] = 255 } else { - size_in_bits := internal_count_bits(a); - i := 0; + size_in_bits := internal_count_bits(a) + i := 0 for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(a, offset, 8); - buf[i] = u8(bits & 255); i += 1; + bits, _ := internal_int_bitfield_extract(a, offset, 8) + buf[i] = u8(bits & 255); i += 1 } } - return; + return } /* @@ -568,29 +568,29 @@ int_to_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocato If `a` is negative when asking for an unsigned number, we return an error like Python does. */ int_to_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); + assert_if_nil(a) if !signed && a.sign == .Negative { return .Invalid_Argument; } if a.sign == .Zero_or_Positive { return int_to_bytes_big(a, buf, signed, allocator); } - l := len(buf); - size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return; + l := len(buf) + size_in_bytes := int_to_bytes_size(a, signed, allocator) or_return if size_in_bytes > l { return .Buffer_Overflow; } - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) - internal_complement(t, a, allocator) or_return; + internal_complement(t, a, allocator) or_return - size_in_bits := internal_count_bits(t); - i := l - 1; + size_in_bits := internal_count_bits(t) + i := l - 1 for offset := 0; offset < size_in_bits; offset += 8 { - bits, _ := internal_int_bitfield_extract(t, offset, 8); - buf[i] = 255 - u8(bits & 255); i -= 1; + bits, _ := internal_int_bitfield_extract(t, offset, 8) + buf[i] = 255 - u8(bits & 255); i -= 1 } - buf[0] = 255; + buf[0] = 255 - return; + return } /* @@ -598,36 +598,36 @@ int_to_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator : Sign is detected from the first byte if `signed` is true. */ int_from_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[0] == 0 else .Negative; - buf = buf[1:]; + sign = .Zero_or_Positive if buf[0] == 0 else .Negative + buf = buf[1:] } for v in buf { - internal_shl(a, a, 8) or_return; - a.digit[0] |= DIGIT(v); + internal_shl(a, a, 8) or_return + a.digit[0] |= DIGIT(v) } - a.sign = sign; - a.used = size_in_digits; - return internal_clamp(a); + a.sign = sign + a.used = size_in_digits + return internal_clamp(a) } /* @@ -635,45 +635,45 @@ int_from_bytes_big :: proc(a: ^Int, buf: []u8, signed := false, allocator := con Sign is detected from the first byte if `signed` is true. */ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[0] == 0 else .Negative; - buf = buf[1:]; + sign = .Zero_or_Positive if buf[0] == 0 else .Negative + buf = buf[1:] } for v in buf { - internal_shl(a, a, 8) or_return; + internal_shl(a, a, 8) or_return if signed && sign == .Negative { - a.digit[0] |= DIGIT(255 - v); + a.digit[0] |= DIGIT(255 - v) } else { - a.digit[0] |= DIGIT(v); + a.digit[0] |= DIGIT(v) } } - a.sign = sign; - a.used = size_in_digits; - internal_clamp(a) or_return; + a.sign = sign + a.used = size_in_digits + internal_clamp(a) or_return if signed && sign == .Negative { - return internal_sub(a, a, 1); + return internal_sub(a, a, 1) } - return nil; + return nil } /* @@ -681,37 +681,37 @@ int_from_bytes_big_python :: proc(a: ^Int, buf: []u8, signed := false, allocator Sign is detected from the last byte if `signed` is true. */ int_from_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative; - buf = buf[:l-1]; - l -= 1; + sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative + buf = buf[:l-1] + l -= 1 } for _, i in buf { - internal_shl(a, a, 8) or_return; - a.digit[0] |= DIGIT(buf[l-i-1]); + internal_shl(a, a, 8) or_return + a.digit[0] |= DIGIT(buf[l-i-1]) } - a.sign = sign; - a.used = size_in_digits; - return internal_clamp(a); + a.sign = sign + a.used = size_in_digits + return internal_clamp(a) } /* @@ -719,67 +719,67 @@ int_from_bytes_little :: proc(a: ^Int, buf: []u8, signed := false, allocator := Sign is detected from the first byte if `signed` is true. */ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a); - buf := buf; - l := len(buf); + assert_if_nil(a) + buf := buf + l := len(buf) if l == 0 { return .Invalid_Argument; } - sign: Sign; - size_in_bits := l * 8; + sign: Sign + size_in_bits := l * 8 if signed { /* First byte denotes the sign. */ - size_in_bits -= 8; + size_in_bits -= 8 } - size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS; - size_in_digits += 0 if size_in_bits % 8 == 0 else 1; - internal_zero(a, false, allocator) or_return; - internal_grow(a, size_in_digits, false, allocator) or_return; + size_in_digits := (size_in_bits + _DIGIT_BITS - 1) / _DIGIT_BITS + size_in_digits += 0 if size_in_bits % 8 == 0 else 1 + internal_zero(a, false, allocator) or_return + internal_grow(a, size_in_digits, false, allocator) or_return if signed { - sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative; - buf = buf[:l-1]; - l -= 1; + sign = .Zero_or_Positive if buf[l-1] == 0 else .Negative + buf = buf[:l-1] + l -= 1 } for _, i in buf { - internal_shl(a, a, 8) or_return; + internal_shl(a, a, 8) or_return if signed && sign == .Negative { - a.digit[0] |= DIGIT(255 - buf[l-i-1]); + a.digit[0] |= DIGIT(255 - buf[l-i-1]) } else { - a.digit[0] |= DIGIT(buf[l-i-1]); + a.digit[0] |= DIGIT(buf[l-i-1]) } } - a.sign = sign; - a.used = size_in_digits; - internal_clamp(a) or_return; + a.sign = sign + a.used = size_in_digits + internal_clamp(a) or_return if signed && sign == .Negative { - return internal_sub(a, a, 1); + return internal_sub(a, a, 1) } - return nil; + return nil } /* Initialize constants. */ -INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}; +INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{} initialize_constants :: proc() -> (res: int) { - internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable}; - internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable}; - internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable}; + internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable} + internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable} + internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable} /* We set these special values to -1 or 1 so they don't get mistake for zero accidentally. This allows for shortcut tests of is_zero as .used == 0. */ - internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN}; - internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf}; - internal_set( INT_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf}; + internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN} + internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf} + internal_set( INT_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf} - return _DEFAULT_MUL_KARATSUBA_CUTOFF; + return _DEFAULT_MUL_KARATSUBA_CUTOFF } /* @@ -787,14 +787,14 @@ initialize_constants :: proc() -> (res: int) { Optional for an EXE, as this would be called at the very end of a process. */ destroy_constants :: proc() { - internal_destroy(INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN); + internal_destroy(INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN) } assert_if_nil :: #force_inline proc(integers: ..^Int, loc := #caller_location) { - integers := integers; + integers := integers for i in &integers { - assert(i != nil, "(nil)", loc); + assert(i != nil, "(nil)", loc) } } diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 9422067ae..033bc11a2 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -43,43 +43,43 @@ import rnd "core:math/rand" `dest`, `a` and `b` != `nil` and have been initalized. */ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - dest := dest; x := a; y := b; - context.allocator = allocator; + dest := dest; x := a; y := b + context.allocator = allocator - old_used, min_used, max_used, i: int; + old_used, min_used, max_used, i: int if x.used < y.used { - x, y = y, x; + x, y = y, x } - min_used = y.used; - max_used = x.used; - old_used = dest.used; + min_used = y.used + max_used = x.used + old_used = dest.used - internal_grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)) or_return; - dest.used = max_used + 1; + internal_grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)) or_return + dest.used = max_used + 1 /* All parameters have been initialized. */ /* Zero the carry */ - carry := DIGIT(0); + carry := DIGIT(0) #no_bounds_check for i = 0; i < min_used; i += 1 { /* Compute the sum one _DIGIT at a time. dest[i] = a[i] + b[i] + carry; */ - dest.digit[i] = x.digit[i] + y.digit[i] + carry; + dest.digit[i] = x.digit[i] + y.digit[i] + carry /* Compute carry */ - carry = dest.digit[i] >> _DIGIT_BITS; + carry = dest.digit[i] >> _DIGIT_BITS /* Mask away carry from result digit. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } if min_used != max_used { @@ -88,32 +88,32 @@ internal_int_add_unsigned :: proc(dest, a, b: ^Int, allocator := context.allocat If A or B has more digits, add those in. */ #no_bounds_check for ; i < max_used; i += 1 { - dest.digit[i] = x.digit[i] + carry; + dest.digit[i] = x.digit[i] + carry /* Compute carry */ - carry = dest.digit[i] >> _DIGIT_BITS; + carry = dest.digit[i] >> _DIGIT_BITS /* Mask away carry from result digit. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } } /* Add remaining carry. */ - dest.digit[i] = carry; + dest.digit[i] = carry /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_add_unsigned :: proc { internal_int_add_unsigned, }; +internal_add_unsigned :: proc { internal_int_add_unsigned, } /* Low-level addition, signed. Handbook of Applied Cryptography, algorithm 14.7. @@ -122,14 +122,14 @@ internal_add_unsigned :: proc { internal_int_add_unsigned, }; `dest`, `a` and `b` != `nil` and have been initalized. */ internal_int_add_signed :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - x := a; y := b; - context.allocator = allocator; + x := a; y := b + context.allocator = allocator /* Handle both negative or both positive. */ if x.sign == y.sign { - dest.sign = x.sign; - return #force_inline internal_int_add_unsigned(dest, x, y); + dest.sign = x.sign + return #force_inline internal_int_add_unsigned(dest, x, y) } /* @@ -138,13 +138,13 @@ internal_int_add_signed :: proc(dest, a, b: ^Int, allocator := context.allocator The result gets the sign of the one with the greater magnitude. */ if #force_inline internal_cmp_mag(a, b) == -1 { - x, y = y, x; + x, y = y, x } - dest.sign = x.sign; - return #force_inline internal_int_sub_unsigned(dest, x, y); + dest.sign = x.sign + return #force_inline internal_int_sub_unsigned(dest, x, y) } -internal_add_signed :: proc { internal_int_add_signed, }; +internal_add_signed :: proc { internal_int_add_signed, } /* Low-level addition Int+DIGIT, signed. Handbook of Applied Cryptography, algorithm 14.7. @@ -154,9 +154,9 @@ internal_add_signed :: proc { internal_int_add_signed, }; `dest` is large enough (a.used + 1) to fit result. */ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - internal_grow(dest, a.used + 1) or_return; + internal_grow(dest, a.used + 1) or_return /* Fast paths for destination and input Int being the same. */ @@ -165,17 +165,17 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context Fast path for dest.digit[0] + digit fits in dest.digit[0] without overflow. */ if dest.sign == .Zero_or_Positive && (dest.digit[0] + digit < _DIGIT_MAX) { - dest.digit[0] += digit; - dest.used += 1; - return internal_clamp(dest); + dest.digit[0] += digit + dest.used += 1 + return internal_clamp(dest) } /* Can be subtracted from dest.digit[0] without underflow. */ if a.sign == .Negative && (dest.digit[0] > digit) { - dest.digit[0] -= digit; - dest.used += 1; - return internal_clamp(dest); + dest.digit[0] -= digit + dest.used += 1 + return internal_clamp(dest) } } @@ -186,7 +186,7 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context /* Temporarily fix `a`'s sign. */ - a.sign = .Zero_or_Positive; + a.sign = .Zero_or_Positive /* dest = |a| - digit */ @@ -194,22 +194,22 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context /* Restore a's sign. */ - a.sign = .Negative; - return err; + a.sign = .Negative + return err } /* Restore sign and set `dest` sign. */ - a.sign = .Negative; - dest.sign = .Negative; + a.sign = .Negative + dest.sign = .Negative - return internal_clamp(dest); + return internal_clamp(dest) } /* Remember the currently used number of digits in `dest`. */ - old_used := dest.used; + old_used := dest.used /* If `a` is positive @@ -218,53 +218,53 @@ internal_int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context /* Add digits, use `carry`. */ - i: int; - carry := digit; + i: int + carry := digit #no_bounds_check for i = 0; i < a.used; i += 1 { - dest.digit[i] = a.digit[i] + carry; - carry = dest.digit[i] >> _DIGIT_BITS; - dest.digit[i] &= _MASK; + dest.digit[i] = a.digit[i] + carry + carry = dest.digit[i] >> _DIGIT_BITS + dest.digit[i] &= _MASK } /* Set final carry. */ - dest.digit[i] = carry; + dest.digit[i] = carry /* Set `dest` size. */ - dest.used = a.used + 1; + dest.used = a.used + 1 } else { /* `a` was negative and |a| < digit. */ - dest.used = 1; + dest.used = 1 /* The result is a single DIGIT. */ - dest.digit[0] = digit - a.digit[0] if a.used == 1 else digit; + dest.digit[0] = digit - a.digit[0] if a.used == 1 else digit } /* Sign is always positive. */ - dest.sign = .Zero_or_Positive; + dest.sign = .Zero_or_Positive /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_add :: proc { internal_int_add_signed, internal_int_add_digit, }; +internal_add :: proc { internal_int_add_signed, internal_int_add_digit, } internal_int_incr :: proc(dest: ^Int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_add(dest, dest, 1); + return #force_inline internal_add(dest, dest, 1) } -internal_incr :: proc { internal_int_incr, }; +internal_incr :: proc { internal_int_incr, } /* Low-level subtraction, dest = number - decrease. Assumes |number| > |decrease|. @@ -274,66 +274,66 @@ internal_incr :: proc { internal_int_incr, }; `dest`, `number` and `decrease` != `nil` and have been initalized. */ internal_int_sub_unsigned :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - dest := dest; x := number; y := decrease; - old_used := dest.used; - min_used := y.used; - max_used := x.used; - i: int; + dest := dest; x := number; y := decrease + old_used := dest.used + min_used := y.used + max_used := x.used + i: int - grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)) or_return; - dest.used = max_used; + grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)) or_return + dest.used = max_used /* All parameters have been initialized. */ - borrow := DIGIT(0); + borrow := DIGIT(0) #no_bounds_check for i = 0; i < min_used; i += 1 { - dest.digit[i] = (x.digit[i] - y.digit[i] - borrow); + dest.digit[i] = (x.digit[i] - y.digit[i] - borrow) /* borrow = carry bit of dest[i] Note this saves performing an AND operation since if a carry does occur, it will propagate all the way to the MSB. As a result a single shift is enough to get the carry. */ - borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1); + borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1) /* Clear borrow from dest[i]. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } /* Now copy higher words if any, e.g. if A has more digits than B */ #no_bounds_check for ; i < max_used; i += 1 { - dest.digit[i] = x.digit[i] - borrow; + dest.digit[i] = x.digit[i] - borrow /* borrow = carry bit of dest[i] Note this saves performing an AND operation since if a carry does occur, it will propagate all the way to the MSB. As a result a single shift is enough to get the carry. */ - borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1); + borrow = dest.digit[i] >> ((size_of(DIGIT) * 8) - 1) /* Clear borrow from dest[i]. */ - dest.digit[i] &= _MASK; + dest.digit[i] &= _MASK } /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_sub_unsigned :: proc { internal_int_sub_unsigned, }; +internal_sub_unsigned :: proc { internal_int_sub_unsigned, } /* Low-level subtraction, signed. Handbook of Applied Cryptography, algorithm 14.9. @@ -343,16 +343,16 @@ internal_sub_unsigned :: proc { internal_int_sub_unsigned, }; `dest`, `number` and `decrease` != `nil` and have been initalized. */ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - number := number; decrease := decrease; + number := number; decrease := decrease if number.sign != decrease.sign { /* Subtract a negative from a positive, OR subtract a positive from a negative. In either case, ADD their magnitudes and use the sign of the first number. */ - dest.sign = number.sign; - return #force_inline internal_int_add_unsigned(dest, number, decrease); + dest.sign = number.sign + return #force_inline internal_int_add_unsigned(dest, number, decrease) } /* @@ -364,16 +364,16 @@ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := conte The second has a larger magnitude. The result has the *opposite* sign from the first number. */ - dest.sign = .Negative if number.sign == .Zero_or_Positive else .Zero_or_Positive; - number, decrease = decrease, number; + dest.sign = .Negative if number.sign == .Zero_or_Positive else .Zero_or_Positive + number, decrease = decrease, number } else { /* The first has a larger or equal magnitude. Copy the sign from the first. */ - dest.sign = number.sign; + dest.sign = number.sign } - return #force_inline internal_int_sub_unsigned(dest, number, decrease); + return #force_inline internal_int_sub_unsigned(dest, number, decrease) } /* @@ -385,11 +385,11 @@ internal_int_sub_signed :: proc(dest, number, decrease: ^Int, allocator := conte `dest` is large enough (number.used + 1) to fit result. */ internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - internal_grow(dest, number.used + 1) or_return; + internal_grow(dest, number.used + 1) or_return - dest := dest; digit := digit; + dest := dest; digit := digit /* All parameters have been initialized. @@ -400,15 +400,15 @@ internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := co Fast path for `dest` is negative and unsigned addition doesn't overflow the lowest digit. */ if dest.sign == .Negative && (dest.digit[0] + digit < _DIGIT_MAX) { - dest.digit[0] += digit; - return nil; + dest.digit[0] += digit + return nil } /* Can be subtracted from dest.digit[0] without underflow. */ if number.sign == .Zero_or_Positive && (dest.digit[0] > digit) { - dest.digit[0] -= digit; - return nil; + dest.digit[0] -= digit + return nil } } @@ -416,58 +416,58 @@ internal_int_sub_digit :: proc(dest, number: ^Int, digit: DIGIT, allocator := co If `a` is negative, just do an unsigned addition (with fudged signs). */ if number.sign == .Negative { - t := number; - t.sign = .Zero_or_Positive; + t := number + t.sign = .Zero_or_Positive - err = #force_inline internal_int_add_digit(dest, t, digit); - dest.sign = .Negative; + err = #force_inline internal_int_add_digit(dest, t, digit) + dest.sign = .Negative - internal_clamp(dest); - return err; + internal_clamp(dest) + return err } - old_used := dest.used; + old_used := dest.used /* if `a`<= digit, simply fix the single digit. */ if number.used == 1 && (number.digit[0] <= digit) || number.used == 0 { - dest.digit[0] = digit - number.digit[0] if number.used == 1 else digit; - dest.sign = .Negative; - dest.used = 1; + dest.digit[0] = digit - number.digit[0] if number.used == 1 else digit + dest.sign = .Negative + dest.used = 1 } else { - dest.sign = .Zero_or_Positive; - dest.used = number.used; + dest.sign = .Zero_or_Positive + dest.used = number.used /* Subtract with carry. */ - carry := digit; + carry := digit #no_bounds_check for i := 0; i < number.used; i += 1 { - dest.digit[i] = number.digit[i] - carry; - carry = dest.digit[i] >> (_DIGIT_TYPE_BITS - 1); - dest.digit[i] &= _MASK; + dest.digit[i] = number.digit[i] - carry + carry = dest.digit[i] >> (_DIGIT_TYPE_BITS - 1) + dest.digit[i] &= _MASK } } /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - return internal_clamp(dest); + return internal_clamp(dest) } -internal_sub :: proc { internal_int_sub_signed, internal_int_sub_digit, }; +internal_sub :: proc { internal_int_sub_signed, internal_int_sub_digit, } internal_int_decr :: proc(dest: ^Int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_sub(dest, dest, 1); + return #force_inline internal_sub(dest, dest, 1) } -internal_decr :: proc { internal_int_decr, }; +internal_decr :: proc { internal_int_decr, } /* dest = src / 2 @@ -477,38 +477,38 @@ internal_decr :: proc { internal_int_decr, }; We make no allocations here. */ internal_int_shr1 :: proc(dest, src: ^Int) -> (err: Error) { - old_used := dest.used; dest.used = src.used; + old_used := dest.used; dest.used = src.used /* Carry */ - fwd_carry := DIGIT(0); + fwd_carry := DIGIT(0) #no_bounds_check for x := dest.used - 1; x >= 0; x -= 1 { /* Get the carry for the next iteration. */ - src_digit := src.digit[x]; - carry := src_digit & 1; + src_digit := src.digit[x] + carry := src_digit & 1 /* Shift the current digit, add in carry and store. */ - dest.digit[x] = (src_digit >> 1) | (fwd_carry << (_DIGIT_BITS - 1)); + dest.digit[x] = (src_digit >> 1) | (fwd_carry << (_DIGIT_BITS - 1)) /* Forward carry to next iteration. */ - fwd_carry = carry; + fwd_carry = carry } /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) /* Adjust dest.used based on leading zeroes. */ - dest.sign = src.sign; - return internal_clamp(dest); + dest.sign = src.sign + return internal_clamp(dest) } /* @@ -516,121 +516,121 @@ internal_int_shr1 :: proc(dest, src: ^Int) -> (err: Error) { dest = src << 1 */ internal_int_shl1 :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Grow `dest` to accommodate the additional bits. */ - digits_needed := dest.used + 1; - internal_grow(dest, digits_needed) or_return; - dest.used = digits_needed; + digits_needed := dest.used + 1 + internal_grow(dest, digits_needed) or_return + dest.used = digits_needed - mask := (DIGIT(1) << uint(1)) - DIGIT(1); - shift := DIGIT(_DIGIT_BITS - 1); - carry := DIGIT(0); + mask := (DIGIT(1) << uint(1)) - DIGIT(1) + shift := DIGIT(_DIGIT_BITS - 1) + carry := DIGIT(0) #no_bounds_check for x:= 0; x < dest.used; x+= 1 { - fwd_carry := (dest.digit[x] >> shift) & mask; - dest.digit[x] = (dest.digit[x] << uint(1) | carry) & _MASK; - carry = fwd_carry; + fwd_carry := (dest.digit[x] >> shift) & mask + dest.digit[x] = (dest.digit[x] << uint(1) | carry) & _MASK + carry = fwd_carry } /* Use final carry. */ if carry != 0 { - dest.digit[dest.used] = carry; - dest.used += 1; + dest.digit[dest.used] = carry + dest.used += 1 } - return internal_clamp(dest); + return internal_clamp(dest) } /* Multiply by a DIGIT. */ internal_int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; - assert_if_nil(dest, src); + context.allocator = allocator + assert_if_nil(dest, src) if multiplier == 0 { - return internal_zero(dest); + return internal_zero(dest) } if multiplier == 1 { - return internal_copy(dest, src); + return internal_copy(dest, src) } /* Power of two? */ if multiplier == 2 { - return #force_inline internal_int_shl1(dest, src); + return #force_inline internal_int_shl1(dest, src) } if #force_inline platform_int_is_power_of_two(int(multiplier)) { - ix := internal_log(multiplier, 2) or_return; - return internal_shl(dest, src, ix); + ix := internal_log(multiplier, 2) or_return + return internal_shl(dest, src, ix) } /* Ensure `dest` is big enough to hold `src` * `multiplier`. */ - grow(dest, max(src.used + 1, _DEFAULT_DIGIT_COUNT)) or_return; + grow(dest, max(src.used + 1, _DEFAULT_DIGIT_COUNT)) or_return /* Save the original used count. */ - old_used := dest.used; + old_used := dest.used /* Set the sign. */ - dest.sign = src.sign; + dest.sign = src.sign /* Set up carry. */ - carry := _WORD(0); + carry := _WORD(0) /* Compute columns. */ - ix := 0; + ix := 0 #no_bounds_check for ; ix < src.used; ix += 1 { /* Compute product and carry sum for this term */ - product := carry + _WORD(src.digit[ix]) * _WORD(multiplier); + product := carry + _WORD(src.digit[ix]) * _WORD(multiplier) /* Mask off higher bits to get a single DIGIT. */ - dest.digit[ix] = DIGIT(product & _WORD(_MASK)); + dest.digit[ix] = DIGIT(product & _WORD(_MASK)) /* Send carry into next iteration */ - carry = product >> _DIGIT_BITS; + carry = product >> _DIGIT_BITS } /* Store final carry [if any] and increment used. */ - dest.digit[ix] = DIGIT(carry); - dest.used = src.used + 1; + dest.digit[ix] = DIGIT(carry) + dest.used = src.used + 1 /* Zero remainder. */ - internal_zero_unused(dest, old_used); + internal_zero_unused(dest, old_used) - return internal_clamp(dest); + return internal_clamp(dest) } /* High level multiplication (handles sign). */ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Early out for `multiplier` is zero; Set `dest` to zero. */ if multiplier.used == 0 || src.used == 0 { return internal_zero(dest); } - neg := src.sign != multiplier.sign; + neg := src.sign != multiplier.sign if src == multiplier { /* @@ -640,19 +640,19 @@ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.alloc /* Use Toom-Cook? */ - err = #force_inline _private_int_sqr_toom(dest, src); + err = #force_inline _private_int_sqr_toom(dest, src) } else if src.used >= SQR_KARATSUBA_CUTOFF { /* Karatsuba? */ - err = #force_inline _private_int_sqr_karatsuba(dest, src); + err = #force_inline _private_int_sqr_karatsuba(dest, src) } else if ((src.used * 2) + 1) < _WARRAY && src.used < (_MAX_COMBA / 2) { /* Fast comba? */ - err = #force_inline _private_int_sqr_comba(dest, src); + err = #force_inline _private_int_sqr_comba(dest, src) } else { - err = #force_inline _private_int_sqr(dest, src); + err = #force_inline _private_int_sqr(dest, src) } } else { /* @@ -664,23 +664,23 @@ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.alloc * was actually slower on the author's machine, but YMMV. */ - min_used := min(src.used, multiplier.used); - max_used := max(src.used, multiplier.used); - digits := src.used + multiplier.used + 1; + min_used := min(src.used, multiplier.used) + max_used := max(src.used, multiplier.used) + digits := src.used + multiplier.used + 1 if min_used >= MUL_KARATSUBA_CUTOFF && (max_used / 2) >= MUL_KARATSUBA_CUTOFF && max_used >= (2 * min_used) { /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ - err = _private_int_mul_balance(dest, src, multiplier); + err = _private_int_mul_balance(dest, src, multiplier) } else if min_used >= MUL_TOOM_CUTOFF { /* Toom path commented out until it no longer fails Factorial 10k or 100k, as reveaved in the long test. */ - err = #force_inline _private_int_mul_toom(dest, src, multiplier); + err = #force_inline _private_int_mul_toom(dest, src, multiplier) } else if min_used >= MUL_KARATSUBA_CUTOFF { - err = #force_inline _private_int_mul_karatsuba(dest, src, multiplier); + err = #force_inline _private_int_mul_karatsuba(dest, src, multiplier) } else if digits < _WARRAY && min_used <= _MAX_COMBA { /* Can we use the fast multiplier? @@ -688,24 +688,24 @@ internal_int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.alloc * have less than MP_WARRAY digits and the number of * digits won't affect carry propagation */ - err = #force_inline _private_int_mul_comba(dest, src, multiplier, digits); + err = #force_inline _private_int_mul_comba(dest, src, multiplier, digits) } else { - err = #force_inline _private_int_mul(dest, src, multiplier, digits); + err = #force_inline _private_int_mul(dest, src, multiplier, digits) } } - dest.sign = .Negative if dest.used > 0 && neg else .Zero_or_Positive; - return err; + dest.sign = .Negative if dest.used > 0 && neg else .Zero_or_Positive + return err } -internal_mul :: proc { internal_int_mul, internal_int_mul_digit, }; +internal_mul :: proc { internal_int_mul, internal_int_mul_digit, } internal_sqr :: proc (dest, src: ^Int, allocator := context.allocator) -> (res: Error) { /* We call `internal_mul` and not e.g. `_private_int_sqr` because the former will dispatch to the optimal implementation depending on the source. */ - return #force_inline internal_mul(dest, src, src, allocator); + return #force_inline internal_mul(dest, src, src, allocator) } /* @@ -714,37 +714,37 @@ internal_sqr :: proc (dest, src: ^Int, allocator := context.allocator) -> (res: `numerator` and `denominator` are expected not to be `nil` and have been initialized. */ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if denominator.used == 0 { return .Division_by_Zero; } /* If numerator < denominator then quotient = 0, remainder = numerator. */ if #force_inline internal_cmp_mag(numerator, denominator) == -1 { if remainder != nil { - internal_copy(remainder, numerator) or_return; + internal_copy(remainder, numerator) or_return } if quotient != nil { - internal_zero(quotient); + internal_zero(quotient) } - return nil; + return nil } if (denominator.used > 2 * MUL_KARATSUBA_CUTOFF) && (denominator.used <= (numerator.used / 3) * 2) { - assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set."); - err = _private_int_div_recursive(quotient, remainder, numerator, denominator); + assert(denominator.used >= 160 && numerator.used >= 240, "MUL_KARATSUBA_CUTOFF global not properly set.") + err = _private_int_div_recursive(quotient, remainder, numerator, denominator) // err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator); } else { when true { - err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator); + err = #force_inline _private_int_div_school(quotient, remainder, numerator, denominator) } else { /* NOTE(Jeroen): We no longer need or use `_private_int_div_small`. We'll keep it around for a bit until we're reasonably certain div_school is bug free. */ - err = _private_int_div_small(quotient, remainder, numerator, denominator); + err = _private_int_div_small(quotient, remainder, numerator, denominator) } } - return; + return } /* @@ -752,7 +752,7 @@ internal_int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, a The quotient is optional and may be passed a nil. */ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Cannot divide by zero. @@ -764,9 +764,9 @@ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, */ if denominator == 1 || numerator.used == 0 { if quotient != nil { - return 0, internal_copy(quotient, numerator); + return 0, internal_copy(quotient, numerator) } - return 0, err; + return 0, err } /* Power of two? @@ -774,75 +774,75 @@ internal_int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, if denominator == 2 { if numerator.used > 0 && numerator.digit[0] & 1 != 0 { // Remainder is 1 if numerator is odd. - remainder = 1; + remainder = 1 } if quotient == nil { - return remainder, nil; + return remainder, nil } - return remainder, internal_shr(quotient, numerator, 1); + return remainder, internal_shr(quotient, numerator, 1) } - ix: int; + ix: int if platform_int_is_power_of_two(int(denominator)) { - ix = 1; + ix = 1 for ix < _DIGIT_BITS && denominator != (1 << uint(ix)) { - ix += 1; + ix += 1 } - remainder = numerator.digit[0] & ((1 << uint(ix)) - 1); + remainder = numerator.digit[0] & ((1 << uint(ix)) - 1) if quotient == nil { - return remainder, nil; + return remainder, nil } - return remainder, internal_shr(quotient, numerator, int(ix)); + return remainder, internal_shr(quotient, numerator, int(ix)) } /* Three? */ if denominator == 3 { - return _private_int_div_3(quotient, numerator); + return _private_int_div_3(quotient, numerator) } /* No easy answer [c'est la vie]. Just division. */ - q := &Int{}; + q := &Int{} - internal_grow(q, numerator.used) or_return; + internal_grow(q, numerator.used) or_return - q.used = numerator.used; - q.sign = numerator.sign; + q.used = numerator.used + q.sign = numerator.sign - w := _WORD(0); + w := _WORD(0) for ix = numerator.used - 1; ix >= 0; ix -= 1 { - t := DIGIT(0); - w = (w << _WORD(_DIGIT_BITS) | _WORD(numerator.digit[ix])); + t := DIGIT(0) + w = (w << _WORD(_DIGIT_BITS) | _WORD(numerator.digit[ix])) if w >= _WORD(denominator) { - t = DIGIT(w / _WORD(denominator)); - w -= _WORD(t) * _WORD(denominator); + t = DIGIT(w / _WORD(denominator)) + w -= _WORD(t) * _WORD(denominator) } - q.digit[ix] = t; + q.digit[ix] = t } - remainder = DIGIT(w); + remainder = DIGIT(w) if quotient != nil { - internal_clamp(q); - internal_swap(q, quotient); + internal_clamp(q) + internal_swap(q, quotient) } - internal_destroy(q); - return remainder, nil; + internal_destroy(q) + return remainder, nil } -internal_divmod :: proc { internal_int_divmod, internal_int_divmod_digit, }; +internal_divmod :: proc { internal_int_divmod, internal_int_divmod_digit, } /* Asssumes quotient, numerator and denominator to have been initialized and not to be nil. */ internal_int_div :: proc(quotient, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_int_divmod(quotient, nil, numerator, denominator, allocator); + return #force_inline internal_int_divmod(quotient, nil, numerator, denominator, allocator) } -internal_div :: proc { internal_int_div, }; +internal_div :: proc { internal_int_div, } /* remainder = numerator % denominator. @@ -856,50 +856,50 @@ internal_int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := c if remainder.used == 0 || denominator.sign == remainder.sign { return nil; } - return #force_inline internal_add(remainder, remainder, numerator, allocator); + return #force_inline internal_add(remainder, remainder, numerator, allocator) } internal_int_mod_digit :: proc(numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) { - return internal_int_divmod_digit(nil, numerator, denominator, allocator); + return internal_int_divmod_digit(nil, numerator, denominator, allocator) } -internal_mod :: proc{ internal_int_mod, internal_int_mod_digit}; +internal_mod :: proc{ internal_int_mod, internal_int_mod_digit} /* remainder = (number + addend) % modulus. */ internal_int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_add(remainder, number, addend, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_addmod :: proc { internal_int_addmod, }; +internal_addmod :: proc { internal_int_addmod, } /* remainder = (number - decrease) % modulus. */ internal_int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_sub(remainder, number, decrease, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_submod :: proc { internal_int_submod, }; +internal_submod :: proc { internal_int_submod, } /* remainder = (number * multiplicand) % modulus. */ internal_int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_mul(remainder, number, multiplicand, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_mulmod :: proc { internal_int_mulmod, }; +internal_mulmod :: proc { internal_int_mulmod, } /* remainder = (number * number) % modulus. */ internal_int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) { #force_inline internal_sqr(remainder, number, allocator) or_return; - return #force_inline internal_mod(remainder, remainder, modulus, allocator); + return #force_inline internal_mod(remainder, remainder, modulus, allocator) } -internal_sqrmod :: proc { internal_int_sqrmod, }; +internal_sqrmod :: proc { internal_int_sqrmod, } @@ -908,26 +908,26 @@ internal_sqrmod :: proc { internal_int_sqrmod, }; This way we'll have to reallocate less, possibly not at all. */ internal_int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if n >= FACTORIAL_BINARY_SPLIT_CUTOFF { - return _private_int_factorial_binary_split(res, n); + return _private_int_factorial_binary_split(res, n) } - i := len(_factorial_table); + i := len(_factorial_table) if n < i { - return #force_inline internal_set(res, _factorial_table[n]); + return #force_inline internal_set(res, _factorial_table[n]) } #force_inline internal_set(res, _factorial_table[i - 1]) or_return; for { if err = #force_inline internal_mul(res, res, DIGIT(i)); err != nil || i == n { - return err; + return err } - i += 1; + i += 1 } - return nil; + return nil } /* @@ -939,7 +939,7 @@ internal_int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator internal_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) { if res_gcd == nil && res_lcm == nil { return nil; } - return #force_inline _private_int_gcd_lcm(res_gcd, res_lcm, a, b, allocator); + return #force_inline _private_int_gcd_lcm(res_gcd, res_lcm, a, b, allocator) } /* @@ -956,29 +956,29 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator : /* If the modulus is larger than the value, return the value. */ - internal_copy(remainder, numerator) or_return; + internal_copy(remainder, numerator) or_return if bits >= (numerator.used * _DIGIT_BITS) { - return; + return } /* Zero digits above the last digit of the modulus. */ - zero_count := (bits / _DIGIT_BITS); - zero_count += 0 if (bits % _DIGIT_BITS == 0) else 1; + zero_count := (bits / _DIGIT_BITS) + zero_count += 0 if (bits % _DIGIT_BITS == 0) else 1 /* Zero remainder. Special case, can't use `internal_zero_unused`. */ if zero_count > 0 { - mem.zero_slice(remainder.digit[zero_count:]); + mem.zero_slice(remainder.digit[zero_count:]) } /* Clear the digit that is not completely outside/inside the modulus. */ - remainder.digit[bits / _DIGIT_BITS] &= DIGIT(1 << DIGIT(bits % _DIGIT_BITS)) - DIGIT(1); - return internal_clamp(remainder); + remainder.digit[bits / _DIGIT_BITS] &= DIGIT(1 << DIGIT(bits % _DIGIT_BITS)) - DIGIT(1) + return internal_clamp(remainder) } /* @@ -997,37 +997,37 @@ internal_int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator : Assumes `a` not to be `nil`. */ internal_int_is_initialized :: #force_inline proc(a: ^Int) -> (initialized: bool) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; - return raw.cap >= _MIN_DIGIT_COUNT; + raw := transmute(mem.Raw_Dynamic_Array)a.digit + return raw.cap >= _MIN_DIGIT_COUNT } -internal_is_initialized :: proc { internal_int_is_initialized, }; +internal_is_initialized :: proc { internal_int_is_initialized, } /* This procedure will return `true` if the `Int` is zero, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_zero :: #force_inline proc(a: ^Int) -> (zero: bool) { - return a.used == 0; + return a.used == 0 } -internal_is_zero :: proc { internal_int_is_zero, }; +internal_is_zero :: proc { internal_int_is_zero, } /* This procedure will return `true` if the `Int` is positive, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_positive :: #force_inline proc(a: ^Int) -> (positive: bool) { - return a.sign == .Zero_or_Positive; + return a.sign == .Zero_or_Positive } -internal_is_positive :: proc { internal_int_is_positive, }; +internal_is_positive :: proc { internal_int_is_positive, } /* This procedure will return `true` if the `Int` is negative, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_negative :: #force_inline proc(a: ^Int) -> (negative: bool) { - return a.sign == .Negative; + return a.sign == .Negative } -internal_is_negative :: proc { internal_int_is_negative, }; +internal_is_negative :: proc { internal_int_is_negative, } /* This procedure will return `true` if the `Int` is even, `false` if not. @@ -1040,18 +1040,18 @@ internal_int_is_even :: #force_inline proc(a: ^Int) -> (even: bool) { `a.used` > 0 here, because the above handled `is_zero`. We don't need to explicitly test it. */ - return a.digit[0] & 1 == 0; + return a.digit[0] & 1 == 0 } -internal_is_even :: proc { internal_int_is_even, }; +internal_is_even :: proc { internal_int_is_even, } /* This procedure will return `true` if the `Int` is even, `false` if not. Assumes `a` not to be `nil`. */ internal_int_is_odd :: #force_inline proc(a: ^Int) -> (odd: bool) { - return !internal_int_is_even(a); + return !internal_int_is_even(a) } -internal_is_odd :: proc { internal_int_is_odd, }; +internal_is_odd :: proc { internal_int_is_odd, } /* @@ -1080,9 +1080,9 @@ internal_int_is_power_of_two :: #force_inline proc(a: ^Int) -> (power_of_two: bo */ for i := 1; i < a.used && a.digit[i - 1] != 0; i += 1 { return false; } - return true; + return true } -internal_is_power_of_two :: proc { internal_int_is_power_of_two, }; +internal_is_power_of_two :: proc { internal_int_is_power_of_two, } /* Compare two `Int`s, signed. @@ -1091,7 +1091,7 @@ internal_is_power_of_two :: proc { internal_int_is_power_of_two, }; Expects `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`. */ internal_int_compare :: #force_inline proc(a, b: ^Int) -> (comparison: int) { - a_is_negative := #force_inline internal_is_negative(a); + a_is_negative := #force_inline internal_is_negative(a) /* Compare based on sign. @@ -1102,10 +1102,10 @@ internal_int_compare :: #force_inline proc(a, b: ^Int) -> (comparison: int) { If `a` is negative, compare in the opposite direction */ if a_is_negative { return #force_inline internal_compare_magnitude(b, a); } - return #force_inline internal_compare_magnitude(a, b); + return #force_inline internal_compare_magnitude(a, b) } -internal_compare :: proc { internal_int_compare, internal_int_compare_digit, }; -internal_cmp :: internal_compare; +internal_compare :: proc { internal_int_compare, internal_int_compare_digit, } +internal_cmp :: internal_compare /* Compare an `Int` to an unsigned number upto `DIGIT & _MASK`. @@ -1114,32 +1114,32 @@ internal_cmp :: internal_compare; Expects: `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`. */ internal_int_compare_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (comparison: int) { - a_is_negative := #force_inline internal_is_negative(a); + a_is_negative := #force_inline internal_is_negative(a) switch { /* Compare based on sign first. */ - case a_is_negative: return -1; + case a_is_negative: return -1 /* Then compare on magnitude. */ - case a.used > 1: return +1; + case a.used > 1: return +1 /* We have only one digit. Compare it against `b`. */ - case a.digit[0] < b: return -1; - case a.digit[0] == b: return 0; - case a.digit[0] > b: return +1; + case a.digit[0] < b: return -1 + case a.digit[0] == b: return 0 + case a.digit[0] > b: return +1 /* Unreachable. Just here because Odin complains about a missing return value at the bottom of the proc otherwise. */ - case: return; + case: return } } -internal_compare_digit :: proc { internal_int_compare_digit, }; -internal_cmp_digit :: internal_compare_digit; +internal_compare_digit :: proc { internal_int_compare_digit, } +internal_cmp_digit :: internal_compare_digit /* Compare the magnitude of two `Int`s, unsigned. @@ -1150,9 +1150,9 @@ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: */ if a.used != b.used { if a.used > b.used { - return +1; + return +1 } - return -1; + return -1 } /* @@ -1161,16 +1161,16 @@ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: #no_bounds_check for n := a.used - 1; n >= 0; n -= 1 { if a.digit[n] != b.digit[n] { if a.digit[n] > b.digit[n] { - return +1; + return +1 } - return -1; + return -1 } } - return 0; + return 0 } -internal_compare_magnitude :: proc { internal_int_compare_magnitude, }; -internal_cmp_mag :: internal_compare_magnitude; +internal_compare_magnitude :: proc { internal_int_compare_magnitude, } +internal_cmp_mag :: internal_compare_magnitude /* Check if remainders are possible squares - fast exclude non-squares. @@ -1179,12 +1179,12 @@ internal_cmp_mag :: internal_compare_magnitude; Assumes `a` not to be `nil` and to have been initialized. */ internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Default to Non-square :) */ - square = false; + square = false if internal_is_negative(a) { return; } if internal_is_zero(a) { return; } @@ -1197,18 +1197,18 @@ internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (squa /* Next check mod 105 (3*5*7). */ - c: DIGIT; - c, err = internal_mod(a, 105); + c: DIGIT + c, err = internal_mod(a, 105) if _private_int_rem_105[c] == 1 { return; } - t := &Int{}; - defer destroy(t); + t := &Int{} + defer destroy(t) - set(t, 11 * 13 * 17 * 19 * 23 * 29 * 31) or_return; - internal_mod(t, a, t) or_return; + set(t, 11 * 13 * 17 * 19 * 23 * 29 * 31) or_return + internal_mod(t, a, t) or_return - r: u64; - r, err = internal_int_get(t, u64); + r: u64 + r, err = internal_int_get(t, u64) /* Check for other prime modules, note it's not an ERROR but we must @@ -1226,12 +1226,12 @@ internal_int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (squa /* Final check - is sqr(sqrt(arg)) == arg? */ - sqrt(t, a) or_return; - sqr(t, t) or_return; + sqrt(t, a) or_return + sqr(t, t) or_return - square = internal_cmp_mag(t, a) == 0; + square = internal_cmp_mag(t, a) == 0 - return; + return } /* @@ -1258,7 +1258,7 @@ internal_int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) { */ if a.used == 1 { return internal_log(a.digit[0], DIGIT(base)); } - return _private_int_log(a, base); + return _private_int_log(a, base) } @@ -1277,52 +1277,52 @@ internal_digit_log :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) { */ if a == base { return 1, nil; } - N := _WORD(a); - bracket_low := _WORD(1); - bracket_high := _WORD(base); - high := 1; - low := 0; + N := _WORD(a) + bracket_low := _WORD(1) + bracket_high := _WORD(base) + high := 1 + low := 0 for bracket_high < N { - low = high; - bracket_low = bracket_high; - high <<= 1; - bracket_high *= bracket_high; + low = high + bracket_low = bracket_high + high <<= 1 + bracket_high *= bracket_high } for high - low > 1 { - mid := (low + high) >> 1; - bracket_mid := bracket_low * #force_inline internal_small_pow(_WORD(base), _WORD(mid - low)); + mid := (low + high) >> 1 + bracket_mid := bracket_low * #force_inline internal_small_pow(_WORD(base), _WORD(mid - low)) if N < bracket_mid { - high = mid; - bracket_high = bracket_mid; + high = mid + bracket_high = bracket_mid } if N > bracket_mid { - low = mid; - bracket_low = bracket_mid; + low = mid + bracket_low = bracket_mid } if N == bracket_mid { - return mid, nil; + return mid, nil } } if bracket_high == N { - return high, nil; + return high, nil } else { - return low, nil; + return low, nil } } -internal_log :: proc { internal_int_log, internal_digit_log, }; +internal_log :: proc { internal_int_log, internal_digit_log, } /* Calculate dest = base^power using a square-multiply algorithm. Assumes `dest` and `base` not to be `nil` and to have been initialized. */ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - power := power; + power := power /* Early outs. */ @@ -1331,8 +1331,8 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo A zero base is a special case. */ if power < 0 { - internal_zero(dest) or_return; - return .Math_Domain_Error; + internal_zero(dest) or_return + return .Math_Domain_Error } if power == 0 { return internal_one(dest); } if power > 0 { return internal_zero(dest); } @@ -1342,52 +1342,52 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo /* Fraction, so we'll return zero. */ - return internal_zero(dest); + return internal_zero(dest) } switch(power) { case 0: /* Any base to the power zero is one. */ - return #force_inline internal_one(dest); + return #force_inline internal_one(dest) case 1: /* Any base to the power one is itself. */ - return copy(dest, base); + return copy(dest, base) case 2: - return #force_inline internal_sqr(dest, base); + return #force_inline internal_sqr(dest, base) } - g := &Int{}; - internal_copy(g, base) or_return; + g := &Int{} + internal_copy(g, base) or_return /* Set initial result. */ - internal_one(dest) or_return; + internal_one(dest) or_return - defer internal_destroy(g); + defer internal_destroy(g) for power > 0 { /* If the bit is set, multiply. */ if power & 1 != 0 { - internal_mul(dest, g, dest) or_return; + internal_mul(dest, g, dest) or_return } /* Square. */ if power > 1 { - internal_sqr(g, g) or_return; + internal_sqr(g, g) or_return } /* shift to next bit */ - power >>= 1; + power >>= 1 } - return; + return } /* @@ -1395,34 +1395,34 @@ internal_int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allo Assumes `dest` not to be `nil` and to have been initialized. */ internal_int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - base_t := &Int{}; - defer internal_destroy(base_t); + base_t := &Int{} + defer internal_destroy(base_t) - internal_set(base_t, base) or_return; + internal_set(base_t, base) or_return - return #force_inline internal_int_pow(dest, base_t, power); + return #force_inline internal_int_pow(dest, base_t, power) } -internal_pow :: proc { internal_int_pow, internal_int_pow_int, }; -internal_exp :: pow; +internal_pow :: proc { internal_int_pow, internal_int_pow_int, } +internal_exp :: pow /* */ internal_small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) { - exponent := exponent; base := base; - result = _WORD(1); + exponent := exponent; base := base + result = _WORD(1) for exponent != 0 { if exponent & 1 == 1 { - result *= base; + result *= base } - exponent >>= 1; - base *= base; + exponent >>= 1 + base *= base } - return result; + return result } /* @@ -1430,7 +1430,7 @@ internal_small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) { Assumes `dest` and `src` not to be `nil` and to have been initialized. */ internal_int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Must be positive. @@ -1445,33 +1445,33 @@ internal_int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (e /* Set up temporaries. */ - x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}; - defer internal_destroy(x, y, t1, t2); + x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{} + defer internal_destroy(x, y, t1, t2) - count := #force_inline internal_count_bits(src); + count := #force_inline internal_count_bits(src) - a, b := count >> 1, count & 1; - internal_int_power_of_two(x, a+b, allocator) or_return; + a, b := count >> 1, count & 1 + internal_int_power_of_two(x, a+b, allocator) or_return for { /* y = (x + n // x) // 2 */ - internal_div(t1, src, x) or_return; - internal_add(t2, t1, x) or_return; - internal_shr(y, t2, 1) or_return; + internal_div(t1, src, x) or_return + internal_add(t2, t1, x) or_return + internal_shr(y, t2, 1) or_return if c := internal_cmp(y, x); c == 0 || c == 1 { - internal_swap(dest, x); - return nil; + internal_swap(dest, x) + return nil } - internal_swap(x, y); + internal_swap(x, y) } - internal_swap(dest, x); - return err; + internal_swap(dest, x) + return err } -internal_sqrt :: proc { internal_int_sqrt, }; +internal_sqrt :: proc { internal_int_sqrt, } /* @@ -1484,7 +1484,7 @@ internal_sqrt :: proc { internal_int_sqrt, }; Assumes `dest` and `src` not to be `nil` and have been initialized. */ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Fast path for n == 2 @@ -1498,15 +1498,15 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca /* Set up temporaries. */ - t1, t2, t3, a := &Int{}, &Int{}, &Int{}, &Int{}; - defer internal_destroy(t1, t2, t3); + t1, t2, t3, a := &Int{}, &Int{}, &Int{}, &Int{} + defer internal_destroy(t1, t2, t3) /* If `src` is negative fudge the sign but keep track. */ - a.sign = .Zero_or_Positive; - a.used = src.used; - a.digit = src.digit; + a.sign = .Zero_or_Positive + a.used = src.used + a.digit = src.digit /* If "n" is larger than INT_MAX it is also larger than @@ -1514,63 +1514,63 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca with an int and hence the root is always < 2 (two). */ if n > max(int) / 2 { - err = set(dest, 1); - dest.sign = a.sign; - return err; + err = set(dest, 1) + dest.sign = a.sign + return err } /* Compute seed: 2^(log_2(src)/n + 2) */ - ilog2 := internal_count_bits(src); + ilog2 := internal_count_bits(src) /* "src" is smaller than max(int), we can cast safely. */ if ilog2 < n { - err = internal_one(dest); - dest.sign = a.sign; - return err; + err = internal_one(dest) + dest.sign = a.sign + return err } - ilog2 /= n; + ilog2 /= n if ilog2 == 0 { - err = internal_one(dest); - dest.sign = a.sign; - return err; + err = internal_one(dest) + dest.sign = a.sign + return err } /* Start value must be larger than root. */ - ilog2 += 2; - internal_int_power_of_two(t2, ilog2) or_return; + ilog2 += 2 + internal_int_power_of_two(t2, ilog2) or_return - c: int; - iterations := 0; + c: int + iterations := 0 for { /* t1 = t2 */ - internal_copy(t1, t2) or_return; + internal_copy(t1, t2) or_return /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */ /* t3 = t1**(b-1) */ - internal_pow(t3, t1, n-1) or_return; + internal_pow(t3, t1, n-1) or_return /* numerator */ /* t2 = t1**b */ - internal_mul(t2, t1, t3) or_return; + internal_mul(t2, t1, t3) or_return /* t2 = t1**b - a */ - internal_sub(t2, t2, a) or_return; + internal_sub(t2, t2, a) or_return /* denominator */ /* t3 = t1**(b-1) * b */ - internal_mul(t3, t3, DIGIT(n)) or_return; + internal_mul(t3, t3, DIGIT(n)) or_return /* t3 = (t1**b - a)/(b * t1**(b-1)) */ - internal_div(t3, t2, t3) or_return; - internal_sub(t2, t1, t3) or_return; + internal_div(t3, t2, t3) or_return + internal_sub(t2, t1, t3) or_return /* Number of rounds is at most log_2(root). If it is more it @@ -1579,65 +1579,65 @@ internal_int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.alloca if ilog2 -= 1; ilog2 == 0 { break; } if internal_cmp(t1, t2) == 0 { break; } - iterations += 1; + iterations += 1 if iterations == MAX_ITERATIONS_ROOT_N { - return .Max_Iterations_Reached; + return .Max_Iterations_Reached } } /* Result can be off by a few so check. */ /* Loop beneath can overshoot by one if found root is smaller than actual root. */ - iterations = 0; + iterations = 0 for { - internal_pow(t2, t1, n) or_return; + internal_pow(t2, t1, n) or_return - c = internal_cmp(t2, a); + c = internal_cmp(t2, a) if c == 0 { - swap(dest, t1); - return nil; + swap(dest, t1) + return nil } else if c == -1 { - internal_add(t1, t1, DIGIT(1)) or_return; + internal_add(t1, t1, DIGIT(1)) or_return } else { - break; + break } - iterations += 1; + iterations += 1 if iterations == MAX_ITERATIONS_ROOT_N { - return .Max_Iterations_Reached; + return .Max_Iterations_Reached } } - iterations = 0; + iterations = 0 /* Correct overshoot from above or from recurrence. */ for { - internal_pow(t2, t1, n) or_return; + internal_pow(t2, t1, n) or_return if internal_cmp(t2, a) != 1 { break; } - internal_sub(t1, t1, DIGIT(1)) or_return; + internal_sub(t1, t1, DIGIT(1)) or_return - iterations += 1; + iterations += 1 if iterations == MAX_ITERATIONS_ROOT_N { - return .Max_Iterations_Reached; + return .Max_Iterations_Reached } } /* Set the result. */ - internal_swap(dest, t1); + internal_swap(dest, t1) /* Set the sign of the result. */ - dest.sign = src.sign; + dest.sign = src.sign - return err; + return err } -internal_root_n :: proc { internal_int_root_n, }; +internal_root_n :: proc { internal_int_root_n, } /* Other internal helpers @@ -1648,51 +1648,51 @@ internal_root_n :: proc { internal_int_root_n, }; Asssumes none of the `integers` to be a `nil`. */ internal_int_destroy :: proc(integers: ..^Int) { - integers := integers; + integers := integers for a in &integers { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; + raw := transmute(mem.Raw_Dynamic_Array)a.digit if raw.cap > 0 { - mem.zero_slice(a.digit[:]); - free(&a.digit[0]); + mem.zero_slice(a.digit[:]) + free(&a.digit[0]) } - a = &Int{}; + a = &Int{} } } -internal_destroy :: proc{ internal_int_destroy, }; +internal_destroy :: proc{ internal_int_destroy, } /* Helpers to set an `Int` to a specific value. */ internal_int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, allocator := context.allocator) -> (err: Error) where intrinsics.type_is_integer(T) { - context.allocator = allocator; + context.allocator = allocator - src := src; + src := src - internal_error_if_immutable(dest) or_return; + internal_error_if_immutable(dest) or_return /* Most internal procs asssume an Int to have already been initialize, but as this is one of the procs that initializes, we have to check the following. */ - internal_clear_if_uninitialized_single(dest) or_return; + internal_clear_if_uninitialized_single(dest) or_return - dest.flags = {}; // We're not -Inf, Inf, NaN or Immutable. + 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.used = 0 + dest.sign = .Zero_or_Positive if src >= 0 else .Negative + src = internal_abs(src) #no_bounds_check for src != 0 { - dest.digit[dest.used] = DIGIT(src) & _MASK; - dest.used += 1; - src >>= _DIGIT_BITS; + dest.digit[dest.used] = DIGIT(src) & _MASK + dest.used += 1 + src >>= _DIGIT_BITS } - internal_zero_unused(dest); - return nil; + internal_zero_unused(dest) + return nil } -internal_set :: proc { internal_int_set_from_integer, internal_int_copy }; +internal_set :: proc { internal_int_set_from_integer, internal_int_copy } internal_copy_digits :: #force_inline proc(dest, src: ^Int, digits: int, offset := int(0)) -> (err: Error) { #force_inline internal_error_if_immutable(dest) or_return; @@ -1700,43 +1700,43 @@ internal_copy_digits :: #force_inline proc(dest, src: ^Int, digits: int, offset /* If dest == src, do nothing */ - return #force_inline _private_copy_digits(dest, src, digits, offset); + return #force_inline _private_copy_digits(dest, src, digits, offset) } /* Copy one `Int` to another. */ internal_int_copy :: proc(dest, src: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* If dest == src, do nothing */ if (dest == src) { return nil; } - internal_error_if_immutable(dest) or_return; + internal_error_if_immutable(dest) or_return /* Grow `dest` to fit `src`. If `dest` is not yet initialized, it will be using `allocator`. */ - needed := src.used if minimize else max(src.used, _DEFAULT_DIGIT_COUNT); + needed := src.used if minimize else max(src.used, _DEFAULT_DIGIT_COUNT) - internal_grow(dest, needed, minimize) or_return; + internal_grow(dest, needed, minimize) or_return /* Copy everything over and zero high digits. */ - internal_copy_digits(dest, src, src.used); + internal_copy_digits(dest, src, src.used) - dest.used = src.used; - dest.sign = src.sign; - dest.flags = src.flags &~ {.Immutable}; + dest.used = src.used + dest.sign = src.sign + dest.flags = src.flags &~ {.Immutable} - internal_zero_unused(dest); - return nil; + internal_zero_unused(dest) + return nil } -internal_copy :: proc { internal_int_copy, }; +internal_copy :: proc { internal_int_copy, } /* In normal code, you can also write `a, b = b, a`. @@ -1744,80 +1744,80 @@ internal_copy :: proc { internal_int_copy, }; This helper swaps completely. */ internal_int_swap :: #force_inline proc(a, b: ^Int) { - a := a; b := b; + a := a; b := b - a.used, b.used = b.used, a.used; - a.sign, b.sign = b.sign, a.sign; - a.digit, b.digit = b.digit, a.digit; + a.used, b.used = b.used, a.used + a.sign, b.sign = b.sign, a.sign + a.digit, b.digit = b.digit, a.digit } -internal_swap :: proc { internal_int_swap, }; +internal_swap :: proc { internal_int_swap, } /* Set `dest` to |`src`|. */ internal_int_abs :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* If `dest == src`, just fix `dest`'s sign. */ if (dest == src) { - dest.sign = .Zero_or_Positive; - return nil; + dest.sign = .Zero_or_Positive + return nil } /* Copy `src` to `dest` */ - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Fix sign. */ - dest.sign = .Zero_or_Positive; - return nil; + dest.sign = .Zero_or_Positive + return nil } internal_platform_abs :: proc(n: $T) -> T where intrinsics.type_is_integer(T) { - return n if n >= 0 else -n; + return n if n >= 0 else -n } -internal_abs :: proc{ internal_int_abs, internal_platform_abs, }; +internal_abs :: proc{ internal_int_abs, internal_platform_abs, } /* Set `dest` to `-src`. */ internal_int_neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* If `dest == src`, just fix `dest`'s sign. */ - sign := Sign.Negative; + sign := Sign.Negative if #force_inline internal_is_zero(src) || #force_inline internal_is_negative(src) { - sign = .Zero_or_Positive; + sign = .Zero_or_Positive } if dest == src { - dest.sign = sign; - return nil; + dest.sign = sign + return nil } /* Copy `src` to `dest` */ - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Fix sign. */ - dest.sign = sign; - return nil; + dest.sign = sign + return nil } -internal_neg :: proc { internal_int_neg, }; +internal_neg :: proc { internal_int_neg, } /* hac 14.61, pp608. */ internal_int_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* For all n in N and n > 0, n = 0 mod 1. */ @@ -1833,15 +1833,15 @@ internal_int_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.alloc */ if internal_is_odd(b) { return _private_inverse_modulo_odd(dest, a, b); } - return _private_inverse_modulo(dest, a, b); + return _private_inverse_modulo(dest, a, b) } -internal_invmod :: proc{ internal_int_inverse_modulo, }; +internal_invmod :: proc{ internal_int_inverse_modulo, } /* Helpers to extract values from the `Int`. */ internal_int_bitfield_extract_single :: proc(a: ^Int, offset: int) -> (bit: _WORD, err: Error) { - return #force_inline int_bitfield_extract(a, offset, 1); + return #force_inline int_bitfield_extract(a, offset, 1) } internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WORD, err: Error) #no_bounds_check { @@ -1849,10 +1849,10 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR Early out for single bit. */ if count == 1 { - limb := offset / _DIGIT_BITS; + limb := offset / _DIGIT_BITS if limb < 0 || limb >= a.used { return 0, .Invalid_Argument; } - i := _WORD(1 << _WORD((offset % _DIGIT_BITS))); - return 1 if ((_WORD(a.digit[limb]) & i) != 0) else 0, nil; + i := _WORD(1 << _WORD((offset % _DIGIT_BITS))) + return 1 if ((_WORD(a.digit[limb]) & i) != 0) else 0, nil } if count > _WORD_BITS || count < 1 { return 0, .Invalid_Argument; } @@ -1869,34 +1869,34 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR e.g. offset: 40, count: 120 = bits 40..59, 0..59, 0..39 */ - limb := offset / _DIGIT_BITS; - bits_left := count; - bits_offset := offset % _DIGIT_BITS; + limb := offset / _DIGIT_BITS + bits_left := count + bits_offset := offset % _DIGIT_BITS - num_bits := min(bits_left, _DIGIT_BITS - bits_offset); + num_bits := min(bits_left, _DIGIT_BITS - bits_offset) - shift := offset % _DIGIT_BITS; - mask := (_WORD(1) << uint(num_bits)) - 1; - res = (_WORD(a.digit[limb]) >> uint(shift)) & mask; + shift := offset % _DIGIT_BITS + mask := (_WORD(1) << uint(num_bits)) - 1 + res = (_WORD(a.digit[limb]) >> uint(shift)) & mask - bits_left -= num_bits; + bits_left -= num_bits if bits_left == 0 { return res, nil; } - res_shift := num_bits; - num_bits = min(bits_left, _DIGIT_BITS); - mask = (1 << uint(num_bits)) - 1; + res_shift := num_bits + num_bits = min(bits_left, _DIGIT_BITS) + mask = (1 << uint(num_bits)) - 1 - res |= (_WORD(a.digit[limb + 1]) & mask) << uint(res_shift); + res |= (_WORD(a.digit[limb + 1]) & mask) << uint(res_shift) - bits_left -= num_bits; + bits_left -= num_bits if bits_left == 0 { return res, nil; } - mask = (1 << uint(bits_left)) - 1; - res_shift += _DIGIT_BITS; + mask = (1 << uint(bits_left)) - 1 + res_shift += _DIGIT_BITS - res |= (_WORD(a.digit[limb + 2]) & mask) << uint(res_shift); + res |= (_WORD(a.digit[limb + 2]) & mask) << uint(res_shift) - return res, nil; + return res, nil } /* @@ -1906,169 +1906,169 @@ internal_int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WOR Assumes `a` not to be `nil`, and to have already been initialized. */ internal_int_shrink :: proc(a: ^Int) -> (err: Error) { - needed := max(_MIN_DIGIT_COUNT, a.used); + needed := max(_MIN_DIGIT_COUNT, a.used) if a.used != needed { return internal_grow(a, needed, true); } - return nil; + return nil } -internal_shrink :: proc { internal_int_shrink, }; +internal_shrink :: proc { internal_int_shrink, } internal_int_grow :: proc(a: ^Int, digits: int, allow_shrink := false, allocator := context.allocator) -> (err: Error) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; + raw := transmute(mem.Raw_Dynamic_Array)a.digit /* We need at least _MIN_DIGIT_COUNT or a.used digits, whichever is bigger. The caller is asking for `digits`. Let's be accomodating. */ - needed := max(_MIN_DIGIT_COUNT, a.used, digits); + needed := max(_MIN_DIGIT_COUNT, a.used, digits) if !allow_shrink { - needed = max(needed, raw.cap); + needed = max(needed, raw.cap) } /* If not yet iniialized, initialize the `digit` backing with the allocator we were passed. */ if raw.cap == 0 { - a.digit = make([dynamic]DIGIT, needed, allocator); + a.digit = make([dynamic]DIGIT, needed, allocator) } else if raw.cap != needed { /* `[dynamic]DIGIT` already knows what allocator was used for it, so resize will do the right thing. */ - resize(&a.digit, needed); + resize(&a.digit, needed) } /* Let's see if the allocation/resize worked as expected. */ if len(a.digit) != needed { - return .Out_Of_Memory; + return .Out_Of_Memory } - return nil; + return nil } -internal_grow :: proc { internal_int_grow, }; +internal_grow :: proc { internal_int_grow, } /* Clear `Int` and resize it to the default size. Assumes `a` not to be `nil`. */ internal_int_clear :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - raw := transmute(mem.Raw_Dynamic_Array)a.digit; + raw := transmute(mem.Raw_Dynamic_Array)a.digit if raw.cap != 0 { - mem.zero_slice(a.digit[:a.used]); + mem.zero_slice(a.digit[:a.used]) } - a.sign = .Zero_or_Positive; - a.used = 0; + a.sign = .Zero_or_Positive + a.used = 0 - return #force_inline internal_grow(a, a.used, minimize, allocator); + return #force_inline internal_grow(a, a.used, minimize, allocator) } -internal_clear :: proc { internal_int_clear, }; -internal_zero :: internal_clear; +internal_clear :: proc { internal_int_clear, } +internal_zero :: internal_clear /* Set the `Int` to 1 and optionally shrink it to the minimum backing size. */ internal_int_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_ONE, minimize, allocator); + return internal_copy(a, INT_ONE, minimize, allocator) } -internal_one :: proc { internal_int_one, }; +internal_one :: proc { internal_int_one, } /* Set the `Int` to -1 and optionally shrink it to the minimum backing size. */ internal_int_minus_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_MINUS_ONE, minimize, allocator); + return internal_copy(a, INT_MINUS_ONE, minimize, allocator) } -internal_minus_one :: proc { internal_int_minus_one, }; +internal_minus_one :: proc { internal_int_minus_one, } /* Set the `Int` to Inf and optionally shrink it to the minimum backing size. */ internal_int_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_INF, minimize, allocator); + return internal_copy(a, INT_INF, minimize, allocator) } -internal_inf :: proc { internal_int_inf, }; +internal_inf :: proc { internal_int_inf, } /* Set the `Int` to -Inf and optionally shrink it to the minimum backing size. */ internal_int_minus_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_MINUS_INF, minimize, allocator); + return internal_copy(a, INT_MINUS_INF, minimize, allocator) } -internal_minus_inf :: proc { internal_int_inf, }; +internal_minus_inf :: proc { internal_int_inf, } /* Set the `Int` to NaN and optionally shrink it to the minimum backing size. */ internal_int_nan :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return internal_copy(a, INT_NAN, minimize, allocator); + return internal_copy(a, INT_NAN, minimize, allocator) } -internal_nan :: proc { internal_int_nan, }; +internal_nan :: proc { internal_int_nan, } internal_int_power_of_two :: proc(a: ^Int, power: int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if power < 0 || power > _MAX_BIT_COUNT { return .Invalid_Argument; } /* Grow to accomodate the single bit. */ - a.used = (power / _DIGIT_BITS) + 1; - internal_grow(a, a.used) or_return; + a.used = (power / _DIGIT_BITS) + 1 + internal_grow(a, a.used) or_return /* Zero the entirety. */ - mem.zero_slice(a.digit[:]); + mem.zero_slice(a.digit[:]) /* Set the bit. */ - a.digit[power / _DIGIT_BITS] = 1 << uint((power % _DIGIT_BITS)); - return nil; + a.digit[power / _DIGIT_BITS] = 1 << uint((power % _DIGIT_BITS)) + return nil } internal_int_get_u128 :: proc(a: ^Int) -> (res: u128, err: Error) { - return internal_int_get(a, u128); + return internal_int_get(a, u128) } -internal_get_u128 :: proc { internal_int_get_u128, }; +internal_get_u128 :: proc { internal_int_get_u128, } internal_int_get_i128 :: proc(a: ^Int) -> (res: i128, err: Error) { - return internal_int_get(a, i128); + return internal_int_get(a, i128) } -internal_get_i128 :: proc { internal_int_get_i128, }; +internal_get_i128 :: proc { internal_int_get_i128, } internal_int_get_u64 :: proc(a: ^Int) -> (res: u64, err: Error) { - return internal_int_get(a, u64); + return internal_int_get(a, u64) } -internal_get_u64 :: proc { internal_int_get_u64, }; +internal_get_u64 :: proc { internal_int_get_u64, } internal_int_get_i64 :: proc(a: ^Int) -> (res: i64, err: Error) { - return internal_int_get(a, i64); + return internal_int_get(a, i64) } -internal_get_i64 :: proc { internal_int_get_i64, }; +internal_get_i64 :: proc { internal_int_get_i64, } internal_int_get_u32 :: proc(a: ^Int) -> (res: u32, err: Error) { - return internal_int_get(a, u32); + return internal_int_get(a, u32) } -internal_get_u32 :: proc { internal_int_get_u32, }; +internal_get_u32 :: proc { internal_int_get_u32, } internal_int_get_i32 :: proc(a: ^Int) -> (res: i32, err: Error) { - return internal_int_get(a, i32); + return internal_int_get(a, i32) } -internal_get_i32 :: proc { internal_int_get_i32, }; +internal_get_i32 :: proc { internal_int_get_i32, } /* 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); + 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]); + res <<= uint(0) if size_in_bits <= _DIGIT_BITS else _DIGIT_BITS + res |= T(a.digit[i]) if size_in_bits <= _DIGIT_BITS { - break; + break }; } @@ -2076,31 +2076,31 @@ internal_int_get :: proc(a: ^Int, $T: typeid) -> (res: T, err: Error) where intr /* Mask off sign bit. */ - res ~= 1 << uint(size_in_bits - 1); + res ~= 1 << uint(size_in_bits - 1) /* Set the sign. */ if a.sign == .Negative { res = -res; } } - return; + return } -internal_get :: proc { internal_int_get, }; +internal_get :: proc { internal_int_get, } internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { /* log2(max(f64)) is approximately 1020, or 17 legs with the 64-bit storage. */ - legs :: 1020 / _DIGIT_BITS; - l := min(a.used, legs); - fac := f64(1 << _DIGIT_BITS); - d := 0.0; + legs :: 1020 / _DIGIT_BITS + l := min(a.used, legs) + fac := f64(1 << _DIGIT_BITS) + d := 0.0 #no_bounds_check for i := l; i >= 0; i -= 1 { - d = (d * fac) + f64(a.digit[i]); + d = (d * fac) + f64(a.digit[i]) } - res = -d if a.sign == .Negative else d; - return; + res = -d if a.sign == .Negative else d + return } /* @@ -2114,278 +2114,278 @@ internal_int_get_float :: proc(a: ^Int) -> (res: f64, err: Error) { 2's complement `and`, returns `dest = a & b;` */ internal_int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - used := max(a.used, b.used) + 1; + used := max(a.used, b.used) + 1 /* Grow the destination to accomodate the result. */ - internal_grow(dest, used) or_return; + internal_grow(dest, used) or_return - neg_a := #force_inline internal_is_negative(a); - neg_b := #force_inline internal_is_negative(b); - neg := neg_a && neg_b; + neg_a := #force_inline internal_is_negative(a) + neg_b := #force_inline internal_is_negative(b) + neg := neg_a && neg_b - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1) #no_bounds_check for i := 0; i < used; i += 1 { - x, y: DIGIT; + 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; + 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]; + 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; + 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]; + y = 0 if i >= b.used else b.digit[i] } - dest.digit[i] = x & y; + 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; + 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 internal_clamp(dest); + dest.used = used + dest.sign = .Negative if neg else .Zero_or_Positive + return internal_clamp(dest) } -internal_and :: proc { internal_int_and, }; +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) { - context.allocator = allocator; + context.allocator = allocator - used := max(a.used, b.used) + 1; + used := max(a.used, b.used) + 1 /* Grow the destination to accomodate the result. */ - internal_grow(dest, used) or_return; + internal_grow(dest, used) or_return - neg_a := #force_inline internal_is_negative(a); - neg_b := #force_inline internal_is_negative(b); - neg := neg_a || neg_b; + neg_a := #force_inline internal_is_negative(a) + neg_b := #force_inline internal_is_negative(b) + neg := neg_a || neg_b - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1) #no_bounds_check for i := 0; i < used; i += 1 { - x, y: DIGIT; + 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; + 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]; + 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; + 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]; + y = 0 if i >= b.used else b.digit[i] } - dest.digit[i] = x | y; + 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; + 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 internal_clamp(dest); + dest.used = used + dest.sign = .Negative if neg else .Zero_or_Positive + return internal_clamp(dest) } -internal_or :: proc { internal_int_or, }; +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) { - context.allocator = allocator; + context.allocator = allocator - used := max(a.used, b.used) + 1; + used := max(a.used, b.used) + 1 /* Grow the destination to accomodate the result. */ - internal_grow(dest, used) or_return; + internal_grow(dest, used) or_return - neg_a := #force_inline internal_is_negative(a); - neg_b := #force_inline internal_is_negative(b); - neg := neg_a != neg_b; + neg_a := #force_inline internal_is_negative(a) + neg_b := #force_inline internal_is_negative(b) + neg := neg_a != neg_b - ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1); + ac, bc, cc := DIGIT(1), DIGIT(1), DIGIT(1) #no_bounds_check for i := 0; i < used; i += 1 { - x, y: DIGIT; + 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; + 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]; + 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; + 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]; + y = 0 if i >= b.used else b.digit[i] } - dest.digit[i] = x ~ y; + 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; + 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 internal_clamp(dest); + dest.used = used + dest.sign = .Negative if neg else .Zero_or_Positive + return internal_clamp(dest) } -internal_xor :: proc { internal_int_xor, }; +internal_xor :: proc { internal_int_xor, } /* dest = ~src */ internal_int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Temporarily fix sign. */ - old_sign := src.sign; + old_sign := src.sign - neg := #force_inline internal_is_zero(src) || #force_inline internal_is_positive(src); + neg := #force_inline internal_is_zero(src) || #force_inline internal_is_positive(src) - src.sign = .Negative if neg else .Zero_or_Positive; + src.sign = .Negative if neg else .Zero_or_Positive - err = #force_inline internal_sub(dest, src, 1); + err = #force_inline internal_sub(dest, src, 1) /* Restore sign. */ - src.sign = old_sign; + src.sign = old_sign - return err; + return err } -internal_complement :: proc { internal_int_complement, }; +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) { - context.allocator = allocator; + context.allocator = allocator - bits := bits; + bits := bits if bits < 0 { return .Invalid_Argument; } - internal_copy(quotient, numerator) or_return; + internal_copy(quotient, numerator) or_return /* Shift right by a certain bit count (store quotient and optional remainder.) `numerator` should not be used after this. */ if remainder != nil { - internal_int_mod_bits(remainder, numerator, bits) or_return; + internal_int_mod_bits(remainder, numerator, bits) or_return } /* Shift by as many digits in the bit count. */ if bits >= _DIGIT_BITS { - internal_shr_digit(quotient, bits / _DIGIT_BITS) or_return; + internal_shr_digit(quotient, bits / _DIGIT_BITS) or_return } /* Shift any bit count < _DIGIT_BITS. */ - bits %= _DIGIT_BITS; + bits %= _DIGIT_BITS if bits != 0 { - mask := DIGIT(1 << uint(bits)) - 1; - shift := DIGIT(_DIGIT_BITS - bits); - carry := DIGIT(0); + mask := DIGIT(1 << uint(bits)) - 1 + shift := DIGIT(_DIGIT_BITS - bits) + carry := DIGIT(0) #no_bounds_check 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; + 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); + quotient.digit[x] = (quotient.digit[x] >> uint(bits)) | (carry << shift) /* Update carry from forward carry. */ - carry = fwd_carry; + carry = fwd_carry } } - return internal_clamp(numerator); + return internal_clamp(numerator) } -internal_shrmod :: proc { internal_int_shrmod, }; +internal_shrmod :: proc { internal_int_shrmod, } internal_int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - return #force_inline internal_shrmod(dest, nil, source, bits, allocator); + return #force_inline internal_shrmod(dest, nil, source, bits, allocator) } -internal_shr :: proc { internal_int_shr, }; +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; + context.allocator = allocator if digits <= 0 { return nil; } @@ -2404,88 +2404,88 @@ internal_int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context */ #no_bounds_check for x := 0; x < (quotient.used - digits); x += 1 { - quotient.digit[x] = quotient.digit[x + digits]; + quotient.digit[x] = quotient.digit[x + digits] } - quotient.used -= digits; - internal_zero_unused(quotient); - return internal_clamp(quotient); + quotient.used -= digits + internal_zero_unused(quotient) + return internal_clamp(quotient) } -internal_shr_digit :: proc { internal_int_shr_digit, }; +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) { - context.allocator = allocator; + context.allocator = allocator if src.sign == .Zero_or_Positive { - return internal_shr(dest, src, bits); + return internal_shr(dest, src, bits) } - internal_int_add_digit(dest, src, DIGIT(1)) or_return; - internal_shr(dest, dest, bits) or_return; - return internal_sub(dest, src, DIGIT(1)); + internal_int_add_digit(dest, src, DIGIT(1)) or_return + internal_shr(dest, dest, bits) or_return + return internal_sub(dest, src, DIGIT(1)) } -internal_shr_signed :: proc { internal_int_shr_signed, }; +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) { - context.allocator = allocator; + context.allocator = allocator - bits := bits; + bits := bits if bits < 0 { return .Invalid_Argument; } - internal_copy(dest, src) or_return; + internal_copy(dest, src) or_return /* Grow `dest` to accommodate the additional bits. */ - digits_needed := dest.used + (bits / _DIGIT_BITS) + 1; - internal_grow(dest, digits_needed) or_return; - dest.used = digits_needed; + digits_needed := dest.used + (bits / _DIGIT_BITS) + 1 + internal_grow(dest, digits_needed) or_return + dest.used = digits_needed /* 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; + internal_shl_digit(dest, bits / _DIGIT_BITS) or_return } /* Shift any remaining bit count < _DIGIT_BITS */ - bits %= _DIGIT_BITS; + bits %= _DIGIT_BITS if bits != 0 { - mask := (DIGIT(1) << uint(bits)) - DIGIT(1); - shift := DIGIT(_DIGIT_BITS - bits); - carry := DIGIT(0); + mask := (DIGIT(1) << uint(bits)) - DIGIT(1) + shift := DIGIT(_DIGIT_BITS - bits) + carry := DIGIT(0) #no_bounds_check 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; + 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; + dest.digit[dest.used] = carry + dest.used += 1 } } - return internal_clamp(dest); + return internal_clamp(dest) } -internal_shl :: proc { internal_int_shl, }; +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; + context.allocator = allocator if digits <= 0 { return nil; } @@ -2493,7 +2493,7 @@ internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context No need to shift a zero. */ if #force_inline internal_is_zero(quotient) { - return nil; + return nil } /* @@ -2510,14 +2510,14 @@ internal_int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context 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.digit[x+digits-1] = quotient.digit[x-1] } - quotient.used += digits; - mem.zero_slice(quotient.digit[:digits]); - return nil; + quotient.used += digits + mem.zero_slice(quotient.digit[:digits]) + return nil } -internal_shl_digit :: proc { internal_int_shl_digit, }; +internal_shl_digit :: proc { internal_int_shl_digit, } /* Count bits in an `Int`. @@ -2531,13 +2531,13 @@ internal_count_bits :: proc(a: ^Int) -> (count: int) { /* Get the number of DIGITs and use it. */ - count = (a.used - 1) * _DIGIT_BITS; + count = (a.used - 1) * _DIGIT_BITS /* Take the last DIGIT and count the bits in it. */ - clz := int(intrinsics.count_leading_zeros(a.digit[a.used - 1])); - count += (_DIGIT_TYPE_BITS - clz); - return; + clz := int(intrinsics.count_leading_zeros(a.digit[a.used - 1])) + count += (_DIGIT_TYPE_BITS - clz) + return } /* @@ -2555,117 +2555,117 @@ internal_int_count_lsb :: proc(a: ^Int) -> (count: int, err: Error) { /* Scan lower digits until non-zero. */ - x: int; + x: int #no_bounds_check for x = 0; x < a.used && a.digit[x] == 0; x += 1 {} - q := a.digit[x]; - x *= _DIGIT_BITS; - x += internal_count_lsb(q); - return x, nil; + q := a.digit[x] + x *= _DIGIT_BITS + x += internal_count_lsb(q) + return x, nil } internal_platform_count_lsb :: #force_inline proc(a: $T) -> (count: int) where intrinsics.type_is_integer(T) && intrinsics.type_is_unsigned(T) { - return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0; + return int(intrinsics.count_trailing_zeros(a)) if a > 0 else 0 } -internal_count_lsb :: proc { internal_int_count_lsb, internal_platform_count_lsb, }; +internal_count_lsb :: proc { internal_int_count_lsb, internal_platform_count_lsb, } internal_int_random_digit :: proc(r: ^rnd.Rand = nil) -> (res: DIGIT) { when _DIGIT_BITS == 60 { // DIGIT = u64 - return DIGIT(rnd.uint64(r)) & _MASK; + return DIGIT(rnd.uint64(r)) & _MASK } else when _DIGIT_BITS == 28 { // DIGIT = u32 - return DIGIT(rnd.uint32(r)) & _MASK; + return DIGIT(rnd.uint32(r)) & _MASK } else { - panic("Unsupported DIGIT size."); + panic("Unsupported DIGIT size.") } - return 0; // We shouldn't get here. + return 0 // We shouldn't get here. } internal_int_rand :: proc(dest: ^Int, bits: int, r: ^rnd.Rand = nil, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - bits := bits; + bits := bits if bits <= 0 { return .Invalid_Argument; } - digits := bits / _DIGIT_BITS; - bits %= _DIGIT_BITS; + digits := bits / _DIGIT_BITS + bits %= _DIGIT_BITS if bits > 0 { - digits += 1; + digits += 1 } #force_inline internal_grow(dest, digits) or_return; for i := 0; i < digits; i += 1 { - dest.digit[i] = int_random_digit(r) & _MASK; + dest.digit[i] = int_random_digit(r) & _MASK } if bits > 0 { - dest.digit[digits - 1] &= ((1 << uint(bits)) - 1); + dest.digit[digits - 1] &= ((1 << uint(bits)) - 1) } - dest.used = digits; - return nil; + dest.used = digits + return nil } -internal_rand :: proc { internal_int_rand, }; +internal_rand :: proc { internal_int_rand, } /* Internal helpers. */ internal_assert_initialized :: proc(a: ^Int, loc := #caller_location) { - assert(internal_is_initialized(a), "`Int` was not properly initialized.", loc); + assert(internal_is_initialized(a), "`Int` was not properly initialized.", loc) } internal_clear_if_uninitialized_single :: proc(arg: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator if ! #force_inline internal_is_initialized(arg) { - return #force_inline internal_grow(arg, _DEFAULT_DIGIT_COUNT); + return #force_inline internal_grow(arg, _DEFAULT_DIGIT_COUNT) } - return err; + return err } internal_clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator for i in args { if ! #force_inline internal_is_initialized(i) { - e := #force_inline internal_grow(i, _DEFAULT_DIGIT_COUNT); + e := #force_inline internal_grow(i, _DEFAULT_DIGIT_COUNT) if e != nil { err = e; } } } - return err; + return err } -internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, }; +internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, } internal_error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) { if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable; } - return nil; + return nil } internal_error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) { for i in args { if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable; } } - return nil; + return nil } -internal_error_if_immutable :: proc {internal_error_if_immutable_single, internal_error_if_immutable_multi, }; +internal_error_if_immutable :: proc {internal_error_if_immutable_single, internal_error_if_immutable_multi, } /* Allocates several `Int`s at once. */ internal_int_init_multi :: proc(integers: ..^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator - integers := integers; + integers := integers for a in &integers { - internal_clear(a) or_return; + internal_clear(a) or_return } - return nil; + return nil } -internal_init_multi :: proc { internal_int_init_multi, }; +internal_init_multi :: proc { internal_int_init_multi, } /* Trim unused digits. @@ -2678,7 +2678,7 @@ internal_clamp :: proc(a: ^Int) -> (err: Error) { if #force_inline internal_is_zero(a) { a.sign = .Zero_or_Positive; } - return nil; + return nil } @@ -2686,21 +2686,21 @@ internal_int_zero_unused :: #force_inline proc(dest: ^Int, old_used := -1) { /* If we don't pass the number of previously used DIGITs, we zero all remaining ones. */ - zero_count: int; + zero_count: int if old_used == -1 { - zero_count = len(dest.digit) - dest.used; + zero_count = len(dest.digit) - dest.used } else { - zero_count = old_used - dest.used; + zero_count = old_used - dest.used } /* Zero remainder. */ if zero_count > 0 && dest.used < len(dest.digit) { - mem.zero_slice(dest.digit[dest.used:][:zero_count]); + mem.zero_slice(dest.digit[dest.used:][:zero_count]) } } -internal_zero_unused :: proc { internal_int_zero_unused, }; +internal_zero_unused :: proc { internal_int_zero_unused, } /* ========================== End of low-level routines ========================== diff --git a/core/math/big/logical.odin b/core/math/big/logical.odin index 64f3b0898..d455d480d 100644 --- a/core/math/big/logical.odin +++ b/core/math/big/logical.odin @@ -22,37 +22,37 @@ package math_big 2's complement `and`, returns `dest = a & b;` */ int_and :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, a, b); - context.allocator = allocator; + assert_if_nil(dest, a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; - return #force_inline internal_int_and(dest, a, b); + internal_clear_if_uninitialized(a, b) or_return + return #force_inline internal_int_and(dest, a, b) } -and :: proc { int_and, }; +and :: proc { int_and, } /* 2's complement `or`, returns `dest = a | b;` */ int_or :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, a, b); - context.allocator = allocator; + assert_if_nil(dest, a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; - return #force_inline internal_int_or(dest, a, b); + internal_clear_if_uninitialized(a, b) or_return + return #force_inline internal_int_or(dest, a, b) } -or :: proc { int_or, }; +or :: proc { int_or, } /* 2's complement `xor`, returns `dest = a ^ b;` */ int_xor :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, a, b); - context.allocator = allocator; + assert_if_nil(dest, a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; - return #force_inline internal_int_xor(dest, a, b); + internal_clear_if_uninitialized(a, b) or_return + return #force_inline internal_int_xor(dest, a, b) } -xor :: proc { int_xor, }; +xor :: proc { int_xor, } /* dest = ~src @@ -61,31 +61,31 @@ int_complement :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: /* Check that `src` and `dest` are usable. */ - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator - internal_clear_if_uninitialized(dest, src) or_return; - return #force_inline internal_int_complement(dest, src); + internal_clear_if_uninitialized(dest, src) or_return + return #force_inline internal_int_complement(dest, src) } -complement :: proc { int_complement, }; +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, allocator := context.allocator) -> (err: Error) { - assert_if_nil(quotient, numerator); - context.allocator = allocator; + assert_if_nil(quotient, numerator) + context.allocator = allocator if err = internal_clear_if_uninitialized(quotient, numerator); err != nil { return err; } - return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits); + return #force_inline internal_int_shrmod(quotient, remainder, numerator, bits) } -shrmod :: proc { int_shrmod, }; +shrmod :: proc { int_shrmod, } int_shr :: proc(dest, source: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - return #force_inline shrmod(dest, nil, source, bits, allocator); + return #force_inline shrmod(dest, nil, source, bits, allocator) } -shr :: proc { int_shr, }; +shr :: proc { int_shr, } /* Shift right by `digits` * _DIGIT_BITS bits. @@ -94,38 +94,38 @@ int_shr_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato /* Check that `quotient` is usable. */ - assert_if_nil(quotient); - context.allocator = allocator; + assert_if_nil(quotient) + context.allocator = allocator - internal_clear_if_uninitialized(quotient) or_return; - return #force_inline internal_int_shr_digit(quotient, digits); + internal_clear_if_uninitialized(quotient) or_return + return #force_inline internal_int_shr_digit(quotient, digits) } -shr_digit :: proc { int_shr_digit, }; +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) { - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator - internal_clear_if_uninitialized(dest, src) or_return; - return #force_inline internal_int_shr_signed(dest, src, bits); + internal_clear_if_uninitialized(dest, src) or_return + return #force_inline internal_int_shr_signed(dest, src, bits) } -shr_signed :: proc { int_shr_signed, }; +shr_signed :: proc { int_shr_signed, } /* Shift left by a certain bit count. */ int_shl :: proc(dest, src: ^Int, bits: int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(dest, src); - context.allocator = allocator; + assert_if_nil(dest, src) + context.allocator = allocator - internal_clear_if_uninitialized(dest, src) or_return; - return #force_inline internal_int_shl(dest, src, bits); + internal_clear_if_uninitialized(dest, src) or_return + return #force_inline internal_int_shl(dest, src, bits) } -shl :: proc { int_shl, }; +shl :: proc { int_shl, } /* @@ -135,10 +135,10 @@ int_shl_digit :: proc(quotient: ^Int, digits: int, allocator := context.allocato /* Check that `quotient` is usable. */ - assert_if_nil(quotient); - context.allocator = allocator; + assert_if_nil(quotient) + context.allocator = allocator - internal_clear_if_uninitialized(quotient) or_return; - return #force_inline internal_int_shl_digit(quotient, digits); + 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 diff --git a/core/math/big/prime.odin b/core/math/big/prime.odin index f35e02807..b943da83b 100644 --- a/core/math/big/prime.odin +++ b/core/math/big/prime.odin @@ -16,43 +16,43 @@ package math_big Returns true if it is, false if not. */ int_prime_is_divisible :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) { - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - internal_clear_if_uninitialized(a) or_return; + internal_clear_if_uninitialized(a) or_return for prime in _private_prime_table { - rem := #force_inline int_mod_digit(a, prime) or_return; + rem := #force_inline int_mod_digit(a, prime) or_return if rem == 0 { - return true, nil; + return true, nil } } /* Default to not divisible. */ - return false, nil; + return false, nil } /* Computes xR**-1 == x (mod N) via Montgomery Reduction. */ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* Can the fast reduction [comba] method be used? Note that unlike in mul, you're safely allowed *less* than the available columns [255 per default], since carries are fixed up in the inner loop. */ - digs := (n.used * 2) + 1; + digs := (n.used * 2) + 1 if digs < _WARRAY && x.used <= _WARRAY && n.used < _MAX_COMBA { - return _private_montgomery_reduce_comba(x, n, rho); + return _private_montgomery_reduce_comba(x, n, rho) } /* Grow the input as required */ - internal_grow(x, digs) or_return; - x.used = digs; + internal_grow(x, digs) or_return + x.used = digs for ix := 0; ix < n.used; ix += 1 { /* @@ -62,29 +62,29 @@ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := cont to reduce the input one digit at a time. */ - mu := DIGIT((_WORD(x.digit[ix]) * _WORD(rho)) & _WORD(_MASK)); + mu := DIGIT((_WORD(x.digit[ix]) * _WORD(rho)) & _WORD(_MASK)) /* a = a + mu * m * b**i Multiply and add in place. */ - u := DIGIT(0); - iy := int(0); + u := DIGIT(0) + iy := int(0) for ; iy < n.used; iy += 1 { /* Compute product and sum. */ - r := (_WORD(mu) * _WORD(n.digit[iy]) + _WORD(u) + _WORD(x.digit[ix + iy])); + r := (_WORD(mu) * _WORD(n.digit[iy]) + _WORD(u) + _WORD(x.digit[ix + iy])) /* Get carry. */ - u = DIGIT(r >> _DIGIT_BITS); + u = DIGIT(r >> _DIGIT_BITS) /* Fix digit. */ - x.digit[ix + iy] = DIGIT(r & _WORD(_MASK)); + x.digit[ix + iy] = DIGIT(r & _WORD(_MASK)) } /* @@ -92,10 +92,10 @@ internal_int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := cont Propagate carries upwards as required. */ for u != 0 { - x.digit[ix + iy] += u; - u = x.digit[ix + iy] >> _DIGIT_BITS; - x.digit[ix + iy] &= _MASK; - iy += 1; + x.digit[ix + iy] += u + u = x.digit[ix + iy] >> _DIGIT_BITS + x.digit[ix + iy] &= _MASK + iy += 1 } } @@ -106,26 +106,26 @@ internal_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); + internal_clamp(x) + internal_shr_digit(x, n.used) /* if x >= n then x = x - n */ if internal_cmp_mag(x, n) != -1 { - return internal_sub(x, x, n); + return internal_sub(x, x, n) } - return nil; + return nil } int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) { - assert_if_nil(x, n); - context.allocator = allocator; + assert_if_nil(x, n) + context.allocator = allocator - internal_clear_if_uninitialized(x, n) or_return; + internal_clear_if_uninitialized(x, n) or_return - return #force_inline internal_int_montgomery_reduce(x, n, rho); + return #force_inline internal_int_montgomery_reduce(x, n, rho) } /* @@ -135,39 +135,39 @@ int_montgomery_reduce :: proc(x, n: ^Int, rho: DIGIT, allocator := context.alloc the leading bit of b. This saves alot of multiple precision shifting. */ internal_int_montgomery_calc_normalization :: proc(a, b: ^Int, allocator := context.allocator) -> (err: Error) { - context.allocator = allocator; + context.allocator = allocator /* How many bits of last digit does b use. */ - bits := internal_count_bits(b) % _DIGIT_BITS; + bits := internal_count_bits(b) % _DIGIT_BITS if b.used > 1 { - power := ((b.used - 1) * _DIGIT_BITS) + bits - 1; - internal_int_power_of_two(a, power) or_return; + power := ((b.used - 1) * _DIGIT_BITS) + bits - 1 + internal_int_power_of_two(a, power) or_return } else { - internal_one(a); - bits = 1; + internal_one(a) + bits = 1 } /* Now compute C = A * B mod b. */ for x := bits - 1; x < _DIGIT_BITS; x += 1 { - internal_int_shl1(a, a) or_return; + internal_int_shl1(a, a) or_return if internal_cmp_mag(a, b) != -1 { - internal_sub(a, a, b) or_return; + internal_sub(a, a, b) or_return } } - return nil; + return nil } int_montgomery_calc_normalization :: proc(a, b: ^Int, allocator := context.allocator) -> (err: Error) { - assert_if_nil(a, b); - context.allocator = allocator; + assert_if_nil(a, b) + context.allocator = allocator - internal_clear_if_uninitialized(a, b) or_return; + internal_clear_if_uninitialized(a, b) or_return - return #force_inline internal_int_montgomery_calc_normalization(a, b); + return #force_inline internal_int_montgomery_calc_normalization(a, b) } /* @@ -182,29 +182,29 @@ internal_int_montgomery_setup :: proc(n: ^Int) -> (rho: DIGIT, err: Error) { => 2*X*A - X*X*A*A = 1 => 2*(1) - (1) = 1 */ - b := n.digit[0]; + b := n.digit[0] if b & 1 == 0 { return 0, .Invalid_Argument; } - x := (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ - x *= 2 - (b * x); /* here x*a==1 mod 2**8 */ - x *= 2 - (b * x); /* here x*a==1 mod 2**16 */ + x := (((b + 2) & 4) << 1) + b /* here x*a==1 mod 2**4 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**8 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**16 */ when _WORD_TYPE_BITS == 64 { - x *= 2 - (b * x); /* here x*a==1 mod 2**32 */ - x *= 2 - (b * x); /* here x*a==1 mod 2**64 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**32 */ + x *= 2 - (b * x) /* here x*a==1 mod 2**64 */ } /* rho = -1/m mod b */ - rho = DIGIT(((_WORD(1) << _WORD(_DIGIT_BITS)) - _WORD(x)) & _WORD(_MASK)); - return rho, nil; + rho = DIGIT(((_WORD(1) << _WORD(_DIGIT_BITS)) - _WORD(x)) & _WORD(_MASK)) + return rho, nil } int_montgomery_setup :: proc(n: ^Int, allocator := context.allocator) -> (rho: DIGIT, err: Error) { - assert_if_nil(n); - internal_clear_if_uninitialized(n, allocator) or_return; + assert_if_nil(n) + internal_clear_if_uninitialized(n, allocator) or_return - return #force_inline internal_int_montgomery_setup(n); + return #force_inline internal_int_montgomery_setup(n) } /* @@ -213,44 +213,44 @@ int_montgomery_setup :: proc(n: ^Int, allocator := context.allocator) -> (rho: D number_of_rabin_miller_trials :: proc(bit_size: int) -> (number_of_trials: int) { switch { case bit_size <= 80: - return - 1; /* Use deterministic algorithm for size <= 80 bits */ + return - 1 /* Use deterministic algorithm for size <= 80 bits */ case bit_size >= 81 && bit_size < 96: - return 37; /* max. error = 2^(-96) */ + return 37 /* max. error = 2^(-96) */ case bit_size >= 96 && bit_size < 128: - return 32; /* max. error = 2^(-96) */ + return 32 /* max. error = 2^(-96) */ case bit_size >= 128 && bit_size < 160: - return 40; /* max. error = 2^(-112) */ + return 40 /* max. error = 2^(-112) */ case bit_size >= 160 && bit_size < 256: - return 35; /* max. error = 2^(-112) */ + return 35 /* max. error = 2^(-112) */ case bit_size >= 256 && bit_size < 384: - return 27; /* max. error = 2^(-128) */ + return 27 /* max. error = 2^(-128) */ case bit_size >= 384 && bit_size < 512: - return 16; /* max. error = 2^(-128) */ + return 16 /* max. error = 2^(-128) */ case bit_size >= 512 && bit_size < 768: - return 18; /* max. error = 2^(-160) */ + return 18 /* max. error = 2^(-160) */ case bit_size >= 768 && bit_size < 896: - return 11; /* max. error = 2^(-160) */ + return 11 /* max. error = 2^(-160) */ case bit_size >= 896 && bit_size < 1_024: - return 10; /* max. error = 2^(-160) */ + return 10 /* max. error = 2^(-160) */ case bit_size >= 1_024 && bit_size < 1_536: - return 12; /* max. error = 2^(-192) */ + return 12 /* max. error = 2^(-192) */ case bit_size >= 1_536 && bit_size < 2_048: - return 8; /* max. error = 2^(-192) */ + return 8 /* max. error = 2^(-192) */ case bit_size >= 2_048 && bit_size < 3_072: - return 6; /* max. error = 2^(-192) */ + return 6 /* max. error = 2^(-192) */ case bit_size >= 3_072 && bit_size < 4_096: - return 4; /* max. error = 2^(-192) */ + return 4 /* max. error = 2^(-192) */ case bit_size >= 4_096 && bit_size < 5_120: - return 5; /* max. error = 2^(-256) */ + return 5 /* max. error = 2^(-256) */ case bit_size >= 5_120 && bit_size < 6_144: - return 4; /* max. error = 2^(-256) */ + return 4 /* max. error = 2^(-256) */ case bit_size >= 6_144 && bit_size < 8_192: - return 4; /* max. error = 2^(-256) */ + return 4 /* max. error = 2^(-256) */ case bit_size >= 8_192 && bit_size < 9_216: - return 3; /* max. error = 2^(-256) */ + return 3 /* max. error = 2^(-256) */ case bit_size >= 9_216 && bit_size < 10_240: - return 3; /* max. error = 2^(-256) */ + return 3 /* max. error = 2^(-256) */ case: - return 2; /* For keysizes bigger than 10_240 use always at least 2 Rounds */ + return 2 /* For keysizes bigger than 10_240 use always at least 2 Rounds */ } }
\ No newline at end of file diff --git a/core/math/big/private.odin b/core/math/big/private.odin index d71946ce2..81bae57f0 100644 --- a/core/math/big/private.odin +++ b/core/math/big/private.odin @@ -27,35 +27,35 @@ import "core:mem" many digits of output are created.
*/
_private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Can we use the fast multiplier?
*/
if digits < _WARRAY && min(a.used, b.used) < _MAX_COMBA {
- return #force_inline _private_int_mul_comba(dest, a, b, digits);
+ return #force_inline _private_int_mul_comba(dest, a, b, digits)
}
/*
Set up temporary output `Int`, which we'll swap for `dest` when done.
*/
- t := &Int{};
+ t := &Int{}
- internal_grow(t, max(digits, _DEFAULT_DIGIT_COUNT)) or_return;
- t.used = digits;
+ internal_grow(t, max(digits, _DEFAULT_DIGIT_COUNT)) or_return
+ t.used = digits
/*
Compute the digits of the product directly.
*/
- pa := a.used;
+ pa := a.used
for ix := 0; ix < pa; ix += 1 {
/*
Limit ourselves to `digits` DIGITs of output.
*/
- pb := min(b.used, digits - ix);
- carry := _WORD(0);
- iy := 0;
+ pb := min(b.used, digits - ix)
+ carry := _WORD(0)
+ iy := 0
/*
Compute the column of the output and propagate the carry.
@@ -64,29 +64,29 @@ _private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.all /*
Compute the column as a _WORD.
*/
- column := _WORD(t.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + carry;
+ column := _WORD(t.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + carry
/*
The new column is the lower part of the result.
*/
- t.digit[ix + iy] = DIGIT(column & _WORD(_MASK));
+ t.digit[ix + iy] = DIGIT(column & _WORD(_MASK))
/*
Get the carry word from the result.
*/
- carry = column >> _DIGIT_BITS;
+ carry = column >> _DIGIT_BITS
}
/*
Set carry if it is placed below digits
*/
if ix + iy < digits {
- t.digit[ix + pb] = DIGIT(carry);
+ t.digit[ix + pb] = DIGIT(carry)
}
}
- internal_swap(dest, t);
- internal_destroy(t);
- return internal_clamp(dest);
+ internal_swap(dest, t)
+ internal_destroy(t)
+ return internal_clamp(dest)
}
@@ -110,121 +110,121 @@ _private_int_mul :: proc(dest, a, b: ^Int, digits: int, allocator := context.all Centro Vito Volterra Universita di Roma Tor Vergata (2006)
*/
_private_int_mul_toom :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- S1, S2, T1, a0, a1, a2, b0, b1, b2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(S1, S2, T1, a0, a1, a2, b0, b1, b2);
+ S1, S2, T1, a0, a1, a2, b0, b1, b2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(S1, S2, T1, a0, a1, a2, b0, b1, b2)
/*
Init temps.
*/
- internal_init_multi(S1, S2, T1) or_return;
+ internal_init_multi(S1, S2, T1) or_return
/*
B
*/
- B := min(a.used, b.used) / 3;
+ B := min(a.used, b.used) / 3
/*
a = a2 * x^2 + a1 * x + a0;
*/
- internal_grow(a0, B) or_return;
- internal_grow(a1, B) or_return;
- internal_grow(a2, a.used - 2 * B) or_return;
+ internal_grow(a0, B) or_return
+ internal_grow(a1, B) or_return
+ internal_grow(a2, a.used - 2 * B) or_return
- a0.used, a1.used = B, B;
- a2.used = a.used - 2 * B;
+ a0.used, a1.used = B, B
+ a2.used = a.used - 2 * B
- internal_copy_digits(a0, a, a0.used) or_return;
- internal_copy_digits(a1, a, a1.used, B) or_return;
- internal_copy_digits(a2, a, a2.used, 2 * B) or_return;
+ internal_copy_digits(a0, a, a0.used) or_return
+ internal_copy_digits(a1, a, a1.used, B) or_return
+ internal_copy_digits(a2, a, a2.used, 2 * B) or_return
- internal_clamp(a0);
- internal_clamp(a1);
- internal_clamp(a2);
+ internal_clamp(a0)
+ internal_clamp(a1)
+ internal_clamp(a2)
/*
b = b2 * x^2 + b1 * x + b0;
*/
- internal_grow(b0, B) or_return;
- internal_grow(b1, B) or_return;
- internal_grow(b2, b.used - 2 * B) or_return;
+ internal_grow(b0, B) or_return
+ internal_grow(b1, B) or_return
+ internal_grow(b2, b.used - 2 * B) or_return
- b0.used, b1.used = B, B;
- b2.used = b.used - 2 * B;
+ b0.used, b1.used = B, B
+ b2.used = b.used - 2 * B
- internal_copy_digits(b0, b, b0.used) or_return;
- internal_copy_digits(b1, b, b1.used, B) or_return;
- internal_copy_digits(b2, b, b2.used, 2 * B) or_return;
+ internal_copy_digits(b0, b, b0.used) or_return
+ internal_copy_digits(b1, b, b1.used, B) or_return
+ internal_copy_digits(b2, b, b2.used, 2 * B) or_return
- internal_clamp(b0);
- internal_clamp(b1);
- internal_clamp(b2);
+ internal_clamp(b0)
+ internal_clamp(b1)
+ internal_clamp(b2)
/*
\\ S1 = (a2+a1+a0) * (b2+b1+b0);
*/
- internal_add(T1, a2, a1) or_return; /* T1 = a2 + a1; */
- internal_add(S2, T1, a0) or_return; /* S2 = T1 + a0; */
- internal_add(dest, b2, b1) or_return; /* dest = b2 + b1; */
- internal_add(S1, dest, b0) or_return; /* S1 = c + b0; */
- internal_mul(S1, S1, S2) or_return; /* S1 = S1 * S2; */
+ internal_add(T1, a2, a1) or_return /* T1 = a2 + a1; */
+ internal_add(S2, T1, a0) or_return /* S2 = T1 + a0; */
+ internal_add(dest, b2, b1) or_return /* dest = b2 + b1; */
+ internal_add(S1, dest, b0) or_return /* S1 = c + b0; */
+ internal_mul(S1, S1, S2) or_return /* S1 = S1 * S2; */
/*
\\S2 = (4*a2+2*a1+a0) * (4*b2+2*b1+b0);
*/
- internal_add(T1, T1, a2) or_return; /* T1 = T1 + a2; */
- internal_int_shl1(T1, T1) or_return; /* T1 = T1 << 1; */
- internal_add(T1, T1, a0) or_return; /* T1 = T1 + a0; */
- internal_add(dest, dest, b2) or_return; /* c = c + b2; */
- internal_int_shl1(dest, dest) or_return; /* c = c << 1; */
- internal_add(dest, dest, b0) or_return; /* c = c + b0; */
- internal_mul(S2, T1, dest) or_return; /* S2 = T1 * c; */
+ internal_add(T1, T1, a2) or_return /* T1 = T1 + a2; */
+ internal_int_shl1(T1, T1) or_return /* T1 = T1 << 1; */
+ internal_add(T1, T1, a0) or_return /* T1 = T1 + a0; */
+ internal_add(dest, dest, b2) or_return /* c = c + b2; */
+ internal_int_shl1(dest, dest) or_return /* c = c << 1; */
+ internal_add(dest, dest, b0) or_return /* c = c + b0; */
+ internal_mul(S2, T1, dest) or_return /* S2 = T1 * c; */
/*
\\S3 = (a2-a1+a0) * (b2-b1+b0);
*/
- internal_sub(a1, a2, a1) or_return; /* a1 = a2 - a1; */
- internal_add(a1, a1, a0) or_return; /* a1 = a1 + a0; */
- internal_sub(b1, b2, b1) or_return; /* b1 = b2 - b1; */
- internal_add(b1, b1, b0) or_return; /* b1 = b1 + b0; */
- internal_mul(a1, a1, b1) or_return; /* a1 = a1 * b1; */
- internal_mul(b1, a2, b2) or_return; /* b1 = a2 * b2; */
+ internal_sub(a1, a2, a1) or_return /* a1 = a2 - a1; */
+ internal_add(a1, a1, a0) or_return /* a1 = a1 + a0; */
+ internal_sub(b1, b2, b1) or_return /* b1 = b2 - b1; */
+ internal_add(b1, b1, b0) or_return /* b1 = b1 + b0; */
+ internal_mul(a1, a1, b1) or_return /* a1 = a1 * b1; */
+ internal_mul(b1, a2, b2) or_return /* b1 = a2 * b2; */
/*
\\S2 = (S2 - S3) / 3;
*/
- internal_sub(S2, S2, a1) or_return; /* S2 = S2 - a1; */
- _private_int_div_3(S2, S2) or_return; /* S2 = S2 / 3; \\ this is an exact division */
- internal_sub(a1, S1, a1) or_return; /* a1 = S1 - a1; */
- internal_int_shr1(a1, a1) or_return; /* a1 = a1 >> 1; */
- internal_mul(a0, a0, b0) or_return; /* a0 = a0 * b0; */
- internal_sub(S1, S1, a0) or_return; /* S1 = S1 - a0; */
- internal_sub(S2, S2, S1) or_return; /* S2 = S2 - S1; */
- internal_int_shr1(S2, S2) or_return; /* S2 = S2 >> 1; */
- internal_sub(S1, S1, a1) or_return; /* S1 = S1 - a1; */
- internal_sub(S1, S1, b1) or_return; /* S1 = S1 - b1; */
- internal_int_shl1(T1, b1) or_return; /* T1 = b1 << 1; */
- internal_sub(S2, S2, T1) or_return; /* S2 = S2 - T1; */
- internal_sub(a1, a1, S2) or_return; /* a1 = a1 - S2; */
+ internal_sub(S2, S2, a1) or_return /* S2 = S2 - a1; */
+ _private_int_div_3(S2, S2) or_return /* S2 = S2 / 3; \\ this is an exact division */
+ internal_sub(a1, S1, a1) or_return /* a1 = S1 - a1; */
+ internal_int_shr1(a1, a1) or_return /* a1 = a1 >> 1; */
+ internal_mul(a0, a0, b0) or_return /* a0 = a0 * b0; */
+ internal_sub(S1, S1, a0) or_return /* S1 = S1 - a0; */
+ internal_sub(S2, S2, S1) or_return /* S2 = S2 - S1; */
+ internal_int_shr1(S2, S2) or_return /* S2 = S2 >> 1; */
+ internal_sub(S1, S1, a1) or_return /* S1 = S1 - a1; */
+ internal_sub(S1, S1, b1) or_return /* S1 = S1 - b1; */
+ internal_int_shl1(T1, b1) or_return /* T1 = b1 << 1; */
+ internal_sub(S2, S2, T1) or_return /* S2 = S2 - T1; */
+ internal_sub(a1, a1, S2) or_return /* a1 = a1 - S2; */
/*
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;
- internal_add(b1, b1, S2) or_return;
- internal_shl_digit(S1, 2 * B) or_return;
- internal_add(b1, b1, S1) or_return;
- internal_shl_digit(a1, 1 * B) or_return;
- internal_add(b1, b1, a1) or_return;
- internal_add(dest, b1, a0) or_return;
+ internal_shl_digit(b1, 4 * B) or_return
+ internal_shl_digit(S2, 3 * B) or_return
+ internal_add(b1, b1, S2) or_return
+ internal_shl_digit(S1, 2 * B) or_return
+ internal_add(b1, b1, S1) or_return
+ internal_shl_digit(a1, 1 * B) or_return
+ internal_add(b1, b1, a1) or_return
+ internal_add(dest, b1, a0) or_return
/*
a * b - P
*/
- return nil;
+ return nil
}
/*
@@ -255,76 +255,76 @@ _private_int_mul_toom :: proc(dest, a, b: ^Int, allocator := context.allocator) until a certain size is reached, of around 80 used DIGITs.
*/
_private_int_mul_karatsuba :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- x0, x1, y0, y1, t1, x0y0, x1y1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x0, x1, y0, y1, t1, x0y0, x1y1);
+ x0, x1, y0, y1, t1, x0y0, x1y1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x0, x1, y0, y1, t1, x0y0, x1y1)
/*
min # of digits, divided by two.
*/
- B := min(a.used, b.used) >> 1;
+ B := min(a.used, b.used) >> 1
/*
Init all the temps.
*/
- internal_grow(x0, B) or_return;
- internal_grow(x1, a.used - B) or_return;
- internal_grow(y0, B) or_return;
- internal_grow(y1, b.used - B) or_return;
- internal_grow(t1, B * 2) or_return;
- internal_grow(x0y0, B * 2) or_return;
- internal_grow(x1y1, B * 2) or_return;
+ internal_grow(x0, B) or_return
+ internal_grow(x1, a.used - B) or_return
+ internal_grow(y0, B) or_return
+ internal_grow(y1, b.used - B) or_return
+ internal_grow(t1, B * 2) or_return
+ internal_grow(x0y0, B * 2) or_return
+ internal_grow(x1y1, B * 2) or_return
/*
Now shift the digits.
*/
- x0.used, y0.used = B, B;
- x1.used = a.used - B;
- y1.used = b.used - B;
+ x0.used, y0.used = B, B
+ x1.used = a.used - B
+ y1.used = b.used - B
/*
We copy the digits directly instead of using higher level functions
since we also need to shift the digits.
*/
- internal_copy_digits(x0, a, x0.used);
- internal_copy_digits(y0, b, y0.used);
- internal_copy_digits(x1, a, x1.used, B);
- internal_copy_digits(y1, b, y1.used, B);
+ internal_copy_digits(x0, a, x0.used)
+ internal_copy_digits(y0, b, y0.used)
+ internal_copy_digits(x1, a, x1.used, B)
+ internal_copy_digits(y1, b, y1.used, B)
/*
Only need to clamp the lower words since by definition the
upper words x1/y1 must have a known number of digits.
*/
- clamp(x0);
- clamp(y0);
+ clamp(x0)
+ clamp(y0)
/*
Now calc the products x0y0 and x1y1,
after this x0 is no longer required, free temp [x0==t2]!
*/
- internal_mul(x0y0, x0, y0) or_return; /* x0y0 = x0*y0 */
- internal_mul(x1y1, x1, y1) or_return; /* x1y1 = x1*y1 */
- internal_add(t1, x1, x0) or_return; /* now calc x1+x0 and */
- internal_add(x0, y1, y0) or_return; /* t2 = y1 + y0 */
- internal_mul(t1, t1, x0) or_return; /* t1 = (x1 + x0) * (y1 + y0) */
+ internal_mul(x0y0, x0, y0) or_return /* x0y0 = x0*y0 */
+ internal_mul(x1y1, x1, y1) or_return /* x1y1 = x1*y1 */
+ internal_add(t1, x1, x0) or_return /* now calc x1+x0 and */
+ internal_add(x0, y1, y0) or_return /* t2 = y1 + y0 */
+ internal_mul(t1, t1, x0) or_return /* t1 = (x1 + x0) * (y1 + y0) */
/*
Add x0y0.
*/
- internal_add(x0, x0y0, x1y1) or_return; /* t2 = x0y0 + x1y1 */
- internal_sub(t1, t1, x0) or_return; /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
+ internal_add(x0, x0y0, x1y1) or_return /* t2 = x0y0 + x1y1 */
+ internal_sub(t1, t1, x0) or_return /* t1 = (x1+x0)*(y1+y0) - (x1y1 + x0y0) */
/*
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 */
+ 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 */
- internal_add(t1, x0y0, t1) or_return; /* t1 = x0y0 + t1 */
- internal_add(dest, t1, x1y1) or_return; /* t1 = x0y0 + t1 + x1y1 */
+ internal_add(t1, x0y0, t1) or_return /* t1 = x0y0 + t1 */
+ internal_add(dest, t1, x1y1) or_return /* t1 = x0y0 + t1 + x1y1 */
- return nil;
+ return nil
}
@@ -346,84 +346,84 @@ _private_int_mul_karatsuba :: proc(dest, a, b: ^Int, allocator := context.alloca Based on Algorithm 14.12 on pp.595 of HAC.
*/
_private_int_mul_comba :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Set up array.
*/
- W: [_WARRAY]DIGIT = ---;
+ W: [_WARRAY]DIGIT = ---
/*
Grow the destination as required.
*/
- internal_grow(dest, digits) or_return;
+ internal_grow(dest, digits) or_return
/*
Number of output digits to produce.
*/
- pa := min(digits, a.used + b.used);
+ pa := min(digits, a.used + b.used)
/*
Clear the carry
*/
- _W := _WORD(0);
+ _W := _WORD(0)
- ix: int;
+ ix: int
for ix = 0; ix < pa; ix += 1 {
- tx, ty, iy, iz: int;
+ tx, ty, iy, iz: int
/*
Get offsets into the two bignums.
*/
- ty = min(b.used - 1, ix);
- tx = ix - ty;
+ ty = min(b.used - 1, ix)
+ tx = ix - ty
/*
This is the number of times the loop will iterate, essentially.
while (tx++ < a->used && ty-- >= 0) { ... }
*/
- iy = min(a.used - tx, ty + 1);
+ iy = min(a.used - tx, ty + 1)
/*
Execute loop.
*/
#no_bounds_check for iz = 0; iz < iy; iz += 1 {
- _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz]);
+ _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz])
}
/*
Store term.
*/
- W[ix] = DIGIT(_W) & _MASK;
+ W[ix] = DIGIT(_W) & _MASK
/*
Make next carry.
*/
- _W = _W >> _WORD(_DIGIT_BITS);
+ _W = _W >> _WORD(_DIGIT_BITS)
}
/*
Setup dest.
*/
- old_used := dest.used;
- dest.used = pa;
+ old_used := dest.used
+ dest.used = pa
/*
Now extract the previous digit [below the carry].
*/
- copy_slice(dest.digit[0:], W[:pa]);
+ copy_slice(dest.digit[0:], W[:pa])
/*
Clear unused digits [that existed in the old copy of dest].
*/
- internal_zero_unused(dest, old_used);
+ internal_zero_unused(dest, old_used)
/*
Adjust dest.used based on leading zeroes.
*/
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
@@ -431,42 +431,42 @@ _private_int_mul_comba :: proc(dest, a, b: ^Int, digits: int, allocator := conte [meant to get the higher part of the product]
*/
_private_int_mul_high :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Can we use the fast multiplier?
*/
if a.used + b.used + 1 < _WARRAY && min(a.used, b.used) < _MAX_COMBA {
- return _private_int_mul_high_comba(dest, a, b, digits);
+ return _private_int_mul_high_comba(dest, a, b, digits)
}
- internal_grow(dest, a.used + b.used + 1) or_return;
- dest.used = a.used + b.used + 1;
+ internal_grow(dest, a.used + b.used + 1) or_return
+ dest.used = a.used + b.used + 1
- pa := a.used;
- pb := b.used;
+ pa := a.used
+ pb := b.used
for ix := 0; ix < pa; ix += 1 {
- carry := DIGIT(0);
+ carry := DIGIT(0)
for iy := digits - ix; iy < pb; iy += 1 {
/*
Calculate the double precision result.
*/
- r := _WORD(dest.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + _WORD(carry);
+ r := _WORD(dest.digit[ix + iy]) + _WORD(a.digit[ix]) * _WORD(b.digit[iy]) + _WORD(carry)
/*
Get the lower part.
*/
- dest.digit[ix + iy] = DIGIT(r & _WORD(_MASK));
+ dest.digit[ix + iy] = DIGIT(r & _WORD(_MASK))
/*
Carry the carry.
*/
- carry = DIGIT(r >> _WORD(_DIGIT_BITS));
+ carry = DIGIT(r >> _WORD(_DIGIT_BITS))
}
- dest.digit[ix + pb] = carry;
+ dest.digit[ix + pb] = carry
}
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
@@ -479,140 +479,140 @@ _private_int_mul_high :: proc(dest, a, b: ^Int, digits: int, allocator := contex Based on Algorithm 14.12 on pp.595 of HAC.
*/
_private_int_mul_high_comba :: proc(dest, a, b: ^Int, digits: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- W: [_WARRAY]DIGIT = ---;
- _W: _WORD = 0;
+ W: [_WARRAY]DIGIT = ---
+ _W: _WORD = 0
/*
Number of output digits to produce. Grow the destination as required.
*/
- pa := a.used + b.used;
- internal_grow(dest, pa) or_return;
+ pa := a.used + b.used
+ internal_grow(dest, pa) or_return
- ix: int;
+ ix: int
for ix = digits; ix < pa; ix += 1 {
/*
Get offsets into the two bignums.
*/
- ty := min(b.used - 1, ix);
- tx := ix - ty;
+ ty := min(b.used - 1, ix)
+ tx := ix - ty
/*
This is the number of times the loop will iterrate, essentially it's
while (tx++ < a->used && ty-- >= 0) { ... }
*/
- iy := min(a.used - tx, ty + 1);
+ iy := min(a.used - tx, ty + 1)
/*
Execute loop.
*/
for iz := 0; iz < iy; iz += 1 {
- _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz]);
+ _W += _WORD(a.digit[tx + iz]) * _WORD(b.digit[ty - iz])
}
/*
Store term.
*/
- W[ix] = DIGIT(_W) & DIGIT(_MASK);
+ W[ix] = DIGIT(_W) & DIGIT(_MASK)
/*
Make next carry.
*/
- _W = _W >> _WORD(_DIGIT_BITS);
+ _W = _W >> _WORD(_DIGIT_BITS)
}
/*
Setup dest
*/
- old_used := dest.used;
- dest.used = pa;
+ old_used := dest.used
+ dest.used = pa
for ix = digits; ix < pa; ix += 1 {
/*
Now extract the previous digit [below the carry].
*/
- dest.digit[ix] = W[ix];
+ dest.digit[ix] = W[ix]
}
/*
Zero remainder.
*/
- internal_zero_unused(dest, old_used);
+ internal_zero_unused(dest, old_used)
/*
Adjust dest.used based on leading zeroes.
*/
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
Single-digit multiplication with the smaller number as the single-digit.
*/
_private_int_mul_balance :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- a, b := a, b;
+ context.allocator = allocator
+ a, b := a, b
- a0, tmp, r := &Int{}, &Int{}, &Int{};
- defer internal_destroy(a0, tmp, r);
+ a0, tmp, r := &Int{}, &Int{}, &Int{}
+ defer internal_destroy(a0, tmp, r)
- b_size := min(a.used, b.used);
- n_blocks := max(a.used, b.used) / b_size;
+ b_size := min(a.used, b.used)
+ n_blocks := max(a.used, b.used) / b_size
- internal_grow(a0, b_size + 2) or_return;
- internal_init_multi(tmp, r) or_return;
+ internal_grow(a0, b_size + 2) or_return
+ internal_init_multi(tmp, r) or_return
/*
Make sure that `a` is the larger one.
*/
if a.used < b.used {
- a, b = b, a;
+ a, b = b, a
}
- assert(a.used >= b.used);
+ assert(a.used >= b.used)
- i, j := 0, 0;
+ i, j := 0, 0
for ; i < n_blocks; i += 1 {
/*
Cut a slice off of `a`.
*/
- a0.used = b_size;
- internal_copy_digits(a0, a, a0.used, j);
- j += a0.used;
- internal_clamp(a0);
+ a0.used = b_size
+ internal_copy_digits(a0, a, a0.used, j)
+ j += a0.used
+ internal_clamp(a0)
/*
Multiply with `b`.
*/
- internal_mul(tmp, a0, b) or_return;
+ internal_mul(tmp, a0, b) or_return
/*
Shift `tmp` to the correct position.
*/
- internal_shl_digit(tmp, b_size * i) or_return;
+ internal_shl_digit(tmp, b_size * i) or_return
/*
Add to output. No carry needed.
*/
- internal_add(r, r, tmp) or_return;
+ internal_add(r, r, tmp) or_return
}
/*
The left-overs; there are always left-overs.
*/
if j < a.used {
- a0.used = a.used - j;
- internal_copy_digits(a0, a, a0.used, j);
- j += a0.used;
- internal_clamp(a0);
-
- internal_mul(tmp, a0, b) or_return;
- internal_shl_digit(tmp, b_size * i) or_return;
- internal_add(r, r, tmp) or_return;
+ a0.used = a.used - j
+ internal_copy_digits(a0, a, a0.used, j)
+ j += a0.used
+ internal_clamp(a0)
+
+ internal_mul(tmp, a0, b) or_return
+ internal_shl_digit(tmp, b_size * i) or_return
+ internal_add(r, r, tmp) or_return
}
- internal_swap(dest, r);
- return;
+ internal_swap(dest, r)
+ return
}
/*
@@ -620,68 +620,68 @@ _private_int_mul_balance :: proc(dest, a, b: ^Int, allocator := context.allocato Assumes `dest` and `src` to not be `nil`, and `src` to have been initialized.
*/
_private_int_sqr :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- pa := src.used;
+ context.allocator = allocator
+ pa := src.used
- t := &Int{}; ix, iy: int;
+ t := &Int{}; ix, iy: int
/*
Grow `t` to maximum needed size, or `_DEFAULT_DIGIT_COUNT`, whichever is bigger.
*/
- internal_grow(t, max((2 * pa) + 1, _DEFAULT_DIGIT_COUNT)) or_return;
- t.used = (2 * pa) + 1;
+ internal_grow(t, max((2 * pa) + 1, _DEFAULT_DIGIT_COUNT)) or_return
+ t.used = (2 * pa) + 1
#no_bounds_check for ix = 0; ix < pa; ix += 1 {
- carry := DIGIT(0);
+ carry := DIGIT(0)
/*
First calculate the digit at 2*ix; calculate double precision result.
*/
- r := _WORD(t.digit[ix+ix]) + (_WORD(src.digit[ix]) * _WORD(src.digit[ix]));
+ r := _WORD(t.digit[ix+ix]) + (_WORD(src.digit[ix]) * _WORD(src.digit[ix]))
/*
Store lower part in result.
*/
- t.digit[ix+ix] = DIGIT(r & _WORD(_MASK));
+ t.digit[ix+ix] = DIGIT(r & _WORD(_MASK))
/*
Get the carry.
*/
- carry = DIGIT(r >> _DIGIT_BITS);
+ carry = DIGIT(r >> _DIGIT_BITS)
#no_bounds_check for iy = ix + 1; iy < pa; iy += 1 {
/*
First calculate the product.
*/
- r = _WORD(src.digit[ix]) * _WORD(src.digit[iy]);
+ r = _WORD(src.digit[ix]) * _WORD(src.digit[iy])
/* Now calculate the double precision result. Nóte we use
* addition instead of *2 since it's easier to optimize
*/
- r = _WORD(t.digit[ix+iy]) + r + r + _WORD(carry);
+ r = _WORD(t.digit[ix+iy]) + r + r + _WORD(carry)
/*
Store lower part.
*/
- t.digit[ix+iy] = DIGIT(r & _WORD(_MASK));
+ t.digit[ix+iy] = DIGIT(r & _WORD(_MASK))
/*
Get carry.
*/
- carry = DIGIT(r >> _DIGIT_BITS);
+ carry = DIGIT(r >> _DIGIT_BITS)
}
/*
Propagate upwards.
*/
#no_bounds_check for carry != 0 {
- r = _WORD(t.digit[ix+iy]) + _WORD(carry);
- t.digit[ix+iy] = DIGIT(r & _WORD(_MASK));
- carry = DIGIT(r >> _WORD(_DIGIT_BITS));
- iy += 1;
+ r = _WORD(t.digit[ix+iy]) + _WORD(carry)
+ t.digit[ix+iy] = DIGIT(r & _WORD(_MASK))
+ carry = DIGIT(r >> _WORD(_DIGIT_BITS))
+ iy += 1
}
}
- err = internal_clamp(t);
- internal_swap(dest, t);
- internal_destroy(t);
- return err;
+ err = internal_clamp(t)
+ internal_swap(dest, t)
+ internal_destroy(t)
+ return err
}
/*
@@ -693,94 +693,94 @@ _private_int_sqr :: proc(dest, src: ^Int, allocator := context.allocator) -> (er Assumes `dest` and `src` not to be `nil` and `src` to have been initialized.
*/
_private_int_sqr_comba :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- W: [_WARRAY]DIGIT = ---;
+ W: [_WARRAY]DIGIT = ---
/*
Grow the destination as required.
*/
- pa := uint(src.used) + uint(src.used);
- internal_grow(dest, int(pa)) or_return;
+ pa := uint(src.used) + uint(src.used)
+ internal_grow(dest, int(pa)) or_return
/*
Number of output digits to produce.
*/
- W1 := _WORD(0);
- _W : _WORD = ---;
- ix := uint(0);
+ W1 := _WORD(0)
+ _W : _WORD = ---
+ ix := uint(0)
#no_bounds_check for ; ix < pa; ix += 1 {
/*
Clear counter.
*/
- _W = {};
+ _W = {}
/*
Get offsets into the two bignums.
*/
- ty := min(uint(src.used) - 1, ix);
- tx := ix - ty;
+ ty := min(uint(src.used) - 1, ix)
+ tx := ix - ty
/*
This is the number of times the loop will iterate,
essentially while (tx++ < a->used && ty-- >= 0) { ... }
*/
- iy := min(uint(src.used) - tx, ty + 1);
+ iy := min(uint(src.used) - tx, ty + 1)
/*
Now for squaring, tx can never equal ty.
We halve the distance since they approach at a rate of 2x,
and we have to round because odd cases need to be executed.
*/
- iy = min(iy, ((ty - tx) + 1) >> 1 );
+ iy = min(iy, ((ty - tx) + 1) >> 1 )
/*
Execute loop.
*/
#no_bounds_check for iz := uint(0); iz < iy; iz += 1 {
- _W += _WORD(src.digit[tx + iz]) * _WORD(src.digit[ty - iz]);
+ _W += _WORD(src.digit[tx + iz]) * _WORD(src.digit[ty - iz])
}
/*
Double the inner product and add carry.
*/
- _W = _W + _W + W1;
+ _W = _W + _W + W1
/*
Even columns have the square term in them.
*/
if ix & 1 == 0 {
- _W += _WORD(src.digit[ix >> 1]) * _WORD(src.digit[ix >> 1]);
+ _W += _WORD(src.digit[ix >> 1]) * _WORD(src.digit[ix >> 1])
}
/*
Store it.
*/
- W[ix] = DIGIT(_W & _WORD(_MASK));
+ W[ix] = DIGIT(_W & _WORD(_MASK))
/*
Make next carry.
*/
- W1 = _W >> _DIGIT_BITS;
+ W1 = _W >> _DIGIT_BITS
}
/*
Setup dest.
*/
- old_used := dest.used;
- dest.used = src.used + src.used;
+ old_used := dest.used
+ dest.used = src.used + src.used
#no_bounds_check for ix = 0; ix < pa; ix += 1 {
- dest.digit[ix] = W[ix] & _MASK;
+ dest.digit[ix] = W[ix] & _MASK
}
/*
Clear unused digits [that existed in the old copy of dest].
*/
- internal_zero_unused(dest, old_used);
+ internal_zero_unused(dest, old_used)
- return internal_clamp(dest);
+ return internal_clamp(dest)
}
/*
@@ -790,31 +790,31 @@ _private_int_sqr_comba :: proc(dest, src: ^Int, allocator := context.allocator) It is essentially the same algorithm but merely tuned to perform recursive squarings.
*/
_private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- x0, x1, t1, t2, x0x0, x1x1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x0, x1, t1, t2, x0x0, x1x1);
+ x0, x1, t1, t2, x0x0, x1x1 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x0, x1, t1, t2, x0x0, x1x1)
/*
Min # of digits, divided by two.
*/
- B := src.used >> 1;
+ B := src.used >> 1
/*
Init temps.
*/
- internal_grow(x0, B) or_return;
- internal_grow(x1, src.used - B) or_return;
- internal_grow(t1, src.used * 2) or_return;
- internal_grow(t2, src.used * 2) or_return;
- internal_grow(x0x0, B * 2 ) or_return;
- internal_grow(x1x1, (src.used - B) * 2) or_return;
+ internal_grow(x0, B) or_return
+ internal_grow(x1, src.used - B) or_return
+ internal_grow(t1, src.used * 2) or_return
+ internal_grow(t2, src.used * 2) or_return
+ internal_grow(x0x0, B * 2 ) or_return
+ internal_grow(x1x1, (src.used - B) * 2) or_return
/*
Now shift the digits.
*/
- x0.used = B;
- x1.used = src.used - B;
+ x0.used = B
+ x1.used = src.used - B
#force_inline internal_copy_digits(x0, src, x0.used);
#force_inline mem.copy_non_overlapping(&x1.digit[0], &src.digit[B], size_of(DIGIT) * x1.used);
@@ -823,30 +823,30 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat /*
Now calc the products x0*x0 and x1*x1.
*/
- internal_sqr(x0x0, x0) or_return;
- internal_sqr(x1x1, x1) or_return;
+ internal_sqr(x0x0, x0) or_return
+ internal_sqr(x1x1, x1) or_return
/*
Now calc (x1+x0)^2
*/
- internal_add(t1, x0, x1) or_return;
- internal_sqr(t1, t1) or_return;
+ internal_add(t1, x0, x1) or_return
+ internal_sqr(t1, t1) or_return
/*
Add x0y0
*/
- internal_add(t2, x0x0, x1x1) or_return;
- internal_sub(t1, t1, t2) or_return;
+ internal_add(t2, x0x0, x1x1) or_return
+ internal_sub(t1, t1, t2) or_return
/*
Shift by B.
*/
- internal_shl_digit(t1, B) or_return;
- internal_shl_digit(x1x1, B * 2) or_return;
- internal_add(t1, t1, x0x0) or_return;
- internal_add(dest, t1, x1x1) or_return;
+ internal_shl_digit(t1, B) or_return
+ internal_shl_digit(x1x1, B * 2) or_return
+ internal_add(t1, t1, x0x0) or_return
+ internal_add(dest, t1, x1x1) or_return
- return #force_inline internal_clamp(dest);
+ return #force_inline internal_clamp(dest)
}
/*
@@ -856,160 +856,160 @@ _private_int_sqr_karatsuba :: proc(dest, src: ^Int, allocator := context.allocat 18th IEEE Symposium on Computer Arithmetic (ARITH'07). IEEE, 2007.
*/
_private_int_sqr_toom :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- S0, a0, a1, a2 := &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(S0, a0, a1, a2);
+ S0, a0, a1, a2 := &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(S0, a0, a1, a2)
/*
Init temps.
*/
- internal_zero(S0) or_return;
+ internal_zero(S0) or_return
/*
B
*/
- B := src.used / 3;
+ B := src.used / 3
/*
a = a2 * x^2 + a1 * x + a0;
*/
- internal_grow(a0, B) or_return;
- internal_grow(a1, B) or_return;
- internal_grow(a2, src.used - (2 * B)) or_return;
+ internal_grow(a0, B) or_return
+ internal_grow(a1, B) or_return
+ internal_grow(a2, src.used - (2 * B)) or_return
- a0.used = B;
- a1.used = B;
- a2.used = src.used - 2 * B;
+ a0.used = B
+ a1.used = B
+ a2.used = src.used - 2 * B
#force_inline mem.copy_non_overlapping(&a0.digit[0], &src.digit[ 0], size_of(DIGIT) * a0.used);
#force_inline mem.copy_non_overlapping(&a1.digit[0], &src.digit[ B], size_of(DIGIT) * a1.used);
#force_inline mem.copy_non_overlapping(&a2.digit[0], &src.digit[2 * B], size_of(DIGIT) * a2.used);
- internal_clamp(a0);
- internal_clamp(a1);
- internal_clamp(a2);
+ internal_clamp(a0)
+ internal_clamp(a1)
+ internal_clamp(a2)
/** S0 = a0^2; */
- internal_sqr(S0, a0) or_return;
+ internal_sqr(S0, a0) or_return
/** \\S1 = (a2 + a1 + a0)^2 */
/** \\S2 = (a2 - a1 + a0)^2 */
/** \\S1 = a0 + a2; */
/** a0 = a0 + a2; */
- internal_add(a0, a0, a2) or_return;
+ internal_add(a0, a0, a2) or_return
/** \\S2 = S1 - a1; */
/** b = a0 - a1; */
- internal_sub(dest, a0, a1) or_return;
+ internal_sub(dest, a0, a1) or_return
/** \\S1 = S1 + a1; */
/** a0 = a0 + a1; */
- internal_add(a0, a0, a1) or_return;
+ internal_add(a0, a0, a1) or_return
/** \\S1 = S1^2; */
/** a0 = a0^2; */
- internal_sqr(a0, a0) or_return;
+ internal_sqr(a0, a0) or_return
/** \\S2 = S2^2; */
/** b = b^2; */
- internal_sqr(dest, dest) or_return;
+ internal_sqr(dest, dest) or_return
/** \\ S3 = 2 * a1 * a2 */
/** \\S3 = a1 * a2; */
/** a1 = a1 * a2; */
- internal_mul(a1, a1, a2) or_return;
+ internal_mul(a1, a1, a2) or_return
/** \\S3 = S3 << 1; */
/** a1 = a1 << 1; */
- internal_shl(a1, a1, 1) or_return;
+ internal_shl(a1, a1, 1) or_return
/** \\S4 = a2^2; */
/** a2 = a2^2; */
- internal_sqr(a2, a2) or_return;
+ internal_sqr(a2, a2) or_return
/** \\ tmp = (S1 + S2)/2 */
/** \\tmp = S1 + S2; */
/** b = a0 + b; */
- internal_add(dest, a0, dest) or_return;
+ internal_add(dest, a0, dest) or_return
/** \\tmp = tmp >> 1; */
/** b = b >> 1; */
- internal_shr(dest, dest, 1) or_return;
+ internal_shr(dest, dest, 1) or_return
/** \\ S1 = S1 - tmp - S3 */
/** \\S1 = S1 - tmp; */
/** a0 = a0 - b; */
- internal_sub(a0, a0, dest) or_return;
+ internal_sub(a0, a0, dest) or_return
/** \\S1 = S1 - S3; */
/** a0 = a0 - a1; */
- internal_sub(a0, a0, a1) or_return;
+ internal_sub(a0, a0, a1) or_return
/** \\S2 = tmp - S4 -S0 */
/** \\S2 = tmp - S4; */
/** b = b - a2; */
- internal_sub(dest, dest, a2) or_return;
+ internal_sub(dest, dest, a2) or_return
/** \\S2 = S2 - S0; */
/** b = b - S0; */
- internal_sub(dest, dest, S0) or_return;
+ 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;
-
- internal_add(a2, a2, a1) or_return;
- internal_add(dest, dest, a2) or_return;
- internal_add(dest, dest, a0) or_return;
- internal_add(dest, dest, S0) or_return;
+ 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
+
+ internal_add(a2, a2, a1) or_return
+ internal_add(dest, dest, a2) or_return
+ internal_add(dest, dest, a0) or_return
+ internal_add(dest, dest, S0) or_return
/** a^2 - P */
- return #force_inline internal_clamp(dest);
+ return #force_inline internal_clamp(dest)
}
/*
Divide by three (based on routine from MPI and the GMP manual).
*/
_private_int_div_3 :: proc(quotient, numerator: ^Int, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
b = 2^_DIGIT_BITS / 3
*/
- b := _WORD(1) << _WORD(_DIGIT_BITS) / _WORD(3);
+ b := _WORD(1) << _WORD(_DIGIT_BITS) / _WORD(3)
- q := &Int{};
- internal_grow(q, numerator.used) or_return;
- q.used = numerator.used;
- q.sign = numerator.sign;
+ q := &Int{}
+ internal_grow(q, numerator.used) or_return
+ q.used = numerator.used
+ q.sign = numerator.sign
- w, t: _WORD;
+ w, t: _WORD
#no_bounds_check for ix := numerator.used; ix >= 0; ix -= 1 {
- w = (w << _WORD(_DIGIT_BITS)) | _WORD(numerator.digit[ix]);
+ w = (w << _WORD(_DIGIT_BITS)) | _WORD(numerator.digit[ix])
if w >= 3 {
/*
Multiply w by [1/3].
*/
- t = (w * b) >> _WORD(_DIGIT_BITS);
+ t = (w * b) >> _WORD(_DIGIT_BITS)
/*
Now subtract 3 * [w/3] from w, to get the remainder.
*/
- w -= t+t+t;
+ w -= t+t+t
/*
Fixup the remainder as required since the optimization is not exact.
*/
for w >= 3 {
- t += 1;
- w -= 3;
+ t += 1
+ w -= 3
}
} else {
- t = 0;
+ t = 0
}
- q.digit[ix] = DIGIT(t);
+ q.digit[ix] = DIGIT(t)
}
- remainder = DIGIT(w);
+ remainder = DIGIT(w)
/*
[optional] store the quotient.
*/
if quotient != nil {
- err = clamp(q);
- internal_swap(q, quotient);
+ err = clamp(q)
+ internal_swap(q, quotient)
}
- internal_destroy(q);
- return remainder, nil;
+ internal_destroy(q)
+ return remainder, nil
}
/*
@@ -1025,64 +1025,64 @@ _private_int_div_3 :: proc(quotient, numerator: ^Int, allocator := context.alloc The overall algorithm is as described as 14.20 from HAC but fixed to treat these cases.
*/
_private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- error_if_immutable(quotient, remainder) or_return;
+ error_if_immutable(quotient, remainder) or_return
- q, x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(q, x, y, t1, t2);
+ q, x, y, t1, t2 := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(q, x, y, t1, t2)
- internal_grow(q, numerator.used + 2) or_return;
- q.used = numerator.used + 2;
+ internal_grow(q, numerator.used + 2) or_return
+ q.used = numerator.used + 2
- internal_init_multi(t1, t2) or_return;
- internal_copy(x, numerator) or_return;
- internal_copy(y, denominator) or_return;
+ internal_init_multi(t1, t2) or_return
+ internal_copy(x, numerator) or_return
+ internal_copy(y, denominator) or_return
/*
Fix the sign.
*/
- neg := numerator.sign != denominator.sign;
- x.sign = .Zero_or_Positive;
- y.sign = .Zero_or_Positive;
+ neg := numerator.sign != denominator.sign
+ x.sign = .Zero_or_Positive
+ y.sign = .Zero_or_Positive
/*
Normalize both x and y, ensure that y >= b/2, [b == 2**MP_DIGIT_BIT]
*/
- norm := internal_count_bits(y) % _DIGIT_BITS;
+ norm := internal_count_bits(y) % _DIGIT_BITS
if norm < _DIGIT_BITS - 1 {
- norm = (_DIGIT_BITS - 1) - norm;
- internal_shl(x, x, norm) or_return;
- internal_shl(y, y, norm) or_return;
+ norm = (_DIGIT_BITS - 1) - norm
+ internal_shl(x, x, norm) or_return
+ internal_shl(y, y, norm) or_return
} else {
- norm = 0;
+ norm = 0
}
/*
Note: HAC does 0 based, so if used==5 then it's 0,1,2,3,4, i.e. use 4
*/
- n := x.used - 1;
- t := y.used - 1;
+ n := x.used - 1
+ t := y.used - 1
/*
while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} }
y = y*b**{n-t}
*/
- internal_shl_digit(y, n - t) or_return;
+ internal_shl_digit(y, n - t) or_return
- c := internal_cmp(x, y);
+ c := internal_cmp(x, y)
for c != -1 {
- q.digit[n - t] += 1;
- internal_sub(x, x, y) or_return;
- c = internal_cmp(x, y);
+ q.digit[n - t] += 1
+ internal_sub(x, x, y) or_return
+ c = internal_cmp(x, y)
}
/*
Reset y by shifting it back down.
*/
- internal_shr_digit(y, n - t);
+ internal_shr_digit(y, n - t)
/*
Step 3. for i from n down to (t + 1).
@@ -1094,16 +1094,16 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt
*/
if x.digit[i] == y.digit[t] {
- q.digit[(i - t) - 1] = 1 << (_DIGIT_BITS - 1);
+ q.digit[(i - t) - 1] = 1 << (_DIGIT_BITS - 1)
} else {
- tmp := _WORD(x.digit[i]) << _DIGIT_BITS;
- tmp |= _WORD(x.digit[i - 1]);
- tmp /= _WORD(y.digit[t]);
+ tmp := _WORD(x.digit[i]) << _DIGIT_BITS
+ tmp |= _WORD(x.digit[i - 1])
+ tmp /= _WORD(y.digit[t])
if tmp > _WORD(_MASK) {
- tmp = _WORD(_MASK);
+ tmp = _WORD(_MASK)
}
- q.digit[(i - t) - 1] = DIGIT(tmp & _WORD(_MASK));
+ q.digit[(i - t) - 1] = DIGIT(tmp & _WORD(_MASK))
}
/* while (q{i-t-1} * (yt * b + y{t-1})) >
@@ -1112,53 +1112,53 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In do q{i-t-1} -= 1;
*/
- iter := 0;
+ iter := 0
- q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] + 1) & _MASK;
+ q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] + 1) & _MASK
#no_bounds_check for {
- q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK;
+ q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK
/*
Find left hand.
*/
- internal_zero(t1);
- t1.digit[0] = ((t - 1) < 0) ? 0 : y.digit[t - 1];
- t1.digit[1] = y.digit[t];
- t1.used = 2;
- internal_mul(t1, t1, q.digit[(i - t) - 1]) or_return;
+ internal_zero(t1)
+ t1.digit[0] = ((t - 1) < 0) ? 0 : y.digit[t - 1]
+ t1.digit[1] = y.digit[t]
+ t1.used = 2
+ internal_mul(t1, t1, q.digit[(i - t) - 1]) or_return
/*
Find right hand.
*/
- t2.digit[0] = ((i - 2) < 0) ? 0 : x.digit[i - 2];
- t2.digit[1] = x.digit[i - 1]; /* i >= 1 always holds */
- t2.digit[2] = x.digit[i];
- t2.used = 3;
+ t2.digit[0] = ((i - 2) < 0) ? 0 : x.digit[i - 2]
+ t2.digit[1] = x.digit[i - 1] /* i >= 1 always holds */
+ t2.digit[2] = x.digit[i]
+ t2.used = 3
if t1_t2 := internal_cmp_mag(t1, t2); t1_t2 != 1 {
- break;
+ break
}
iter += 1; if iter > 100 {
- return .Max_Iterations_Reached;
+ return .Max_Iterations_Reached
}
}
/*
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;
- internal_sub(x, x, t1) or_return;
+ int_mul_digit(t1, y, q.digit[(i - t) - 1]) or_return
+ internal_shl_digit(t1, (i - t) - 1) or_return
+ internal_sub(x, x, t1) or_return
/*
if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; }
*/
if x.sign == .Negative {
- internal_copy(t1, y) or_return;
- internal_shl_digit(t1, (i - t) - 1) or_return;
- internal_add(x, x, t1) or_return;
+ internal_copy(t1, y) or_return
+ internal_shl_digit(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;
+ q.digit[(i - t) - 1] = (q.digit[(i - t) - 1] - 1) & _MASK
}
}
@@ -1166,21 +1166,21 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In Now q is the quotient and x is the remainder, [which we have to normalize]
Get sign before writing to c.
*/
- z, _ := is_zero(x);
- x.sign = .Zero_or_Positive if z else numerator.sign;
+ z, _ := is_zero(x)
+ x.sign = .Zero_or_Positive if z else numerator.sign
if quotient != nil {
- internal_clamp(q);
- internal_swap(q, quotient);
- quotient.sign = .Negative if neg else .Zero_or_Positive;
+ internal_clamp(q)
+ internal_swap(q, quotient)
+ quotient.sign = .Negative if neg else .Zero_or_Positive
}
if remainder != nil {
- internal_shr(x, x, norm) or_return;
- internal_swap(x, remainder);
+ internal_shr(x, x, norm) or_return
+ internal_swap(x, remainder)
}
- return nil;
+ return nil
}
/*
@@ -1193,49 +1193,49 @@ _private_int_div_school :: proc(quotient, remainder, numerator, denominator: ^In pages 19ff. in the above online document.
*/
_private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- A1, A2, B1, B0, Q1, Q0, R1, R0, t := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(A1, A2, B1, B0, Q1, Q0, R1, R0, t);
+ A1, A2, B1, B0, Q1, Q0, R1, R0, t := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(A1, A2, B1, B0, Q1, Q0, R1, R0, t)
- m := a.used - b.used;
- k := m / 2;
+ m := a.used - b.used
+ k := m / 2
if m < MUL_KARATSUBA_CUTOFF {
- return _private_int_div_school(quotient, remainder, a, b);
+ return _private_int_div_school(quotient, remainder, a, b)
}
- internal_init_multi(A1, A2, B1, B0, Q1, Q0, R1, R0, t) or_return;
+ internal_init_multi(A1, A2, B1, B0, Q1, Q0, R1, R0, t) or_return
/*
`B1` = `b` / `beta`^`k`, `B0` = `b` % `beta`^`k`
*/
- internal_shrmod(B1, B0, b, k * _DIGIT_BITS) or_return;
+ internal_shrmod(B1, B0, b, k * _DIGIT_BITS) or_return
/*
(Q1, R1) = RecursiveDivRem(A / beta^(2k), B1)
*/
- internal_shrmod(A1, t, a, 2 * k * _DIGIT_BITS) or_return;
- _private_div_recursion(Q1, R1, A1, B1) or_return;
+ internal_shrmod(A1, t, a, 2 * k * _DIGIT_BITS) or_return
+ _private_div_recursion(Q1, R1, A1, B1) or_return
/*
A1 = (R1 * beta^(2k)) + (A % beta^(2k)) - (Q1 * B0 * beta^k)
*/
- internal_shl_digit(R1, 2 * k) or_return;
- internal_add(A1, R1, t) or_return;
- internal_mul(t, Q1, B0) or_return;
+ internal_shl_digit(R1, 2 * k) or_return
+ internal_add(A1, R1, t) or_return
+ internal_mul(t, Q1, B0) or_return
/*
While A1 < 0 do Q1 = Q1 - 1, A1 = A1 + (beta^k * B)
*/
if internal_cmp(A1, 0) == -1 {
- internal_shl(t, b, k * _DIGIT_BITS) or_return;
+ internal_shl(t, b, k * _DIGIT_BITS) or_return
for {
- internal_decr(Q1) or_return;
- internal_add(A1, A1, t) or_return;
+ internal_decr(Q1) or_return
+ internal_add(A1, A1, t) or_return
if internal_cmp(A1, 0) != -1 {
- break;
+ break
}
}
}
@@ -1243,72 +1243,72 @@ _private_div_recursion :: proc(quotient, remainder, a, b: ^Int, allocator := con /*
(Q0, R0) = RecursiveDivRem(A1 / beta^(k), B1)
*/
- internal_shrmod(A1, t, A1, k * _DIGIT_BITS) or_return;
- _private_div_recursion(Q0, R0, A1, B1) or_return;
+ internal_shrmod(A1, t, A1, k * _DIGIT_BITS) or_return
+ _private_div_recursion(Q0, R0, A1, B1) or_return
/*
A2 = (R0*beta^k) + (A1 % beta^k) - (Q0*B0)
*/
- internal_shl_digit(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;
+ internal_shl_digit(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
/*
While A2 < 0 do Q0 = Q0 - 1, A2 = A2 + B.
*/
for internal_cmp(A2, 0) == -1 {
- internal_decr(Q0) or_return;
- internal_add(A2, A2, b) or_return;
+ internal_decr(Q0) or_return
+ internal_add(A2, A2, b) or_return
}
/*
Return q = (Q1*beta^k) + Q0, r = A2.
*/
- internal_shl_digit(Q1, k) or_return;
- internal_add(quotient, Q1, Q0) or_return;
+ internal_shl_digit(Q1, k) or_return
+ internal_add(quotient, Q1, Q0) or_return
- return internal_copy(remainder, A2);
+ return internal_copy(remainder, A2)
}
_private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- A, B, Q, Q1, R, A_div, A_mod := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(A, B, Q, Q1, R, A_div, A_mod);
+ A, B, Q, Q1, R, A_div, A_mod := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(A, B, Q, Q1, R, A_div, A_mod)
- internal_init_multi(A, B, Q, Q1, R, A_div, A_mod) or_return;
+ internal_init_multi(A, B, Q, Q1, R, A_div, A_mod) or_return
/*
Most significant bit of a limb.
Assumes _DIGIT_MAX < (sizeof(DIGIT) * sizeof(u8)).
*/
- msb := (_DIGIT_MAX + DIGIT(1)) >> 1;
- sigma := 0;
- msb_b := b.digit[b.used - 1];
+ msb := (_DIGIT_MAX + DIGIT(1)) >> 1
+ sigma := 0
+ msb_b := b.digit[b.used - 1]
for msb_b < msb {
- sigma += 1;
- msb_b <<= 1;
+ sigma += 1
+ msb_b <<= 1
}
/*
Use that sigma to normalize B.
*/
- internal_shl(B, b, sigma) or_return;
- internal_shl(A, a, sigma) or_return;
+ internal_shl(B, b, sigma) or_return
+ internal_shl(A, a, sigma) or_return
/*
Fix the sign.
*/
- neg := a.sign != b.sign;
- A.sign = .Zero_or_Positive; B.sign = .Zero_or_Positive;
+ neg := a.sign != b.sign
+ A.sign = .Zero_or_Positive; B.sign = .Zero_or_Positive
/*
If the magnitude of "A" is not more more than twice that of "B" we can work
on them directly, otherwise we need to work at "A" in chunks.
*/
- n := B.used;
- m := A.used - B.used;
+ n := B.used
+ m := A.used - B.used
/*
Q = 0. We already ensured that when we called `internal_init_multi`.
@@ -1317,56 +1317,56 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := /*
(q, r) = RecursiveDivRem(A / (beta^(m-n)), B)
*/
- j := (m - n) * _DIGIT_BITS;
- internal_shrmod(A_div, A_mod, A, j) or_return;
- _private_div_recursion(Q1, R, A_div, B) or_return;
+ j := (m - n) * _DIGIT_BITS
+ internal_shrmod(A_div, A_mod, A, j) or_return
+ _private_div_recursion(Q1, R, A_div, B) or_return
/*
Q = (Q*beta!(n)) + q
*/
- internal_shl(Q, Q, n * _DIGIT_BITS) or_return;
- internal_add(Q, Q, Q1) or_return;
+ internal_shl(Q, Q, n * _DIGIT_BITS) or_return
+ internal_add(Q, Q, Q1) or_return
/*
A = (r * beta^(m-n)) + (A % beta^(m-n))
*/
- internal_shl(R, R, (m - n) * _DIGIT_BITS) or_return;
- internal_add(A, R, A_mod) or_return;
+ internal_shl(R, R, (m - n) * _DIGIT_BITS) or_return
+ internal_add(A, R, A_mod) or_return
/*
m = m - n
*/
- m -= n;
+ m -= n
}
/*
(q, r) = RecursiveDivRem(A, B)
*/
- _private_div_recursion(Q1, R, A, B) or_return;
+ _private_div_recursion(Q1, R, A, B) or_return
/*
Q = (Q * beta^m) + q, R = r
*/
- internal_shl(Q, Q, m * _DIGIT_BITS) or_return;
- internal_add(Q, Q, Q1) or_return;
+ internal_shl(Q, Q, m * _DIGIT_BITS) or_return
+ internal_add(Q, Q, Q1) or_return
/*
Get sign before writing to dest.
*/
- R.sign = .Zero_or_Positive if internal_is_zero(Q) else a.sign;
+ R.sign = .Zero_or_Positive if internal_is_zero(Q) else a.sign
if quotient != nil {
- swap(quotient, Q);
- quotient.sign = .Negative if neg else .Zero_or_Positive;
+ swap(quotient, Q)
+ quotient.sign = .Negative if neg else .Zero_or_Positive
}
if remainder != nil {
/*
De-normalize the remainder.
*/
- internal_shrmod(R, nil, R, sigma) or_return;
- swap(remainder, R);
+ internal_shrmod(R, nil, R, sigma) or_return
+ swap(remainder, R)
}
- return nil;
+ return nil
}
/*
@@ -1375,53 +1375,53 @@ _private_int_div_recursive :: proc(quotient, remainder, a, b: ^Int, allocator := @(deprecated="Use `_int_div_school`, it's 3.5x faster.")
_private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int) -> (err: Error) {
- ta, tb, tq, q := &Int{}, &Int{}, &Int{}, &Int{};
- c: int;
- defer internal_destroy(ta, tb, tq, q);
+ ta, tb, tq, q := &Int{}, &Int{}, &Int{}, &Int{}
+ c: int
+ defer internal_destroy(ta, tb, tq, q)
for {
- internal_one(tq) or_return;
+ internal_one(tq) or_return
- num_bits, _ := count_bits(numerator);
- den_bits, _ := count_bits(denominator);
- n := num_bits - den_bits;
+ num_bits, _ := count_bits(numerator)
+ den_bits, _ := count_bits(denominator)
+ n := num_bits - den_bits
- abs(ta, numerator) or_return;
- abs(tb, denominator) or_return;
- shl(tb, tb, n) or_return;
- shl(tq, tq, n) or_return;
+ abs(ta, numerator) or_return
+ abs(tb, denominator) or_return
+ shl(tb, tb, n) or_return
+ shl(tq, tq, n) or_return
for n >= 0 {
if c, _ = cmp_mag(ta, tb); c == 0 || c == 1 {
// ta -= tb
- sub(ta, ta, tb) or_return;
+ sub(ta, ta, tb) or_return
// q += tq
- add( q, q, tq) or_return;
+ add( q, q, tq) or_return
}
- shr1(tb, tb) or_return;
- shr1(tq, tq) or_return;
+ shr1(tb, tb) or_return
+ shr1(tq, tq) or_return
- n -= 1;
+ n -= 1
}
/*
Now q == quotient and ta == remainder.
*/
- neg := numerator.sign != denominator.sign;
+ neg := numerator.sign != denominator.sign
if quotient != nil {
- swap(quotient, q);
- z, _ := is_zero(quotient);
- quotient.sign = .Negative if neg && !z else .Zero_or_Positive;
+ swap(quotient, q)
+ z, _ := is_zero(quotient)
+ quotient.sign = .Negative if neg && !z else .Zero_or_Positive
}
if remainder != nil {
- swap(remainder, ta);
- z, _ := is_zero(numerator);
- remainder.sign = .Zero_or_Positive if z else numerator.sign;
+ swap(remainder, ta)
+ z, _ := is_zero(numerator)
+ remainder.sign = .Zero_or_Positive if z else numerator.sign
}
- break;
+ break
}
- return err;
+ return err
}
@@ -1430,65 +1430,65 @@ _private_int_div_small :: proc(quotient, remainder, numerator, denominator: ^Int Binary split factorial algo due to: http://www.luschny.de/math/factorial/binarysplitfact.html
*/
_private_int_factorial_binary_split :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- inner, outer, start, stop, temp := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(inner, outer, start, stop, temp);
+ inner, outer, start, stop, temp := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(inner, outer, start, stop, temp)
- internal_one(inner, false) or_return;
- internal_one(outer, false) or_return;
+ internal_one(inner, false) or_return
+ internal_one(outer, false) or_return
- bits_used := int(_DIGIT_TYPE_BITS - intrinsics.count_leading_zeros(n));
+ bits_used := int(_DIGIT_TYPE_BITS - intrinsics.count_leading_zeros(n))
for i := bits_used; i >= 0; i -= 1 {
- start := (n >> (uint(i) + 1)) + 1 | 1;
- stop := (n >> uint(i)) + 1 | 1;
- _private_int_recursive_product(temp, start, stop, 0) or_return;
- internal_mul(inner, inner, temp) or_return;
- internal_mul(outer, outer, inner) or_return;
+ start := (n >> (uint(i) + 1)) + 1 | 1
+ stop := (n >> uint(i)) + 1 | 1
+ _private_int_recursive_product(temp, start, stop, 0) or_return
+ internal_mul(inner, inner, temp) or_return
+ internal_mul(outer, outer, inner) or_return
}
- shift := n - intrinsics.count_ones(n);
+ shift := n - intrinsics.count_ones(n)
- return internal_shl(res, outer, int(shift));
+ return internal_shl(res, outer, int(shift))
}
/*
Recursive product used by binary split factorial algorithm.
*/
_private_int_recursive_product :: proc(res: ^Int, start, stop: int, level := int(0), allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
- t1, t2 := &Int{}, &Int{};
- defer internal_destroy(t1, t2);
+ t1, t2 := &Int{}, &Int{}
+ defer internal_destroy(t1, t2)
if level > FACTORIAL_BINARY_SPLIT_MAX_RECURSIONS {
- return .Max_Iterations_Reached;
+ return .Max_Iterations_Reached
}
- num_factors := (stop - start) >> 1;
+ num_factors := (stop - start) >> 1
if num_factors == 2 {
- internal_set(t1, start, false) or_return;
+ internal_set(t1, start, false) or_return
when true {
- internal_grow(t2, t1.used + 1, false) or_return;
- internal_add(t2, t1, 2) or_return;
+ internal_grow(t2, t1.used + 1, false) or_return
+ internal_add(t2, t1, 2) or_return
} else {
- internal_add(t2, t1, 2) or_return;
+ internal_add(t2, t1, 2) or_return
}
- return internal_mul(res, t1, t2);
+ return internal_mul(res, t1, t2)
}
if num_factors > 1 {
- mid := (start + num_factors) | 1;
- _private_int_recursive_product(t1, start, mid, level + 1) or_return;
- _private_int_recursive_product(t2, mid, stop, level + 1) or_return;
- return internal_mul(res, t1, t2);
+ mid := (start + num_factors) | 1
+ _private_int_recursive_product(t1, start, mid, level + 1) or_return
+ _private_int_recursive_product(t2, mid, stop, level + 1) or_return
+ return internal_mul(res, t1, t2)
}
if num_factors == 1 {
- return #force_inline internal_set(res, start, true);
+ return #force_inline internal_set(res, start, true)
}
- return #force_inline internal_one(res, true);
+ return #force_inline internal_one(res, true)
}
/*
@@ -1507,10 +1507,10 @@ _private_int_recursive_product :: proc(res: ^Int, start, stop: int, level := int If neither result is wanted, we have nothing to do.
*/
_private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
if res_gcd == nil && res_lcm == nil {
- return nil;
+ return nil
}
/*
@@ -1521,76 +1521,76 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. GCD(0, 0) and LCM(0, 0) are both 0.
*/
if res_gcd != nil {
- internal_zero(res_gcd) or_return;
+ internal_zero(res_gcd) or_return
}
if res_lcm != nil {
- internal_zero(res_lcm) or_return;
+ internal_zero(res_lcm) or_return
}
- return nil;
+ return nil
} else if a.used == 0 {
/*
We can early out with GCD = B and LCM = 0
*/
if res_gcd != nil {
- internal_abs(res_gcd, b) or_return;
+ internal_abs(res_gcd, b) or_return
}
if res_lcm != nil {
- internal_zero(res_lcm) or_return;
+ internal_zero(res_lcm) or_return
}
- return nil;
+ return nil
} else if b.used == 0 {
/*
We can early out with GCD = A and LCM = 0
*/
if res_gcd != nil {
- internal_abs(res_gcd, a) or_return;
+ internal_abs(res_gcd, a) or_return
}
if res_lcm != nil {
- internal_zero(res_lcm) or_return;
+ internal_zero(res_lcm) or_return
}
- return nil;
+ return nil
}
- temp_gcd_res := &Int{};
- defer internal_destroy(temp_gcd_res);
+ temp_gcd_res := &Int{}
+ defer internal_destroy(temp_gcd_res)
/*
If neither `a` or `b` was zero, we need to compute `gcd`.
Get copies of `a` and `b` we can modify.
*/
- u, v := &Int{}, &Int{};
- defer internal_destroy(u, v);
- internal_copy(u, a) or_return;
- internal_copy(v, b) or_return;
+ u, v := &Int{}, &Int{}
+ defer internal_destroy(u, v)
+ internal_copy(u, a) or_return
+ internal_copy(v, b) or_return
/*
Must be positive for the remainder of the algorithm.
*/
- u.sign = .Zero_or_Positive; v.sign = .Zero_or_Positive;
+ u.sign = .Zero_or_Positive; v.sign = .Zero_or_Positive
/*
B1. Find the common power of two for `u` and `v`.
*/
- u_lsb, _ := internal_count_lsb(u);
- v_lsb, _ := internal_count_lsb(v);
- k := min(u_lsb, v_lsb);
+ u_lsb, _ := internal_count_lsb(u)
+ v_lsb, _ := internal_count_lsb(v)
+ k := min(u_lsb, v_lsb)
if k > 0 {
/*
Divide the power of two out.
*/
- internal_shr(u, u, k) or_return;
- internal_shr(v, v, k) or_return;
+ internal_shr(u, u, k) or_return
+ internal_shr(v, v, k) or_return
}
/*
Divide any remaining factors of two out.
*/
if u_lsb != k {
- internal_shr(u, u, u_lsb - k) or_return;
+ internal_shr(u, u, u_lsb - k) or_return
}
if v_lsb != k {
- internal_shr(v, v, v_lsb - k) or_return;
+ internal_shr(v, v, v_lsb - k) or_return
}
for v.used != 0 {
@@ -1601,34 +1601,34 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. /*
Swap `u` and `v` to make sure `v` is >= `u`.
*/
- internal_swap(u, v);
+ internal_swap(u, v)
}
/*
Subtract smallest from largest.
*/
- internal_sub(v, v, u) or_return;
+ internal_sub(v, v, u) or_return
/*
Divide out all factors of two.
*/
- b, _ := internal_count_lsb(v);
- internal_shr(v, v, b) or_return;
+ b, _ := internal_count_lsb(v)
+ internal_shr(v, v, b) or_return
}
/*
Multiply by 2**k which we divided out at the beginning.
*/
- internal_shl(temp_gcd_res, u, k) or_return;
- temp_gcd_res.sign = .Zero_or_Positive;
+ internal_shl(temp_gcd_res, u, k) or_return
+ temp_gcd_res.sign = .Zero_or_Positive
/*
We've computed `gcd`, either the long way, or because one of the inputs was zero.
If we don't want `lcm`, we're done.
*/
if res_lcm == nil {
- internal_swap(temp_gcd_res, res_gcd);
- return nil;
+ internal_swap(temp_gcd_res, res_gcd)
+ return nil
}
/*
@@ -1639,25 +1639,25 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. /*
Store quotient in `t2` such that `t2 * b` is the LCM.
*/
- internal_div(res_lcm, a, temp_gcd_res) or_return;
- err = internal_mul(res_lcm, res_lcm, b);
+ internal_div(res_lcm, a, temp_gcd_res) or_return
+ err = internal_mul(res_lcm, res_lcm, b)
} else {
/*
Store quotient in `t2` such that `t2 * a` is the LCM.
*/
- internal_div(res_lcm, a, temp_gcd_res) or_return;
- err = internal_mul(res_lcm, res_lcm, b);
+ internal_div(res_lcm, a, temp_gcd_res) or_return
+ err = internal_mul(res_lcm, res_lcm, b)
}
if res_gcd != nil {
- internal_swap(temp_gcd_res, res_gcd);
+ internal_swap(temp_gcd_res, res_gcd)
}
/*
Fix the sign to positive and return.
*/
- res_lcm.sign = .Zero_or_Positive;
- return err;
+ res_lcm.sign = .Zero_or_Positive
+ return err
}
/*
@@ -1665,24 +1665,24 @@ _private_int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context. Assumes `a` not to be `nil` and to have been initialized.
*/
_private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -> (res: int, err: Error) {
- bracket_low, bracket_high, bracket_mid, t, bi_base := &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(bracket_low, bracket_high, bracket_mid, t, bi_base);
+ bracket_low, bracket_high, bracket_mid, t, bi_base := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(bracket_low, bracket_high, bracket_mid, t, bi_base)
- ic := #force_inline internal_cmp(a, base);
+ ic := #force_inline internal_cmp(a, base)
if ic == -1 || ic == 0 {
- return 1 if ic == 0 else 0, nil;
+ return 1 if ic == 0 else 0, nil
}
defer if err != nil {
- res = -1;
+ res = -1
}
- internal_set(bi_base, base, true, allocator) or_return;
- internal_clear(bracket_mid, false, allocator) or_return;
- internal_clear(t, false, allocator) or_return;
- internal_one(bracket_low, false, allocator) or_return;
- internal_set(bracket_high, base, false, allocator) or_return;
+ internal_set(bi_base, base, true, allocator) or_return
+ internal_clear(bracket_mid, false, allocator) or_return
+ internal_clear(t, false, allocator) or_return
+ internal_one(bracket_low, false, allocator) or_return
+ internal_set(bracket_high, base, false, allocator) or_return
- low := 0; high := 1;
+ low := 0; high := 1
/*
A kind of Giant-step/baby-step algorithm.
@@ -1696,39 +1696,39 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) - Iterate until `a` is bracketed between low + high.
*/
if #force_inline internal_cmp(bracket_high, a) != -1 {
- break;
+ break
}
- low = high;
+ low = high
#force_inline internal_copy(bracket_low, bracket_high) or_return;
- high <<= 1;
+ high <<= 1
#force_inline internal_sqr(bracket_high, bracket_high) or_return;
}
for (high - low) > 1 {
- mid := (high + low) >> 1;
+ mid := (high + low) >> 1
#force_inline internal_pow(t, bi_base, mid - low) or_return;
#force_inline internal_mul(bracket_mid, bracket_low, t) or_return;
- mc := #force_inline internal_cmp(a, bracket_mid);
+ mc := #force_inline internal_cmp(a, bracket_mid)
switch mc {
case -1:
- high = mid;
- internal_swap(bracket_mid, bracket_high);
+ high = mid
+ internal_swap(bracket_mid, bracket_high)
case 0:
- return mid, nil;
+ return mid, nil
case 1:
- low = mid;
- internal_swap(bracket_mid, bracket_low);
+ low = mid
+ internal_swap(bracket_mid, bracket_low)
}
}
- fc := #force_inline internal_cmp(bracket_high, a);
- res = high if fc == 0 else low;
+ fc := #force_inline internal_cmp(bracket_high, a)
+ res = high if fc == 0 else low
- return;
+ return
}
@@ -1741,37 +1741,37 @@ _private_int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) - Based on Algorithm 14.32 on pp.601 of HAC.
*/
_private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- W: [_WARRAY]_WORD = ---;
+ context.allocator = allocator
+ W: [_WARRAY]_WORD = ---
if x.used > _WARRAY { return .Invalid_Argument; }
/*
Get old used count.
*/
- old_used := x.used;
+ old_used := x.used
/*
Grow `x` as required.
*/
- internal_grow(x, n.used + 1) or_return;
+ internal_grow(x, n.used + 1) or_return
/*
First we have to get the digits of the input into an array of double precision words W[...]
Copy the digits of `x` into W[0..`x.used` - 1]
*/
- ix: int;
+ ix: int
for ix = 0; ix < x.used; ix += 1 {
- W[ix] = _WORD(x.digit[ix]);
+ W[ix] = _WORD(x.digit[ix])
}
/*
Zero the high words of W[a->used..m->used*2].
*/
- zero_upper := (n.used * 2) + 1;
+ zero_upper := (n.used * 2) + 1
if ix < zero_upper {
for ix = x.used; ix < zero_upper; ix += 1 {
- W[ix] = {};
+ W[ix] = {}
}
}
@@ -1786,7 +1786,7 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co by casting the value down to a DIGIT. Note this requires
that W[ix-1] have the carry cleared (see after the inner loop)
*/
- mu := ((W[ix] & _WORD(_MASK)) * _WORD(rho)) & _WORD(_MASK);
+ mu := ((W[ix] & _WORD(_MASK)) * _WORD(rho)) & _WORD(_MASK)
/*
`a = a + mu * m * b**i`
@@ -1805,13 +1805,13 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co first m->used words of W[] have the carries fixed.
*/
for iy := 0; iy < n.used; iy += 1 {
- W[ix + iy] += mu * _WORD(n.digit[iy]);
+ W[ix + iy] += mu * _WORD(n.digit[iy])
}
/*
Now fix carry for next digit, W[ix+1].
*/
- W[ix + 1] += (W[ix] >> _DIGIT_BITS);
+ W[ix + 1] += (W[ix] >> _DIGIT_BITS)
}
/*
@@ -1820,7 +1820,7 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co */
for ; ix < n.used * 2; ix += 1 {
- W[ix + 1] += (W[ix] >> _DIGIT_BITS);
+ W[ix + 1] += (W[ix] >> _DIGIT_BITS)
}
/* copy out, A = A/b**n
@@ -1831,69 +1831,69 @@ _private_montgomery_reduce_comba :: proc(x, n: ^Int, rho: DIGIT, allocator := co */
for ix = 0; ix < (n.used + 1); ix += 1 {
- x.digit[ix] = DIGIT(W[n.used + ix] & _WORD(_MASK));
+ x.digit[ix] = DIGIT(W[n.used + ix] & _WORD(_MASK))
}
/*
Set the max used.
*/
- x.used = n.used + 1;
+ x.used = n.used + 1
/*
Zero old_used digits, if the input a was larger than m->used+1 we'll have to clear the digits.
*/
- internal_zero_unused(x, old_used);
- internal_clamp(x);
+ internal_zero_unused(x, old_used)
+ internal_clamp(x)
/*
if A >= m then A = A - m
*/
if internal_cmp_mag(x, n) != -1 {
- return internal_sub(x, x, n);
+ return internal_sub(x, x, n)
}
- return nil;
+ return nil
}
/*
hac 14.61, pp608
*/
_private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- x, y, u, v, A, B, C, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x, y, u, v, A, B, C, D);
+ context.allocator = allocator
+ x, y, u, v, A, B, C, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x, y, u, v, A, B, C, D)
/*
`b` cannot be negative.
*/
if b.sign == .Negative || internal_is_zero(b) {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
init temps.
*/
- internal_init_multi(x, y, u, v, A, B, C, D) or_return;
+ internal_init_multi(x, y, u, v, A, B, C, D) or_return
/*
`x` = `a` % `b`, `y` = `b`
*/
- internal_mod(x, a, b) or_return;
- internal_copy(y, b) or_return;
+ internal_mod(x, a, b) or_return
+ internal_copy(y, b) or_return
/*
2. [modified] if x,y are both even then return an error!
*/
if internal_is_even(x) && internal_is_even(y) {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
3. u=x, v=y, A=1, B=0, C=0, D=1
*/
- internal_copy(u, x) or_return;
- internal_copy(v, y) or_return;
- internal_one(A) or_return;
- internal_one(D) or_return;
+ internal_copy(u, x) or_return
+ internal_copy(v, y) or_return
+ internal_one(A) or_return
+ internal_one(D) or_return
for {
/*
@@ -1903,7 +1903,7 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
4.1 `u` = `u` / 2
*/
- internal_int_shr1(u, u) or_return;
+ internal_int_shr1(u, u) or_return
/*
4.2 if `A` or `B` is odd then:
@@ -1912,14 +1912,14 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
`A` = (`A`+`y`) / 2, `B` = (`B`-`x`) / 2
*/
- internal_add(A, A, y) or_return;
- internal_add(B, B, x) or_return;
+ internal_add(A, A, y) or_return
+ internal_add(B, B, x) or_return
}
/*
`A` = `A` / 2, `B` = `B` / 2
*/
- internal_int_shr1(A, A) or_return;
- internal_int_shr1(B, B) or_return;
+ internal_int_shr1(A, A) or_return
+ internal_int_shr1(B, B) or_return
}
/*
@@ -1929,7 +1929,7 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
5.1 `v` = `v` / 2
*/
- internal_int_shr1(v, v) or_return;
+ internal_int_shr1(v, v) or_return
/*
5.2 if `C` or `D` is odd then:
@@ -1938,14 +1938,14 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
`C` = (`C`+`y`) / 2, `D` = (`D`-`x`) / 2
*/
- internal_add(C, C, y) or_return;
- internal_add(D, D, x) or_return;
+ internal_add(C, C, y) or_return
+ internal_add(D, D, x) or_return
}
/*
`C` = `C` / 2, `D` = `D` / 2
*/
- internal_int_shr1(C, C) or_return;
- internal_int_shr1(D, D) or_return;
+ internal_int_shr1(C, C) or_return
+ internal_int_shr1(D, D) or_return
}
/*
@@ -1955,21 +1955,21 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator /*
`u` = `u` - `v`, `A` = `A` - `C`, `B` = `B` - `D`
*/
- internal_sub(u, u, v) or_return;
- internal_sub(A, A, C) or_return;
- internal_sub(B, B, D) or_return;
+ internal_sub(u, u, v) or_return
+ internal_sub(A, A, C) or_return
+ internal_sub(B, B, D) or_return
} else {
/* v - v - u, C = C - A, D = D - B */
- internal_sub(v, v, u) or_return;
- internal_sub(C, C, A) or_return;
- internal_sub(D, D, B) or_return;
+ internal_sub(v, v, u) or_return
+ internal_sub(C, C, A) or_return
+ internal_sub(D, D, B) or_return
}
/*
If not zero goto step 4
*/
if internal_is_zero(u) {
- break;
+ break
}
}
@@ -1981,29 +1981,29 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator If `v` != `1` then there is no inverse.
*/
if internal_cmp(v, 1) != 0 {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
If its too low.
*/
if internal_cmp(C, 0) == -1 {
- internal_add(C, C, b) or_return;
+ internal_add(C, C, b) or_return
}
/*
Too big.
*/
if internal_cmp(C, 0) != -1 {
- internal_sub(C, C, b) or_return;
+ internal_sub(C, C, b) or_return
}
/*
`C` is now the inverse.
*/
- swap(dest, C);
+ swap(dest, C)
- return;
+ return
}
/*
@@ -2013,11 +2013,11 @@ _private_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.allocator as per HAC Note 14.64 on pp. 610.
*/
_private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
- x, y, u, v, B, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{};
- defer internal_destroy(x, y, u, v, B, D);
+ context.allocator = allocator
+ x, y, u, v, B, D := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{}
+ defer internal_destroy(x, y, u, v, B, D)
- sign: Sign;
+ sign: Sign
/*
2. [modified] `b` must be odd.
@@ -2027,17 +2027,17 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
Init all our temps.
*/
- internal_init_multi(x, y, u, v, B, D) or_return;
+ internal_init_multi(x, y, u, v, B, D) or_return
/*
`x` == modulus, `y` == value to invert.
*/
- internal_copy(x, b) or_return;
+ internal_copy(x, b) or_return
/*
We need `y` = `|a|`.
*/
- internal_mod(y, a, b) or_return;
+ internal_mod(y, a, b) or_return
/*
If one of `x`, `y` is zero return an error!
@@ -2047,10 +2047,10 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
3. `u` = `x`, `v` = `y`, `A` = 1, `B` = 0, `C` = 0, `D` = 1
*/
- internal_copy(u, x) or_return;
- internal_copy(v, y) or_return;
+ internal_copy(u, x) or_return
+ internal_copy(v, y) or_return
- internal_one(D) or_return;
+ internal_one(D) or_return
for {
/*
@@ -2060,7 +2060,7 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
4.1 `u` = `u` / 2
*/
- internal_int_shr1(u, u) or_return;
+ internal_int_shr1(u, u) or_return
/*
4.2 if `B` is odd then:
@@ -2069,13 +2069,13 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
`B` = (`B` - `x`) / 2
*/
- internal_sub(B, B, x) or_return;
+ internal_sub(B, B, x) or_return
}
/*
`B` = `B` / 2
*/
- internal_int_shr1(B, B) or_return;
+ internal_int_shr1(B, B) or_return
}
/*
@@ -2085,7 +2085,7 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
5.1 `v` = `v` / 2
*/
- internal_int_shr1(v, v) or_return;
+ internal_int_shr1(v, v) or_return
/*
5.2 if `D` is odd then:
@@ -2094,12 +2094,12 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
`D` = (`D` - `x`) / 2
*/
- internal_sub(D, D, x) or_return;
+ internal_sub(D, D, x) or_return
}
/*
`D` = `D` / 2
*/
- internal_int_shr1(D, D) or_return;
+ internal_int_shr1(D, D) or_return
}
/*
@@ -2109,14 +2109,14 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc /*
`u` = `u` - `v`, `B` = `B` - `D`
*/
- internal_sub(u, u, v) or_return;
- internal_sub(B, B, D) or_return;
+ internal_sub(u, u, v) or_return
+ internal_sub(B, B, D) or_return
} else {
/*
`v` - `v` - `u`, `D` = `D` - `B`
*/
- internal_sub(v, v, u) or_return;
- internal_sub(D, D, B) or_return;
+ internal_sub(v, v, u) or_return
+ internal_sub(D, D, B) or_return
}
/*
@@ -2133,27 +2133,27 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc if `v` != 1 then there is no inverse
*/
if internal_cmp(v, 1) != 0 {
- return .Invalid_Argument;
+ return .Invalid_Argument
}
/*
`b` is now the inverse.
*/
- sign = a.sign;
+ sign = a.sign
for internal_int_is_negative(D) {
- internal_add(D, D, b) or_return;
+ internal_add(D, D, b) or_return
}
/*
Too big.
*/
for internal_cmp_mag(D, b) != -1 {
- internal_sub(D, D, b) or_return;
+ internal_sub(D, D, b) or_return
}
- swap(dest, D);
- dest.sign = sign;
- return nil;
+ swap(dest, D)
+ dest.sign = sign
+ return nil
}
@@ -2163,14 +2163,14 @@ _private_inverse_modulo_odd :: proc(dest, a, b: ^Int, allocator := context.alloc Also assumes `base` is a power of two.
*/
_private_log_power_of_two :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
- base := base;
- y: int;
+ base := base
+ y: int
for y = 0; base & 1 == 0; {
- y += 1;
- base >>= 1;
+ y += 1
+ base >>= 1
}
- log = internal_count_bits(a);
- return (log - 1) / y, err;
+ log = internal_count_bits(a)
+ return (log - 1) / y, err
}
/*
@@ -2178,17 +2178,17 @@ _private_log_power_of_two :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error Assumes `src` and `dest` to not be `nil` and have been initialized.
*/
_private_copy_digits :: proc(dest, src: ^Int, digits: int, offset := int(0)) -> (err: Error) {
- digits := digits;
+ digits := digits
/*
If dest == src, do nothing
*/
if dest == src {
- return nil;
+ return nil
}
- digits = min(digits, len(src.digit), len(dest.digit));
- mem.copy_non_overlapping(&dest.digit[0], &src.digit[offset], size_of(DIGIT) * digits);
- return nil;
+ digits = min(digits, len(src.digit), len(dest.digit))
+ mem.copy_non_overlapping(&dest.digit[0], &src.digit[offset], size_of(DIGIT) * digits)
+ return nil
}
/*
@@ -2208,7 +2208,7 @@ _private_int_rem_128 := [?]DIGIT{ 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
-};
+}
#assert(128 * size_of(DIGIT) == size_of(_private_int_rem_128));
_private_int_rem_105 := [?]DIGIT{
@@ -2219,7 +2219,7 @@ _private_int_rem_105 := [?]DIGIT{ 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1,
-};
+}
#assert(105 * size_of(DIGIT) == size_of(_private_int_rem_105));
_private_prime_table := [?]DIGIT{
@@ -2258,7 +2258,7 @@ _private_prime_table := [?]DIGIT{ 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653,
-};
+}
#assert(256 * size_of(DIGIT) == size_of(_private_prime_table));
when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) {
@@ -2298,7 +2298,7 @@ when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* f(32): */ 263_130_836_933_693_530_167_218_012_160_000_000,
/* f(33): */ 8_683_317_618_811_886_495_518_194_401_280_000_000,
/* f(34): */ 295_232_799_039_604_140_847_618_609_643_520_000_000,
- };
+ }
} else {
_factorial_table := [21]_WORD{
/* f(00): */ 1,
@@ -2322,7 +2322,7 @@ when MATH_BIG_FORCE_64_BIT || (!MATH_BIG_FORCE_32_BIT && size_of(rawptr) == 8) { /* f(18): */ 6_402_373_705_728_000,
/* f(19): */ 121_645_100_408_832_000,
/* f(20): */ 2_432_902_008_176_640_000,
- };
+ }
};
/*
diff --git a/core/math/big/public.odin b/core/math/big/public.odin index 542725289..f3dd096b6 100644 --- a/core/math/big/public.odin +++ b/core/math/big/public.odin @@ -21,14 +21,14 @@ package math_big High-level addition. Handles sign.
*/
int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a, b);
- context.allocator = allocator;
+ assert_if_nil(dest, a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, a, b) or_return;
+ internal_clear_if_uninitialized(dest, a, b) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_add_signed(dest, a, b);
+ return #force_inline internal_int_add_signed(dest, a, b)
}
/*
@@ -38,33 +38,33 @@ int_add :: proc(dest, a, b: ^Int, allocator := context.allocator) -> (err: Error dest = a + digit;
*/
int_add_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a);
- context.allocator = allocator;
+ assert_if_nil(dest, a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
/*
Grow destination as required.
*/
- grow(dest, a.used + 1) or_return;
+ grow(dest, a.used + 1) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_add_digit(dest, a, digit);
+ return #force_inline internal_int_add_digit(dest, a, digit)
}
/*
High-level subtraction, dest = number - decrease. Handles signs.
*/
int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, number, decrease);
- context.allocator = allocator;
+ assert_if_nil(dest, number, decrease)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, number, decrease) or_return;
+ internal_clear_if_uninitialized(dest, number, decrease) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_sub_signed(dest, number, decrease);
+ return #force_inline internal_int_sub_signed(dest, number, decrease)
}
/*
@@ -74,19 +74,19 @@ int_sub :: proc(dest, number, decrease: ^Int, allocator := context.allocator) -> dest = a - digit;
*/
int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, a);
- context.allocator = allocator;
+ assert_if_nil(dest, a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
/*
Grow destination as required.
*/
- grow(dest, a.used + 1) or_return;
+ grow(dest, a.used + 1) or_return
/*
All parameters have been initialized.
*/
- return #force_inline internal_int_sub_digit(dest, a, digit);
+ return #force_inline internal_int_sub_digit(dest, a, digit)
}
/*
@@ -94,64 +94,64 @@ int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT, allocator := context.allocato dest = src >> 1
*/
int_halve :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
/*
Grow destination as required.
*/
if dest != src { grow(dest, src.used + 1) or_return }
- return #force_inline internal_int_shr1(dest, src);
+ return #force_inline internal_int_shr1(dest, src)
}
-halve :: proc { int_halve, };
-shr1 :: halve;
+halve :: proc { int_halve, }
+shr1 :: halve
/*
dest = src * 2
dest = src << 1
*/
int_double :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
/*
Grow destination as required.
*/
if dest != src { grow(dest, src.used + 1) or_return; }
- return #force_inline internal_int_shl1(dest, src);
+ return #force_inline internal_int_shl1(dest, src)
}
-double :: proc { int_double, };
-shl1 :: double;
+double :: proc { int_double, }
+shl1 :: double
/*
Multiply by a DIGIT.
*/
int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(src, dest) or_return;
+ internal_clear_if_uninitialized(src, dest) or_return
- return #force_inline internal_int_mul_digit(dest, src, multiplier);
+ return #force_inline internal_int_mul_digit(dest, src, multiplier)
}
/*
High level multiplication (handles sign).
*/
int_mul :: proc(dest, src, multiplier: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src, multiplier);
- context.allocator = allocator;
+ assert_if_nil(dest, src, multiplier)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src, multiplier) or_return;
+ internal_clear_if_uninitialized(dest, src, multiplier) or_return
- return #force_inline internal_int_mul(dest, src, multiplier);
+ return #force_inline internal_int_mul(dest, src, multiplier)
}
-mul :: proc { int_mul, int_mul_digit, };
+mul :: proc { int_mul, int_mul_digit, }
sqr :: proc(dest, src: ^Int) -> (err: Error) { return mul(dest, src, src); }
@@ -160,46 +160,46 @@ sqr :: proc(dest, src: ^Int) -> (err: Error) { return mul(dest, src, src); } Both the quotient and remainder are optional and may be passed a nil.
*/
int_divmod :: proc(quotient, remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Early out if neither of the results is wanted.
*/
if quotient == nil && remainder == nil { return nil; }
- internal_clear_if_uninitialized(numerator, denominator) or_return;
+ internal_clear_if_uninitialized(numerator, denominator) or_return
- return #force_inline internal_divmod(quotient, remainder, numerator, denominator);
+ return #force_inline internal_divmod(quotient, remainder, numerator, denominator)
}
int_divmod_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
- assert_if_nil(quotient, numerator);
- context.allocator = allocator;
+ assert_if_nil(quotient, numerator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator) or_return;
+ internal_clear_if_uninitialized(numerator) or_return
- return #force_inline internal_divmod(quotient, numerator, denominator);
+ return #force_inline internal_divmod(quotient, numerator, denominator)
}
-divmod :: proc{ int_divmod, int_divmod_digit, };
+divmod :: proc{ int_divmod, int_divmod_digit, }
int_div :: proc(quotient, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(quotient, numerator, denominator);
- context.allocator = allocator;
+ assert_if_nil(quotient, numerator, denominator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator, denominator) or_return;
+ internal_clear_if_uninitialized(numerator, denominator) or_return
- return #force_inline internal_divmod(quotient, nil, numerator, denominator);
+ return #force_inline internal_divmod(quotient, nil, numerator, denominator)
}
int_div_digit :: proc(quotient, numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(quotient, numerator);
- context.allocator = allocator;
+ assert_if_nil(quotient, numerator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator) or_return;
+ internal_clear_if_uninitialized(numerator) or_return
- _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return;
- return;
+ _ = #force_inline internal_divmod(quotient, numerator, denominator) or_return
+ return
}
-div :: proc { int_div, int_div_digit, };
+div :: proc { int_div, int_div_digit, }
/*
remainder = numerator % denominator.
@@ -207,80 +207,80 @@ div :: proc { int_div, int_div_digit, }; denominator < remainder <= 0 if denominator < 0
*/
int_mod :: proc(remainder, numerator, denominator: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, numerator, denominator);
- context.allocator = allocator;
+ assert_if_nil(remainder, numerator, denominator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(numerator, denominator) or_return;
+ internal_clear_if_uninitialized(numerator, denominator) or_return
- return #force_inline internal_int_mod(remainder, numerator, denominator);
+ return #force_inline internal_int_mod(remainder, numerator, denominator)
}
int_mod_digit :: proc(numerator: ^Int, denominator: DIGIT, allocator := context.allocator) -> (remainder: DIGIT, err: Error) {
- return #force_inline internal_divmod(nil, numerator, denominator, allocator);
+ return #force_inline internal_divmod(nil, numerator, denominator, allocator)
}
-mod :: proc { int_mod, int_mod_digit, };
+mod :: proc { int_mod, int_mod_digit, }
/*
remainder = (number + addend) % modulus.
*/
int_addmod :: proc(remainder, number, addend, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, addend);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, addend)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, addend, modulus) or_return;
+ internal_clear_if_uninitialized(number, addend, modulus) or_return
- return #force_inline internal_addmod(remainder, number, addend, modulus);
+ return #force_inline internal_addmod(remainder, number, addend, modulus)
}
-addmod :: proc { int_addmod, };
+addmod :: proc { int_addmod, }
/*
remainder = (number - decrease) % modulus.
*/
int_submod :: proc(remainder, number, decrease, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, decrease);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, decrease)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, decrease, modulus) or_return;
+ internal_clear_if_uninitialized(number, decrease, modulus) or_return
- return #force_inline internal_submod(remainder, number, decrease, modulus);
+ return #force_inline internal_submod(remainder, number, decrease, modulus)
}
-submod :: proc { int_submod, };
+submod :: proc { int_submod, }
/*
remainder = (number * multiplicand) % modulus.
*/
int_mulmod :: proc(remainder, number, multiplicand, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, multiplicand);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, multiplicand)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, multiplicand, modulus) or_return;
+ internal_clear_if_uninitialized(number, multiplicand, modulus) or_return
- return #force_inline internal_mulmod(remainder, number, multiplicand, modulus);
+ return #force_inline internal_mulmod(remainder, number, multiplicand, modulus)
}
-mulmod :: proc { int_mulmod, };
+mulmod :: proc { int_mulmod, }
/*
remainder = (number * number) % modulus.
*/
int_sqrmod :: proc(remainder, number, modulus: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, number, modulus);
- context.allocator = allocator;
+ assert_if_nil(remainder, number, modulus)
+ context.allocator = allocator
- internal_clear_if_uninitialized(number, modulus) or_return;
+ internal_clear_if_uninitialized(number, modulus) or_return
- return #force_inline internal_sqrmod(remainder, number, modulus);
+ return #force_inline internal_sqrmod(remainder, number, modulus)
}
-sqrmod :: proc { int_sqrmod, };
+sqrmod :: proc { int_sqrmod, }
int_factorial :: proc(res: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
if n < 0 || n > FACTORIAL_MAX_N { return .Invalid_Argument; }
- assert_if_nil(res);
+ assert_if_nil(res)
- return #force_inline internal_int_factorial(res, n, allocator);
+ return #force_inline internal_int_factorial(res, n, allocator)
}
-factorial :: proc { int_factorial, };
+factorial :: proc { int_factorial, }
/*
@@ -299,8 +299,8 @@ factorial :: proc { int_factorial, }; */
int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(res);
- context.allocator = allocator;
+ assert_if_nil(res)
+ context.allocator = allocator
if n < 0 || n > FACTORIAL_MAX_N { return .Invalid_Argument; }
if k > n { return internal_zero(res); }
@@ -308,8 +308,8 @@ int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) - /*
res = n! / (k! * (n - k)!)
*/
- n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{};
- defer internal_destroy(n_fac, k_fac, n_minus_k_fac);
+ n_fac, k_fac, n_minus_k_fac := &Int{}, &Int{}, &Int{}
+ defer internal_destroy(n_fac, k_fac, n_minus_k_fac)
#force_inline internal_int_factorial(n_minus_k_fac, n - k) or_return;
#force_inline internal_int_factorial(k_fac, k) or_return;
@@ -318,112 +318,112 @@ int_choose_digit :: proc(res: ^Int, n, k: int, allocator := context.allocator) - #force_inline internal_int_factorial(n_fac, n) or_return;
#force_inline internal_div(res, n_fac, k_fac) or_return;
- return;
+ return
}
-choose :: proc { int_choose_digit, };
+choose :: proc { int_choose_digit, }
/*
Function computing both GCD and (if target isn't `nil`) also LCM.
*/
int_gcd_lcm :: proc(res_gcd, res_lcm, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
if res_gcd == nil && res_lcm == nil { return nil; }
- assert_if_nil(a, b);
- context.allocator = allocator;
+ assert_if_nil(a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return;
- return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b);
+ internal_clear_if_uninitialized(a, b) or_return
+ return #force_inline internal_int_gcd_lcm(res_gcd, res_lcm, a, b)
}
-gcd_lcm :: proc { int_gcd_lcm, };
+gcd_lcm :: proc { int_gcd_lcm, }
/*
Greatest Common Divisor.
*/
int_gcd :: proc(res, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- return #force_inline int_gcd_lcm(res, nil, a, b, allocator);
+ return #force_inline int_gcd_lcm(res, nil, a, b, allocator)
}
-gcd :: proc { int_gcd, };
+gcd :: proc { int_gcd, }
/*
Least Common Multiple.
*/
int_lcm :: proc(res, a, b: ^Int, allocator := context.allocator) -> (err: Error) {
- return #force_inline int_gcd_lcm(nil, res, a, b, allocator);
+ return #force_inline int_gcd_lcm(nil, res, a, b, allocator)
}
-lcm :: proc { int_lcm, };
+lcm :: proc { int_lcm, }
/*
remainder = numerator % (1 << bits)
*/
int_mod_bits :: proc(remainder, numerator: ^Int, bits: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(remainder, numerator);
- context.allocator = allocator;
+ assert_if_nil(remainder, numerator)
+ context.allocator = allocator
- internal_clear_if_uninitialized(remainder, numerator) or_return;
+ internal_clear_if_uninitialized(remainder, numerator) or_return
if bits < 0 { return .Invalid_Argument; }
- return #force_inline internal_int_mod_bits(remainder, numerator, bits);
+ return #force_inline internal_int_mod_bits(remainder, numerator, bits)
}
-mod_bits :: proc { int_mod_bits, };
+mod_bits :: proc { int_mod_bits, }
/*
Logs and roots and such.
*/
int_log :: proc(a: ^Int, base: DIGIT, allocator := context.allocator) -> (res: int, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_int_log(a, base);
+ return #force_inline internal_int_log(a, base)
}
digit_log :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
- return #force_inline internal_digit_log(a, base);
+ return #force_inline internal_digit_log(a, base)
}
-log :: proc { int_log, digit_log, };
+log :: proc { int_log, digit_log, }
/*
Calculate `dest = base^power` using a square-multiply algorithm.
*/
int_pow :: proc(dest, base: ^Int, power: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, base);
- context.allocator = allocator;
+ assert_if_nil(dest, base)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, base) or_return;
+ internal_clear_if_uninitialized(dest, base) or_return
- return #force_inline internal_int_pow(dest, base, power);
+ return #force_inline internal_int_pow(dest, base, power)
}
/*
Calculate `dest = base^power` using a square-multiply algorithm.
*/
int_pow_int :: proc(dest: ^Int, base, power: int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest);
+ assert_if_nil(dest)
- return #force_inline internal_pow(dest, base, power, allocator);
+ return #force_inline internal_pow(dest, base, power, allocator)
}
-pow :: proc { int_pow, int_pow_int, small_pow, };
-exp :: pow;
+pow :: proc { int_pow, int_pow_int, small_pow, }
+exp :: pow
small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) {
- return #force_inline internal_small_pow(base, exponent);
+ return #force_inline internal_small_pow(base, exponent)
}
/*
This function is less generic than `root_n`, simpler and faster.
*/
int_sqrt :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
- assert_if_nil(dest, src);
- context.allocator = allocator;
+ assert_if_nil(dest, src)
+ context.allocator = allocator
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_sqrt(dest, src);
+ return #force_inline internal_int_sqrt(dest, src)
}
-sqrt :: proc { int_sqrt, };
+sqrt :: proc { int_sqrt, }
/*
@@ -434,22 +434,22 @@ sqrt :: proc { int_sqrt, }; which will find the root in `log(n)` time where each step involves a fair bit.
*/
int_root_n :: proc(dest, src: ^Int, n: int, allocator := context.allocator) -> (err: Error) {
- context.allocator = allocator;
+ context.allocator = allocator
/*
Fast path for n == 2.
*/
if n == 2 { return sqrt(dest, src); }
- assert_if_nil(dest, src);
+ assert_if_nil(dest, src)
/*
Initialize dest + src if needed.
*/
- internal_clear_if_uninitialized(dest, src) or_return;
+ internal_clear_if_uninitialized(dest, src) or_return
- return #force_inline internal_int_root_n(dest, src, n);
+ return #force_inline internal_int_root_n(dest, src, n)
}
-root_n :: proc { int_root_n, };
+root_n :: proc { int_root_n, }
/*
Comparison routines.
@@ -458,103 +458,103 @@ root_n :: proc { int_root_n, }; int_is_initialized :: proc(a: ^Int) -> bool {
if a == nil { return false; }
- return #force_inline internal_int_is_initialized(a);
+ return #force_inline internal_int_is_initialized(a)
}
int_is_zero :: proc(a: ^Int, allocator := context.allocator) -> (zero: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_zero(a), nil;
+ return #force_inline internal_is_zero(a), nil
}
int_is_positive :: proc(a: ^Int, allocator := context.allocator) -> (positive: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_positive(a), nil;
+ return #force_inline internal_is_positive(a), nil
}
int_is_negative :: proc(a: ^Int, allocator := context.allocator) -> (negative: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_negative(a), nil;
+ return #force_inline internal_is_negative(a), nil
}
int_is_even :: proc(a: ^Int, allocator := context.allocator) -> (even: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_even(a), nil;
+ return #force_inline internal_is_even(a), nil
}
int_is_odd :: proc(a: ^Int, allocator := context.allocator) -> (odd: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_odd(a), nil;
+ return #force_inline internal_is_odd(a), nil
}
platform_int_is_power_of_two :: #force_inline proc(a: int) -> bool {
- return ((a) != 0) && (((a) & ((a) - 1)) == 0);
+ return ((a) != 0) && (((a) & ((a) - 1)) == 0)
}
int_is_power_of_two :: proc(a: ^Int, allocator := context.allocator) -> (res: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_is_power_of_two(a), nil;
+ return #force_inline internal_is_power_of_two(a), nil
}
/*
Compare two `Int`s, signed.
*/
int_compare :: proc(a, b: ^Int, allocator := context.allocator) -> (comparison: int, err: Error) {
- assert_if_nil(a, b);
- context.allocator = allocator;
+ assert_if_nil(a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return;
+ internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_cmp(a, b), nil;
+ return #force_inline internal_cmp(a, b), nil
}
-int_cmp :: int_compare;
+int_cmp :: int_compare
/*
Compare an `Int` to an unsigned number upto the size of the backing type.
*/
int_compare_digit :: proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (comparison: int, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_cmp_digit(a, b), nil;
+ return #force_inline internal_cmp_digit(a, b), nil
}
-int_cmp_digit :: int_compare_digit;
+int_cmp_digit :: int_compare_digit
/*
Compare the magnitude of two `Int`s, unsigned.
*/
int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (res: int, err: Error) {
- assert_if_nil(a, b);
- context.allocator = allocator;
+ assert_if_nil(a, b)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a, b) or_return;
+ internal_clear_if_uninitialized(a, b) or_return
- return #force_inline internal_cmp_mag(a, b), nil;
+ return #force_inline internal_cmp_mag(a, b), nil
}
/*
@@ -564,10 +564,10 @@ int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (re Assumes `a` not to be `nil` and to have been initialized.
*/
int_is_square :: proc(a: ^Int, allocator := context.allocator) -> (square: bool, err: Error) {
- assert_if_nil(a);
- context.allocator = allocator;
+ assert_if_nil(a)
+ context.allocator = allocator
- internal_clear_if_uninitialized(a) or_return;
+ internal_clear_if_uninitialized(a) or_return
- return #force_inline internal_int_is_square(a);
+ return #force_inline internal_int_is_square(a)
}
\ No newline at end of file diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin index acf0bacbd..8908f7775 100644 --- a/core/math/big/radix.odin +++ b/core/math/big/radix.odin @@ -22,15 +22,15 @@ 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); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - a := a; radix := radix; - clear_if_uninitialized(a) or_return; + a := a; radix := radix + clear_if_uninitialized(a) or_return /* Radix defaults to 10. */ - radix = radix if radix > 0 else 10; + radix = radix if radix > 0 else 10 /* TODO: If we want to write a prefix for some of the radixes, we can oversize the buffer. @@ -41,39 +41,39 @@ int_itoa_string :: proc(a: ^Int, radix := i8(-1), zero_terminate := false, alloc Calculate the size of the buffer we need, and Exit if calculating the size returned an error. */ - size := radix_size(a, radix, zero_terminate) or_return; + size := radix_size(a, radix, zero_terminate) or_return /* Allocate the buffer we need. */ - buffer := make([]u8, size); + buffer := make([]u8, size) /* Write the digits out into the buffer. */ - written: int; - written, err = int_itoa_raw(a, radix, buffer, size, zero_terminate); + written: int + written, err = int_itoa_raw(a, radix, buffer, size, zero_terminate) - return string(buffer[:written]), err; + return string(buffer[:written]), err } /* 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); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - a := a; radix := radix; - clear_if_uninitialized(a) or_return; + a := a; radix := radix + clear_if_uninitialized(a) or_return /* Radix defaults to 10. */ - radix = radix if radix > 0 else 10; + radix = radix if radix > 0 else 10 - s: string; - s, err = int_itoa_string(a, radix, true); - return cstring(raw_data(s)), err; + s: string + s, err = int_itoa_string(a, radix, true) + return cstring(raw_data(s)), err } /* @@ -97,57 +97,57 @@ 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; - clear_if_uninitialized(a) or_return; + assert_if_nil(a) + a := a; radix := radix; size := size + clear_if_uninitialized(a) or_return /* Radix defaults to 10. */ - radix = radix if radix > 0 else 10; + radix = radix if radix > 0 else 10 if radix < 2 || radix > 64 { - return 0, .Invalid_Argument; + return 0, .Invalid_Argument } /* We weren't given a size. Let's compute it. */ if size == -1 { - size = radix_size(a, radix, zero_terminate) or_return; + size = radix_size(a, radix, zero_terminate) or_return } /* Early exit if the buffer we were given is too small. */ - available := len(buffer); + available := len(buffer) if available < size { - return 0, .Buffer_Overflow; + return 0, .Buffer_Overflow } /* Fast path for when `Int` == 0 or the entire `Int` fits in a single radix digit. */ - z, _ := is_zero(a); + z, _ := is_zero(a) if z || (a.used == 1 && a.digit[0] < DIGIT(radix)) { if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } - available -= 1; - buffer[available] = RADIX_TABLE[a.digit[0]]; + available -= 1 + buffer[available] = RADIX_TABLE[a.digit[0]] if n, _ := is_neg(a); n { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < size { - diff := size - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := size - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil } /* @@ -155,32 +155,32 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter */ if a.used == 1 || a.used == 2 { if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } - val := _WORD(a.digit[1]) << _DIGIT_BITS + _WORD(a.digit[0]); + val := _WORD(a.digit[1]) << _DIGIT_BITS + _WORD(a.digit[0]) for val > 0 { - q := val / _WORD(radix); - available -= 1; - buffer[available] = RADIX_TABLE[val - (q * _WORD(radix))]; + q := val / _WORD(radix) + available -= 1 + buffer[available] = RADIX_TABLE[val - (q * _WORD(radix))] - val = q; + val = q } if n, _ := is_neg(a); n { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < size { - diff := size - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := size - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil } /* @@ -188,57 +188,57 @@ int_itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_ter */ if is_power_of_two(int(radix)) { if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } - shift, count: int; + shift, count: int // mask := _WORD(radix - 1); - shift, err = log(DIGIT(radix), 2); - count, err = count_bits(a); - digit: _WORD; + shift, err = log(DIGIT(radix), 2) + count, err = count_bits(a) + digit: _WORD for offset := 0; offset < count; offset += shift { - bits_to_get := int(min(count - offset, shift)); + bits_to_get := int(min(count - offset, shift)) - digit, err = int_bitfield_extract(a, offset, bits_to_get); + digit, err = int_bitfield_extract(a, offset, bits_to_get) if err != nil { - return len(buffer) - available, .Invalid_Argument; + return len(buffer) - available, .Invalid_Argument } - available -= 1; - buffer[available] = RADIX_TABLE[digit]; + available -= 1 + buffer[available] = RADIX_TABLE[digit] } if n, _ := is_neg(a); n { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < size { - diff := size - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := size - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil } - return _itoa_raw_full(a, radix, buffer, zero_terminate); + return _itoa_raw_full(a, radix, buffer, zero_terminate) } -itoa :: proc{int_itoa_string, int_itoa_raw}; -int_to_string :: int_itoa_string; -int_to_cstring :: int_itoa_cstring; +itoa :: proc{int_itoa_string, int_itoa_raw} +int_to_string :: int_itoa_string +int_to_cstring :: int_itoa_cstring /* Read a string [ASCII] in a given radix. */ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context.allocator) -> (err: Error) { - assert_if_nil(res); - input := input; - context.allocator = allocator; + assert_if_nil(res) + input := input + context.allocator = allocator /* Make sure the radix is ok. @@ -249,92 +249,92 @@ int_atoi :: proc(res: ^Int, input: string, radix := i8(10), allocator := context /* Set the integer to the default of zero. */ - internal_zero(res) or_return; + internal_zero(res) or_return /* We'll interpret an empty string as zero. */ if len(input) == 0 { - return nil; + return nil } /* If the leading digit is a minus set the sign to negative. Given the above early out, the length should be at least 1. */ - sign := Sign.Zero_or_Positive; + sign := Sign.Zero_or_Positive if input[0] == '-' { - input = input[1:]; - sign = .Negative; + input = input[1:] + sign = .Negative } /* Process each digit of the string. */ - ch: rune; + ch: rune for len(input) > 0 { /* if the radix <= 36 the conversion is case insensitive * this allows numbers like 1AB and 1ab to represent the same value * [e.g. in hex] */ - ch = rune(input[0]); + ch = rune(input[0]) if radix <= 36 && ch >= 'a' && ch <= 'z' { - ch -= 32; // 'a' - 'A' + ch -= 32 // 'a' - 'A' } - pos := ch - '+'; + pos := ch - '+' if RADIX_TABLE_REVERSE_SIZE <= pos { - break; + break } - y := RADIX_TABLE_REVERSE[pos]; + y := RADIX_TABLE_REVERSE[pos] /* if the char was found in the map * and is less than the given radix add it * to the number, otherwise exit the loop. */ if y >= u8(radix) { - break; + break } - internal_mul(res, res, DIGIT(radix)) or_return; - internal_add(res, res, DIGIT(y)) or_return; + internal_mul(res, res, DIGIT(radix)) or_return + internal_add(res, res, DIGIT(y)) or_return - input = input[1:]; + input = input[1:] } /* If an illegal character was found, fail. */ if len(input) > 0 && ch != 0 && ch != '\r' && ch != '\n' { - return .Invalid_Argument; + return .Invalid_Argument } /* Set the sign only if res != 0. */ if res.used > 0 { - res.sign = sign; + res.sign = sign } - return nil; + return nil } -atoi :: proc { int_atoi, }; +atoi :: proc { int_atoi, } /* We size for `string` by default. */ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := context.allocator) -> (size: int, err: Error) { - a := a; - assert_if_nil(a); + a := a + assert_if_nil(a) if radix < 2 || radix > 64 { return -1, .Invalid_Argument; } - clear_if_uninitialized(a) or_return; + clear_if_uninitialized(a) or_return if internal_is_zero(a) { if zero_terminate { - return 2, nil; + return 2, nil } - return 1, nil; + return 1, nil } if internal_is_power_of_two(a) { @@ -345,37 +345,37 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con used = a.used, sign = .Zero_or_Positive, digit = a.digit, - }; + } - size = internal_log(t, DIGIT(radix)) or_return; + size = internal_log(t, DIGIT(radix)) or_return } else { - la, k := &Int{}, &Int{}; - defer internal_destroy(la, k); + la, k := &Int{}, &Int{} + defer internal_destroy(la, k) /* la = floor(log_2(a)) + 1 */ - bit_count := internal_count_bits(a); - internal_set(la, bit_count) or_return; + bit_count := internal_count_bits(a) + internal_set(la, bit_count) or_return /* k = floor(2^29/log_2(radix)) + 1 */ - lb := _log_bases; - internal_set(k, lb[radix]) or_return; + lb := _log_bases + internal_set(k, lb[radix]) or_return /* n = floor((la * k) / 2^29) + 1 */ - internal_mul(k, la, k) or_return; - internal_shr(k, k, _RADIX_SIZE_SCALE) or_return; + internal_mul(k, la, k) or_return + internal_shr(k, k, _RADIX_SIZE_SCALE) or_return /* The "+1" here is the "+1" in "floor((la * k) / 2^29) + 1" */ /* n = n + 1 + EOS + sign */ - size_, _ := internal_get(k, u128); - size = int(size_); + size_, _ := internal_get(k, u128) + size = int(size_) } /* log truncates to zero, so we need to add one more, and one for `-` if negative. */ - size += 2 if a.sign == .Negative else 1; - size += 1 if zero_terminate else 0; - return size, nil; + size += 2 if a.sign == .Negative else 1 + size += 1 if zero_terminate else 0 + return size, nil } /* @@ -392,7 +392,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false, allocator := con for 64 bit "int". */ -_RADIX_SIZE_SCALE :: 29; +_RADIX_SIZE_SCALE :: 29 _log_bases :: [65]u32{ 0, 0, 0x20000001, 0x14309399, 0x10000001, 0xdc81a35, 0xc611924, 0xb660c9e, 0xaaaaaab, 0xa1849cd, @@ -407,12 +407,12 @@ _log_bases :: [65]u32{ 0x5ab7d68, 0x5a42df0, 0x59d1506, 0x5962ffe, 0x58f7c57, 0x588f7bc, 0x582a000, 0x57c7319, 0x5766f1d, 0x5709243, 0x56adad9, 0x565474d, 0x55fd61f, 0x55a85e8, 0x5555556, -}; +} /* Characters used in radix conversions. */ -RADIX_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +RADIX_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/" RADIX_TABLE_REVERSE := [RADIX_TABLE_REVERSE_SIZE]u8{ 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x01, 0x02, 0x03, 0x04, /* +,-./01234 */ 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, /* 56789:;<=> */ @@ -422,59 +422,59 @@ RADIX_TABLE_REVERSE := [RADIX_TABLE_REVERSE_SIZE]u8{ 0xff, 0xff, 0xff, 0xff, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, /* ]^_`abcdef */ 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, /* ghijklmnop */ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, /* qrstuvwxyz */ -}; -RADIX_TABLE_REVERSE_SIZE :: 80; +} +RADIX_TABLE_REVERSE_SIZE :: 80 /* Stores a bignum as a ASCII string in a given radix (2..64) The buffer must be appropriately sized. This routine doesn't check. */ _itoa_raw_full :: proc(a: ^Int, radix: i8, buffer: []u8, zero_terminate := false, allocator := context.allocator) -> (written: int, err: Error) { - assert_if_nil(a); - context.allocator = allocator; + assert_if_nil(a) + context.allocator = allocator - temp, denominator := &Int{}, &Int{}; + temp, denominator := &Int{}, &Int{} - internal_copy(temp, a) or_return; - internal_set(denominator, radix) or_return; + internal_copy(temp, a) or_return + internal_set(denominator, radix) or_return - available := len(buffer); + available := len(buffer) if zero_terminate { - available -= 1; - buffer[available] = 0; + available -= 1 + buffer[available] = 0 } if a.sign == .Negative { - temp.sign = .Zero_or_Positive; + temp.sign = .Zero_or_Positive } - remainder: DIGIT; + remainder: DIGIT for { if remainder, err = #force_inline internal_divmod(temp, temp, DIGIT(radix)); err != nil { - internal_destroy(temp, denominator); - return len(buffer) - available, err; + internal_destroy(temp, denominator) + return len(buffer) - available, err } - available -= 1; - buffer[available] = RADIX_TABLE[remainder]; + available -= 1 + buffer[available] = RADIX_TABLE[remainder] if temp.used == 0 { - break; + break } } if a.sign == .Negative { - available -= 1; - buffer[available] = '-'; + available -= 1 + buffer[available] = '-' } - internal_destroy(temp, denominator); + internal_destroy(temp, denominator) /* If we overestimated the size, we need to move the buffer left. */ - written = len(buffer) - available; + written = len(buffer) - available if written < len(buffer) { - diff := len(buffer) - written; - mem.copy(&buffer[0], &buffer[diff], written); + diff := len(buffer) - written + mem.copy(&buffer[0], &buffer[diff], written) } - return written, nil; + return written, nil }
\ No newline at end of file diff --git a/core/math/big/test.odin b/core/math/big/test.odin index ea3c6be49..609b8ce10 100644 --- a/core/math/big/test.odin +++ b/core/math/big/test.odin @@ -25,24 +25,24 @@ PyRes :: struct { } @export test_initialize_constants :: proc "c" () -> (res: u64) { - context = runtime.default_context(); - res = u64(initialize_constants()); + context = runtime.default_context() + res = u64(initialize_constants()) //assert(MUL_KARATSUBA_CUTOFF >= 40); - return res; + return res } @export test_error_string :: proc "c" (err: Error) -> (res: cstring) { - context = runtime.default_context(); - es := Error_String; - return strings.clone_to_cstring(es[err], context.temp_allocator); + context = runtime.default_context() + es := Error_String + return strings.clone_to_cstring(es[err], context.temp_allocator) } @export test_add :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, sum := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, sum); + aa, bb, sum := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, sum) 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}; } @@ -52,18 +52,18 @@ PyRes :: struct { if err = #force_inline internal_add(sum, aa, bb); err != nil { return PyRes{res=":add:add(sum,a,b):", err=err}; } } - r: cstring; - r, err = int_itoa_cstring(sum, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(sum, 16, context.temp_allocator) if err != nil { return PyRes{res=":add:itoa(sum):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @export test_sub :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, sum := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, sum); + aa, bb, sum := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, sum) 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}; } @@ -73,63 +73,63 @@ PyRes :: struct { if err = #force_inline internal_sub(sum, aa, bb); err != nil { return PyRes{res=":sub:sub(sum,a,b):", err=err}; } } - r: cstring; - r, err = int_itoa_cstring(sum, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(sum, 16, context.temp_allocator) if err != nil { return PyRes{res=":sub:itoa(sum):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @export test_mul :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, product := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, product); + aa, bb, product := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, product) 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 = #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); + r: cstring + r, err = int_itoa_cstring(product, 16, context.temp_allocator) if err != nil { return PyRes{res=":mul:itoa(product):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @export test_sqr :: proc "c" (a: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, square := &Int{}, &Int{}; - defer internal_destroy(aa, square); + aa, square := &Int{}, &Int{} + defer internal_destroy(aa, square) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":sqr:atoi(a):", err=err}; } if err = #force_inline internal_sqr(square, aa); err != nil { return PyRes{res=":sqr:sqr(square,a):", err=err}; } - r: cstring; - r, err = int_itoa_cstring(square, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(square, 16, context.temp_allocator) if err != nil { return PyRes{res=":sqr:itoa(square):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* NOTE(Jeroen): For simplicity, we don't return the quotient and the remainder, just the quotient. */ @export test_div :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - aa, bb, quotient := &Int{}, &Int{}, &Int{}; - defer internal_destroy(aa, bb, quotient); + aa, bb, quotient := &Int{}, &Int{}, &Int{} + defer internal_destroy(aa, bb, quotient) 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 = #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); + r: cstring + r, err = int_itoa_cstring(quotient, 16, context.temp_allocator) if err != nil { return PyRes{res=":div:itoa(quotient):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } @@ -137,254 +137,254 @@ PyRes :: struct { res = log(a, base) */ @export test_log :: proc "c" (a: cstring, base := DIGIT(2)) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; - l: int; + context = runtime.default_context() + err: Error + l: int - aa := &Int{}; - defer internal_destroy(aa); + aa := &Int{} + defer internal_destroy(aa) if err = atoi(aa, string(a), 16); err != nil { return PyRes{res=":log:atoi(a):", err=err}; } if l, err = #force_inline internal_log(aa, base); err != nil { return PyRes{res=":log:log(a, base):", err=err}; } #force_inline internal_zero(aa); - aa.digit[0] = DIGIT(l) & _MASK; - aa.digit[1] = DIGIT(l) >> _DIGIT_BITS; - aa.used = 2; - clamp(aa); + aa.digit[0] = DIGIT(l) & _MASK + aa.digit[1] = DIGIT(l) >> _DIGIT_BITS + aa.used = 2 + clamp(aa) - r: cstring; - r, err = int_itoa_cstring(aa, 16, context.temp_allocator); + r: cstring + r, err = int_itoa_cstring(aa, 16, context.temp_allocator) if err != nil { return PyRes{res=":log:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = base^power */ @export test_pow :: proc "c" (base: cstring, power := int(2)) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - dest, bb := &Int{}, &Int{}; - defer internal_destroy(dest, bb); + dest, bb := &Int{}, &Int{} + defer internal_destroy(dest, bb) if err = atoi(bb, string(base), 16); err != nil { return PyRes{res=":pow:atoi(base):", 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); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":log:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = sqrt(src) */ @export test_sqrt :: proc "c" (source: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":sqrt:atoi(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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":log:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = root_n(src, power) */ @export test_root_n :: proc "c" (source: cstring, power: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":root_n:atoi(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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":root_n:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shr_digit(src, digits) */ @export test_shr_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_digit:atoi(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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shr_digit:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shl_digit(src, digits) */ @export test_shl_digit :: proc "c" (source: cstring, digits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl_digit:atoi(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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shl_digit:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shr(src, bits) */ @export test_shr :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr:atoi(src):", 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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shr:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shr_signed(src, bits) */ @export test_shr_signed :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shr_signed:atoi(src):", 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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shr_signed:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = shl(src, bits) */ @export test_shl :: proc "c" (source: cstring, bits: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - src := &Int{}; - defer internal_destroy(src); + src := &Int{} + defer internal_destroy(src) if err = atoi(src, string(source), 16); err != nil { return PyRes{res=":shl:atoi(src):", 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); + r: cstring + r, err = int_itoa_cstring(src, 16, context.temp_allocator) if err != nil { return PyRes{res=":shl:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = factorial(n) */ @export test_factorial :: proc "c" (n: int) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - dest := &Int{}; - defer internal_destroy(dest); + dest := &Int{} + defer internal_destroy(dest) if err = #force_inline internal_int_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); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":factorial:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = gcd(a, b) */ @export test_gcd :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - ai, bi, dest := &Int{}, &Int{}, &Int{}; - defer internal_destroy(ai, bi, dest); + ai, bi, dest := &Int{}, &Int{}, &Int{} + defer internal_destroy(ai, bi, dest) 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 = #force_inline internal_int_gcd_lcm(dest, nil, 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); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":gcd:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = lcm(a, b) */ @export test_lcm :: proc "c" (a, b: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; + context = runtime.default_context() + err: Error - ai, bi, dest := &Int{}, &Int{}, &Int{}; - defer internal_destroy(ai, bi, dest); + ai, bi, dest := &Int{}, &Int{}, &Int{} + defer internal_destroy(ai, bi, dest) 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 = #force_inline internal_int_gcd_lcm(nil, 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); + r: cstring + r, err = int_itoa_cstring(dest, 16, context.temp_allocator) if err != nil { return PyRes{res=":lcm:itoa(res):", err=err}; } - return PyRes{res = r, err = nil}; + return PyRes{res = r, err = nil} } /* dest = lcm(a, b) */ @export test_is_square :: proc "c" (a: cstring) -> (res: PyRes) { - context = runtime.default_context(); - err: Error; - square: bool; + context = runtime.default_context() + err: Error + square: bool - ai := &Int{}; - defer internal_destroy(ai); + ai := &Int{} + defer internal_destroy(ai) if err = atoi(ai, string(a), 16); err != nil { return PyRes{res=":is_square:atoi(a):", err=err}; } if square, err = #force_inline internal_int_is_square(ai); err != nil { return PyRes{res=":is_square:is_square(a):", err=err}; } if square { - return PyRes{"True", nil}; + return PyRes{"True", nil} } - return PyRes{"False", nil}; + return PyRes{"False", nil} }
\ No newline at end of file diff --git a/core/math/big/tune.odin b/core/math/big/tune.odin index 700a5e74a..c34f73b37 100644 --- a/core/math/big/tune.odin +++ b/core/math/big/tune.odin @@ -24,58 +24,58 @@ Category :: enum { sqr, bitfield_extract, rm_trials, -}; +} Event :: struct { ticks: time.Duration, count: int, cycles: u64, } -Timings := [Category]Event{}; +Timings := [Category]Event{} print_timings :: proc() { duration :: proc(d: time.Duration) -> (res: string) { switch { case d < time.Microsecond: - return fmt.tprintf("%v ns", time.duration_nanoseconds(d)); + return fmt.tprintf("%v ns", time.duration_nanoseconds(d)) case d < time.Millisecond: - return fmt.tprintf("%v µs", time.duration_microseconds(d)); + return fmt.tprintf("%v µs", time.duration_microseconds(d)) case: - return fmt.tprintf("%v ms", time.duration_milliseconds(d)); + return fmt.tprintf("%v ms", time.duration_milliseconds(d)) } } for v in Timings { if v.count > 0 { - fmt.println("\nTimings:"); - break; + fmt.println("\nTimings:") + break } } for v, i in Timings { if v.count > 0 { - avg_ticks := time.Duration(f64(v.ticks) / f64(v.count)); - avg_cycles := f64(v.cycles) / f64(v.count); + avg_ticks := time.Duration(f64(v.ticks) / f64(v.count)) + avg_cycles := f64(v.cycles) / f64(v.count) - fmt.printf("\t%v: %s / %v cycles (avg), %s / %v cycles (total, %v calls)\n", i, duration(avg_ticks), avg_cycles, duration(v.ticks), v.cycles, v.count); + fmt.printf("\t%v: %s / %v cycles (avg), %s / %v cycles (total, %v calls)\n", i, duration(avg_ticks), avg_cycles, duration(v.ticks), v.cycles, v.count) } } } @(deferred_in_out=_SCOPE_END) SCOPED_TIMING :: #force_inline proc(c: Category) -> (ticks: time.Tick, cycles: u64) { - cycles = time.read_cycle_counter(); - ticks = time.tick_now(); - return; + cycles = time.read_cycle_counter() + ticks = time.tick_now() + return } _SCOPE_END :: #force_inline proc(c: Category, ticks: time.Tick, cycles: u64) { - cycles_now := time.read_cycle_counter(); - ticks_now := time.tick_now(); + cycles_now := time.read_cycle_counter() + ticks_now := time.tick_now() - Timings[c].ticks = time.tick_diff(ticks, ticks_now); - Timings[c].cycles = cycles_now - cycles; - Timings[c].count += 1; + Timings[c].ticks = time.tick_diff(ticks, ticks_now) + Timings[c].cycles = cycles_now - cycles + Timings[c].count += 1 } SCOPED_COUNT_ADD :: #force_inline proc(c: Category, count: int) { - Timings[c].count += count; + Timings[c].count += count } diff --git a/core/math/bits/bits.odin b/core/math/bits/bits.odin index 91b773504..c65c2fa2b 100644 --- a/core/math/bits/bits.odin +++ b/core/math/bits/bits.odin @@ -2,66 +2,66 @@ package math_bits import "core:intrinsics" -U8_MIN :: 0; -U16_MIN :: 0; -U32_MIN :: 0; -U64_MIN :: 0; +U8_MIN :: 0 +U16_MIN :: 0 +U32_MIN :: 0 +U64_MIN :: 0 -U8_MAX :: 1 << 8 - 1; -U16_MAX :: 1 << 16 - 1; -U32_MAX :: 1 << 32 - 1; -U64_MAX :: 1 << 64 - 1; +U8_MAX :: 1 << 8 - 1 +U16_MAX :: 1 << 16 - 1 +U32_MAX :: 1 << 32 - 1 +U64_MAX :: 1 << 64 - 1 -I8_MIN :: - 1 << 7; -I16_MIN :: - 1 << 15; -I32_MIN :: - 1 << 31; -I64_MIN :: - 1 << 63; +I8_MIN :: - 1 << 7 +I16_MIN :: - 1 << 15 +I32_MIN :: - 1 << 31 +I64_MIN :: - 1 << 63 -I8_MAX :: 1 << 7 - 1; -I16_MAX :: 1 << 15 - 1; -I32_MAX :: 1 << 31 - 1; -I64_MAX :: 1 << 63 - 1; +I8_MAX :: 1 << 7 - 1 +I16_MAX :: 1 << 15 - 1 +I32_MAX :: 1 << 31 - 1 +I64_MAX :: 1 << 63 - 1 -count_ones :: intrinsics.count_ones; -count_zeros :: intrinsics.count_zeros; -trailing_zeros :: intrinsics.count_trailing_zeros; -leading_zeros :: intrinsics.count_leading_zeros; -count_trailing_zeros :: intrinsics.count_trailing_zeros; -count_leading_zeros :: intrinsics.count_leading_zeros; -reverse_bits :: intrinsics.reverse_bits; -byte_swap :: intrinsics.byte_swap; +count_ones :: intrinsics.count_ones +count_zeros :: intrinsics.count_zeros +trailing_zeros :: intrinsics.count_trailing_zeros +leading_zeros :: intrinsics.count_leading_zeros +count_trailing_zeros :: intrinsics.count_trailing_zeros +count_leading_zeros :: intrinsics.count_leading_zeros +reverse_bits :: intrinsics.reverse_bits +byte_swap :: intrinsics.byte_swap -overflowing_add :: intrinsics.overflow_add; -overflowing_sub :: intrinsics.overflow_sub; -overflowing_mul :: intrinsics.overflow_mul; +overflowing_add :: intrinsics.overflow_add +overflowing_sub :: intrinsics.overflow_sub +overflowing_mul :: intrinsics.overflow_mul rotate_left8 :: proc(x: u8, k: int) -> u8 { - n :: 8; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 8 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left16 :: proc(x: u16, k: int) -> u16 { - n :: 16; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 16 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left32 :: proc(x: u32, k: int) -> u32 { - n :: 32; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 32 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left64 :: proc(x: u64, k: int) -> u64 { - n :: 64; - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 64 + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } rotate_left :: proc(x: uint, k: int) -> uint { - n :: 8*size_of(uint); - s := uint(k) & (n-1); - return x <<s | x>>(n-s); + n :: 8*size_of(uint) + s := uint(k) & (n-1) + return x <<s | x>>(n-s) } from_be_u8 :: proc(i: u8) -> u8 { return i; } @@ -92,205 +92,205 @@ to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } len_u8 :: proc(x: u8) -> int { - return int(len_u8_table[x]); + return int(len_u8_table[x]) } len_u16 :: proc(x: u16) -> (n: int) { - x := x; + x := x if x >= 1<<8 { - x >>= 8; - n = 8; + x >>= 8 + n = 8 } - return n + int(len_u8_table[x]); + return n + int(len_u8_table[x]) } len_u32 :: proc(x: u32) -> (n: int) { - x := x; + x := x if x >= 1<<16 { - x >>= 16; - n = 16; + x >>= 16 + n = 16 } if x >= 1<<8 { - x >>= 8; - n += 8; + x >>= 8 + n += 8 } - return n + int(len_u8_table[x]); + return n + int(len_u8_table[x]) } len_u64 :: proc(x: u64) -> (n: int) { - x := x; + x := x if x >= 1<<32 { - x >>= 32; - n = 32; + x >>= 32 + n = 32 } if x >= 1<<16 { - x >>= 16; - n += 16; + x >>= 16 + n += 16 } if x >= 1<<8 { - x >>= 8; - n += 8; + x >>= 8 + n += 8 } - return n + int(len_u8_table[x]); + return n + int(len_u8_table[x]) } len_uint :: proc(x: uint) -> (n: int) { when size_of(uint) == size_of(u64) { - return len_u64(u64(x)); + return len_u64(u64(x)) } else { - return len_u32(u32(x)); + return len_u32(u32(x)) } } // returns the minimum number of bits required to represent x -len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint}; +len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint} add_u32 :: proc(x, y, carry: u32) -> (sum, carry_out: u32) { - yc := y + carry; - sum = x + yc; + yc := y + carry + sum = x + yc if sum < x || yc < y { - carry_out = 1; + carry_out = 1 } - return; + return } add_u64 :: proc(x, y, carry: u64) -> (sum, carry_out: u64) { - yc := y + carry; - sum = x + yc; + yc := y + carry + sum = x + yc if sum < x || yc < y { - carry_out = 1; + carry_out = 1 } - return; + return } add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) { - yc := y + carry; - sum = x + yc; + yc := y + carry + sum = x + yc if sum < x || yc < y { - carry_out = 1; + carry_out = 1 } - return; + return } -add :: proc{add_u32, add_u64, add_uint}; +add :: proc{add_u32, add_u64, add_uint} sub_u32 :: proc(x, y, borrow: u32) -> (diff, borrow_out: u32) { - yb := y + borrow; - diff = x - yb; + yb := y + borrow + diff = x - yb if diff > x || yb < y { - borrow_out = 1; + borrow_out = 1 } - return; + return } sub_u64 :: proc(x, y, borrow: u64) -> (diff, borrow_out: u64) { - yb := y + borrow; - diff = x - yb; + yb := y + borrow + diff = x - yb if diff > x || yb < y { - borrow_out = 1; + borrow_out = 1 } - return; + return } sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) { - yb := y + borrow; - diff = x - yb; + yb := y + borrow + diff = x - yb if diff > x || yb < y { - borrow_out = 1; + borrow_out = 1 } - return; + return } -sub :: proc{sub_u32, sub_u64, sub_uint}; +sub :: proc{sub_u32, sub_u64, sub_uint} mul_u32 :: proc(x, y: u32) -> (hi, lo: u32) { - z := u64(x) * u64(y); - hi, lo = u32(z>>32), u32(z); - return; + z := u64(x) * u64(y) + hi, lo = u32(z>>32), u32(z) + return } mul_u64 :: proc(x, y: u64) -> (hi, lo: u64) { - mask :: 1<<32 - 1; + mask :: 1<<32 - 1 - x0, x1 := x & mask, x >> 32; - y0, y1 := y & mask, y >> 32; + x0, x1 := x & mask, x >> 32 + y0, y1 := y & mask, y >> 32 - w0 := x0 * y0; - t := x1*y0 + w0>>32; + w0 := x0 * y0 + t := x1*y0 + w0>>32 - w1, w2 := t & mask, t >> 32; - w1 += x0 * y1; - hi = x1*y1 + w2 + w1>>32; - lo = x * y; - return; + w1, w2 := t & mask, t >> 32 + w1 += x0 * y1 + hi = x1*y1 + w2 + w1>>32 + lo = x * y + return } mul_uint :: proc(x, y: uint) -> (hi, lo: uint) { when size_of(uint) == size_of(u32) { - a, b := mul_u32(u32(x), u32(y)); + a, b := mul_u32(u32(x), u32(y)) } else { #assert(size_of(uint) == size_of(u64)); - a, b := mul_u64(u64(x), u64(y)); + a, b := mul_u64(u64(x), u64(y)) } - return uint(a), uint(b); + return uint(a), uint(b) } -mul :: proc{mul_u32, mul_u64, mul_uint}; +mul :: proc{mul_u32, mul_u64, mul_uint} div_u32 :: proc(hi, lo, y: u32) -> (quo, rem: u32) { - assert(y != 0 && y <= hi); - z := u64(hi)<<32 | u64(lo); - quo, rem = u32(z/u64(y)), u32(z%u64(y)); - return; + assert(y != 0 && y <= hi) + z := u64(hi)<<32 | u64(lo) + quo, rem = u32(z/u64(y)), u32(z%u64(y)) + return } div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) { - y := y; - two32 :: 1 << 32; - mask32 :: two32 - 1; + y := y + two32 :: 1 << 32 + mask32 :: two32 - 1 if y == 0 { - panic("divide error"); + panic("divide error") } if y <= hi { - panic("overflow error"); + panic("overflow error") } - s := uint(count_leading_zeros(y)); - y <<= s; + s := uint(count_leading_zeros(y)) + y <<= s - yn1 := y >> 32; - yn0 := y & mask32; - un32 := hi<<s | lo>>(64-s); - un10 := lo << s; - un1 := un10 >> 32; - un0 := un10 & mask32; - q1 := un32 / yn1; - rhat := un32 - q1*yn1; + yn1 := y >> 32 + yn0 := y & mask32 + un32 := hi<<s | lo>>(64-s) + un10 := lo << s + un1 := un10 >> 32 + un0 := un10 & mask32 + q1 := un32 / yn1 + rhat := un32 - q1*yn1 for q1 >= two32 || q1*yn0 > two32*rhat+un1 { - q1 -= 1; - rhat += yn1; + q1 -= 1 + rhat += yn1 if rhat >= two32 { - break; + break } } - un21 := un32*two32 + un1 - q1*y; - q0 := un21 / yn1; - rhat = un21 - q0*yn1; + un21 := un32*two32 + un1 - q1*y + q0 := un21 / yn1 + rhat = un21 - q0*yn1 for q0 >= two32 || q0*yn0 > two32*rhat+un0 { - q0 -= 1; - rhat += yn1; + q0 -= 1 + rhat += yn1 if rhat >= two32 { - break; + break } } - return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s; + return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s } div_uint :: proc(hi, lo, y: uint) -> (quo, rem: uint) { when size_of(uint) == size_of(u32) { - a, b := div_u32(u32(hi), u32(lo), u32(y)); + a, b := div_u32(u32(hi), u32(lo), u32(y)) } else { #assert(size_of(uint) == size_of(u64)); - a, b := div_u64(u64(hi), u64(lo), u64(y)); + a, b := div_u64(u64(hi), u64(lo), u64(y)) } - return uint(a), uint(b); + return uint(a), uint(b) } -div :: proc{div_u32, div_u64, div_uint}; +div :: proc{div_u32, div_u64, div_uint} @@ -311,7 +311,7 @@ is_power_of_two :: proc{ is_power_of_two_u32, is_power_of_two_i32, is_power_of_two_u64, is_power_of_two_i64, is_power_of_two_uint, is_power_of_two_int, -}; +} @private @@ -325,7 +325,7 @@ len_u8_table := [256]u8{ 32..<64 = 6, 64..<128 = 7, 128..<256 = 8, -}; +} bitfield_extract_u8 :: proc(value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1); } @@ -336,40 +336,40 @@ bitfield_extract_u128 :: proc(value: u128, offset, bits: uint) -> u128 { return bitfield_extract_uint :: proc(value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1); } bitfield_extract_i8 :: proc(value: i8, offset, bits: uint) -> i8 { - v := (u8(value) >> offset) & u8(1<<bits - 1); - m := u8(1<<(bits-1)); - r := (v~m) - m; - return i8(r); + v := (u8(value) >> offset) & u8(1<<bits - 1) + m := u8(1<<(bits-1)) + r := (v~m) - m + return i8(r) } bitfield_extract_i16 :: proc(value: i16, offset, bits: uint) -> i16 { - v := (u16(value) >> offset) & u16(1<<bits - 1); - m := u16(1<<(bits-1)); - r := (v~m) - m; - return i16(r); + v := (u16(value) >> offset) & u16(1<<bits - 1) + m := u16(1<<(bits-1)) + r := (v~m) - m + return i16(r) } bitfield_extract_i32 :: proc(value: i32, offset, bits: uint) -> i32 { - v := (u32(value) >> offset) & u32(1<<bits - 1); - m := u32(1<<(bits-1)); - r := (v~m) - m; - return i32(r); + v := (u32(value) >> offset) & u32(1<<bits - 1) + m := u32(1<<(bits-1)) + r := (v~m) - m + return i32(r) } bitfield_extract_i64 :: proc(value: i64, offset, bits: uint) -> i64 { - v := (u64(value) >> offset) & u64(1<<bits - 1); - m := u64(1<<(bits-1)); - r := (v~m) - m; - return i64(r); + v := (u64(value) >> offset) & u64(1<<bits - 1) + m := u64(1<<(bits-1)) + r := (v~m) - m + return i64(r) } bitfield_extract_i128 :: proc(value: i128, offset, bits: uint) -> i128 { - v := (u128(value) >> offset) & u128(1<<bits - 1); - m := u128(1<<(bits-1)); - r := (v~m) - m; - return i128(r); + v := (u128(value) >> offset) & u128(1<<bits - 1) + m := u128(1<<(bits-1)) + r := (v~m) - m + return i128(r) } bitfield_extract_int :: proc(value: int, offset, bits: uint) -> int { - v := (uint(value) >> offset) & uint(1<<bits - 1); - m := uint(1<<(bits-1)); - r := (v~m) - m; - return int(r); + v := (uint(value) >> offset) & uint(1<<bits - 1) + m := uint(1<<(bits-1)) + r := (v~m) - m + return int(r) } @@ -386,57 +386,57 @@ bitfield_extract :: proc{ bitfield_extract_i64, bitfield_extract_i128, bitfield_extract_int, -}; +} bitfield_insert_u8 :: proc(base, insert: u8, offset, bits: uint) -> u8 { - mask := u8(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u8(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u16 :: proc(base, insert: u16, offset, bits: uint) -> u16 { - mask := u16(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u16(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u32 :: proc(base, insert: u32, offset, bits: uint) -> u32 { - mask := u32(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u32(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u64 :: proc(base, insert: u64, offset, bits: uint) -> u64 { - mask := u64(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u64(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_u128 :: proc(base, insert: u128, offset, bits: uint) -> u128 { - mask := u128(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := u128(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_uint :: proc(base, insert: uint, offset, bits: uint) -> uint { - mask := uint(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := uint(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i8 :: proc(base, insert: i8, offset, bits: uint) -> i8 { - mask := i8(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i8(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i16 :: proc(base, insert: i16, offset, bits: uint) -> i16 { - mask := i16(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i16(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i32 :: proc(base, insert: i32, offset, bits: uint) -> i32 { - mask := i32(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i32(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i64 :: proc(base, insert: i64, offset, bits: uint) -> i64 { - mask := i64(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i64(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_i128 :: proc(base, insert: i128, offset, bits: uint) -> i128 { - mask := i128(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := i128(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert_int :: proc(base, insert: int, offset, bits: uint) -> int { - mask := int(1<<bits - 1); - return (base &~ (mask<<offset)) | ((insert&mask) << offset); + mask := int(1<<bits - 1) + return (base &~ (mask<<offset)) | ((insert&mask) << offset) } bitfield_insert :: proc{ @@ -452,4 +452,4 @@ bitfield_insert :: proc{ bitfield_insert_i64, bitfield_insert_i128, bitfield_insert_int, -}; +} diff --git a/core/math/fixed/fixed.odin b/core/math/fixed/fixed.odin index 6e4709af7..ef97b66d3 100644 --- a/core/math/fixed/fixed.odin +++ b/core/math/fixed/fixed.odin @@ -4,7 +4,7 @@ import "core:math" import "core:strconv" import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics Fixed :: struct($Backing: typeid, $Fraction_Width: uint) where @@ -14,120 +14,120 @@ Fixed :: struct($Backing: typeid, $Fraction_Width: uint) i: Backing, } -Fixed4_4 :: distinct Fixed(i8, 4); -Fixed5_3 :: distinct Fixed(i8, 3); -Fixed6_2 :: distinct Fixed(i8, 2); -Fixed7_1 :: distinct Fixed(i8, 1); +Fixed4_4 :: distinct Fixed(i8, 4) +Fixed5_3 :: distinct Fixed(i8, 3) +Fixed6_2 :: distinct Fixed(i8, 2) +Fixed7_1 :: distinct Fixed(i8, 1) -Fixed8_8 :: distinct Fixed(i16, 8); -Fixed13_3 :: distinct Fixed(i16, 3); +Fixed8_8 :: distinct Fixed(i16, 8) +Fixed13_3 :: distinct Fixed(i16, 3) -Fixed16_16 :: distinct Fixed(i32, 16); -Fixed26_6 :: distinct Fixed(i32, 6); +Fixed16_16 :: distinct Fixed(i32, 16) +Fixed26_6 :: distinct Fixed(i32, 6) -Fixed32_32 :: distinct Fixed(i64, 32); -Fixed52_12 :: distinct Fixed(i64, 12); +Fixed32_32 :: distinct Fixed(i64, 32) +Fixed52_12 :: distinct Fixed(i64, 12) init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) { - i, f := math.modf(val); - x.i = Backing(f * (1<<Fraction_Width)); - x.i &= 1<<Fraction_Width - 1; - x.i |= Backing(i) << Fraction_Width; + i, f := math.modf(val) + x.i = Backing(f * (1<<Fraction_Width)) + x.i &= 1<<Fraction_Width - 1 + x.i |= Backing(i) << Fraction_Width } init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) { - i, f := math.modf(val); - x.i = fraction; - x.i &= 1<<Fraction_Width - 1; - x.i |= integer; + i, f := math.modf(val) + x.i = fraction + x.i &= 1<<Fraction_Width - 1 + x.i |= integer } to_f64 :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> f64 { - res := f64(x.i >> Fraction_Width); - res += f64(x.i & (1<<Fraction_Width-1)) / f64(1<<Fraction_Width); - return res; + res := f64(x.i >> Fraction_Width) + res += f64(x.i & (1<<Fraction_Width-1)) / f64(1<<Fraction_Width) + return res } add :: proc(x, y: $T/Fixed) -> T { - return {x.i + y.i}; + return {x.i + y.i} } sub :: proc(x, y: $T/Fixed) -> T { - return {x.i - y.i}; + return {x.i - y.i} } mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width) + return } mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width) + return } div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width) + return } div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) { - z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width); - return; + z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width) + return } floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - return x.i >> Fraction_Width; + return x.i >> Fraction_Width } ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - Integer :: 8*size_of(Backing) - Fraction_Width; - return (x.i + (1 << Integer-1)) >> Fraction_Width; + Integer :: 8*size_of(Backing) - Fraction_Width + return (x.i + (1 << Integer-1)) >> Fraction_Width } round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing { - Integer :: 8*size_of(Backing) - Fraction_Width; - return (x.i + (1 << (Integer - 1))) >> Fraction_Width; + Integer :: 8*size_of(Backing) - Fraction_Width + return (x.i + (1 << (Integer - 1))) >> Fraction_Width } append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string { - x := x; - buf: [48]byte; - i := 0; + x := x + buf: [48]byte + i := 0 if x.i < 0 { - buf[i] = '-'; - i += 1; - x.i = -x.i; + buf[i] = '-' + i += 1 + x.i = -x.i } - integer := x.i >> Fraction_Width; - fraction := x.i & (1<<Fraction_Width - 1); + integer := x.i >> Fraction_Width + fraction := x.i & (1<<Fraction_Width - 1) - s := strconv.append_uint(buf[i:], u64(integer), 10); - i += len(s); + s := strconv.append_uint(buf[i:], u64(integer), 10) + i += len(s) if fraction != 0 { - buf[i] = '.'; - i += 1; + buf[i] = '.' + i += 1 for fraction > 0 { - fraction *= 10; - buf[i] = byte('0' + (fraction>>Fraction_Width)); - i += 1; - fraction &= 1<<Fraction_Width - 1; + fraction *= 10 + buf[i] = byte('0' + (fraction>>Fraction_Width)) + i += 1 + fraction &= 1<<Fraction_Width - 1 } } - n := copy(dst, buf[:i]); - return string(dst[:i]); + n := copy(dst, buf[:i]) + return string(dst[:i]) } to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string { - buf: [48]byte; - s := append(buf[:], x); - str := make([]byte, len(s), allocator); - copy(str, s); - return string(str); + buf: [48]byte + s := append(buf[:], x) + str := make([]byte, len(s), allocator) + copy(str, s) + return string(str) } diff --git a/core/math/linalg/extended.odin b/core/math/linalg/extended.odin index 373a4e4ce..8f7b2dd1e 100644 --- a/core/math/linalg/extended.odin +++ b/core/math/linalg/extended.odin @@ -6,476 +6,476 @@ import "core:math" radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = degrees * RAD_PER_DEG; + out[i] = degrees * RAD_PER_DEG } } else { - out = degrees * RAD_PER_DEG; + out = degrees * RAD_PER_DEG } - return; + return } degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = radians * DEG_PER_RAD; + out[i] = radians * DEG_PER_RAD } } else { - out = radians * DEG_PER_RAD; + out = radians * DEG_PER_RAD } - return; + return } min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.min(a[i], b[i]); + out[i] = builtin.min(a[i], b[i]) } } else { - out = builtin.min(a, b); + out = builtin.min(a, b) } - return; + return } min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - N :: len(T); + N :: len(T) when N == 1 { - out = a[0]; + out = a[0] } else when N == 2 { - out = builtin.min(a[0], a[1]); + out = builtin.min(a[0], a[1]) } else { - out = builtin.min(a[0], a[1]); + out = builtin.min(a[0], a[1]) for i in 2..<N { - out = builtin.min(out, a[i]); + out = builtin.min(out, a[i]) } } } else { - out = a; + out = a } - return; + return } min_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) { - return min_double(a, min_double(b, c)); + return min_double(a, min_double(b, c)) } -min :: proc{min_single, min_double, min_triple}; +min :: proc{min_single, min_double, min_triple} max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.max(a[i], b[i]); + out[i] = builtin.max(a[i], b[i]) } } else { - out = builtin.max(a, b); + out = builtin.max(a, b) } - return; + return } max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { - N :: len(T); + N :: len(T) when N == 1 { - out = a[0]; + out = a[0] } else when N == 2 { - out = builtin.max(a[0], a[1]); + out = builtin.max(a[0], a[1]) } else when N == 3 { - out = builtin.max(a[0], a[1], a[3]); + out = builtin.max(a[0], a[1], a[3]) }else { - out = builtin.max(a[0], a[1]); + out = builtin.max(a[0], a[1]) for i in 2..<N { - out = builtin.max(out, a[i]); + out = builtin.max(out, a[i]) } } } else { - out = a; + out = a } - return; + return } max_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) { - return max_double(a, max_double(b, c)); + return max_double(a, max_double(b, c)) } -max :: proc{max_single, max_double, max_triple}; +max :: proc{max_single, max_double, max_triple} abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.abs(a[i]); + out[i] = builtin.abs(a[i]) } } else { - out = builtin.abs(a); + out = builtin.abs(a) } - return; + return } sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.sign(a[i]); + out[i] = #force_inline math.sign(a[i]) } } else { - out = #force_inline math.sign(a); + out = #force_inline math.sign(a) } - return; + return } clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = builtin.clamp(x[i], a[i], b[i]); + out[i] = builtin.clamp(x[i], a[i], b[i]) } } else { - out = builtin.clamp(x, a, b); + out = builtin.clamp(x, a, b) } - return; + return } saturate :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - return clamp(x, 0.0, 1.0); + return clamp(x, 0.0, 1.0) } lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = a[i]*(1-t[i]) + b[i]*t[i]; + out[i] = a[i]*(1-t[i]) + b[i]*t[i] } } else { - out = a * (1.0 - t) + b * t; + out = a * (1.0 - t) + b * t } - return; + return } mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = a[i]*(1-t[i]) + b[i]*t[i]; + out[i] = a[i]*(1-t[i]) + b[i]*t[i] } } else { - out = a * (1.0 - t) + b * t; + out = a * (1.0 - t) + b * t } - return; + return } unlerp :: proc(a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - return (x - a) / (b - a); + return (x - a) / (b - a) } step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = x[i] < e[i] ? 0.0 : 1.0; + out[i] = x[i] < e[i] ? 0.0 : 1.0 } } else { - out = x < e ? 0.0 : 1.0; + out = x < e ? 0.0 : 1.0 } - return; + return } smoothstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - t := saturate(unlerp(e0, e1, x)); - return t * t * (3.0 - 2.0 * t); + t := saturate(unlerp(e0, e1, x)) + return t * t * (3.0 - 2.0 * t) } smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - t := saturate(unlerp(e0, e1, x)); - return t * t * t * (t * (6*t - 15) + 10); + t := saturate(unlerp(e0, e1, x)) + return t * t * t * (t * (6*t - 15) + 10) } sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.sqrt(x[i]); + out[i] = math.sqrt(x[i]) } } else { - out = math.sqrt(x); + out = math.sqrt(x) } - return; + return } inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = 1.0/math.sqrt(x[i]); + out[i] = 1.0/math.sqrt(x[i]) } } else { - out = 1.0/math.sqrt(x); + out = 1.0/math.sqrt(x) } - return; + return } cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.cos(x[i]); + out[i] = math.cos(x[i]) } } else { - out = math.cos(x); + out = math.cos(x) } - return; + return } sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.sin(x[i]); + out[i] = math.sin(x[i]) } } else { - out = math.sin(x); + out = math.sin(x) } - return; + return } tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.tan(x[i]); + out[i] = math.tan(x[i]) } } else { - out = math.tan(x); + out = math.tan(x) } - return; + return } acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.acos(x[i]); + out[i] = math.acos(x[i]) } } else { - out = math.acos(x); + out = math.acos(x) } - return; + return } asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.asin(x[i]); + out[i] = math.asin(x[i]) } } else { - out = math.asin(x); + out = math.asin(x) } - return; + return } atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.atan(x[i]); + out[i] = math.atan(x[i]) } } else { - out = math.atan(x); + out = math.atan(x) } - return; + return } atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.atan2(y[i], x[i]); + out[i] = math.atan2(y[i], x[i]) } } else { - out = math.atan2(y, x); + out = math.atan2(y, x) } - return; + return } ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.ln(x[i]); + out[i] = math.ln(x[i]) } } else { - out = math.ln(x); + out = math.ln(x) } - return; + return } log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = INVLN2 * math.ln(x[i]); + out[i] = INVLN2 * math.ln(x[i]) } } else { - out = INVLN2 * math.ln(x); + out = INVLN2 * math.ln(x) } - return; + return } log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = INVLN10 * math.ln(x[i]); + out[i] = INVLN10 * math.ln(x[i]) } } else { - out = INVLN10 * math.ln(x); + out = INVLN10 * math.ln(x) } - return; + return } log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i]); + out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i]) } } else { - out = INVLN10 * math.ln(x) / math.ln(cast(ELEM_TYPE(T))b); + out = INVLN10 * math.ln(x) / math.ln(cast(ELEM_TYPE(T))b) } - return; + return } exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.exp(x[i]); + out[i] = math.exp(x[i]) } } else { - out = math.exp(x); + out = math.exp(x) } - return; + return } exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.exp(LN2 * x[i]); + out[i] = math.exp(LN2 * x[i]) } } else { - out = math.exp(LN2 * x); + out = math.exp(LN2 * x) } - return; + return } exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.exp(LN10 * x[i]); + out[i] = math.exp(LN10 * x[i]) } } else { - out = math.exp(LN10 * x); + out = math.exp(LN10 * x) } - return; + return } pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = math.pow(x[i], e[i]); + out[i] = math.pow(x[i], e[i]) } } else { - out = math.pow(x, e); + out = math.pow(x, e) } - return; + return } ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.ceil(x[i]); + out[i] = #force_inline math.ceil(x[i]) } } else { - out = #force_inline math.ceil(x); + out = #force_inline math.ceil(x) } - return; + return } floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.floor(x[i]); + out[i] = #force_inline math.floor(x[i]) } } else { - out = #force_inline math.floor(x); + out = #force_inline math.floor(x) } - return; + return } round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0..<len(T) { - out[i] = #force_inline math.round(x[i]); + out[i] = #force_inline math.round(x[i]) } } else { - out = #force_inline math.round(x); + out = #force_inline math.round(x) } - return; + return } fract :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - f := #force_inline floor(x); - return x - f; + f := #force_inline floor(x) + return x - f } mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { - f := #force_inline floor(x / m); - return x - f * m; + f := #force_inline floor(x / m) + return x - f * m } face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { - return dot(N_ref, I) < 0 ? N : -N; + return dot(N_ref, I) < 0 ? N : -N } distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) { - return length(p1 - p0); + return length(p1 - p0) } reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { - b := n * (2 * dot(n, i)); - return i - b; + b := n * (2 * dot(n, i)) + return i - b } refract :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { - dv := dot(n, i); - k := 1 - eta*eta - (1 - dv*dv); - a := i * eta; - b := n * eta*dv*math.sqrt(k); - return (a - b) * E(int(k >= 0)); + dv := dot(n, i) + k := 1 - eta*eta - (1 - dv*dv) + a := i * eta + b := n * eta*dv*math.sqrt(k) + return (a - b) * E(int(k >= 0)) } is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) { - return #force_inline math.is_nan(x); + return #force_inline math.is_nan(x) } is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { for i in 0..<N { - out[i] = #force_inline is_nan(x[i]); + out[i] = #force_inline is_nan(x[i]) } - return; + return } is_inf_single :: proc(x: $T) -> bool where IS_FLOAT(T) { - return #force_inline math.is_inf(x); + return #force_inline math.is_inf(x) } is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { for i in 0..<N { - out[i] = #force_inline is_inf(x[i]); + out[i] = #force_inline is_inf(x[i]) } - return; + return } classify_single :: proc(x: $T) -> math.Float_Class where IS_FLOAT(T) { - return #force_inline math.classify(x); + return #force_inline math.classify(x) } classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) { for i in 0..<N { - out[i] = #force_inline classify_single(x[i]); + out[i] = #force_inline classify_single(x[i]) } - return; + return } -is_nan :: proc{is_nan_single, is_nan_array}; -is_inf :: proc{is_inf_single, is_inf_array}; -classify :: proc{classify_single, classify_array}; +is_nan :: proc{is_nan_single, is_nan_array} +is_inf :: proc{is_inf_single, is_inf_array} +classify :: proc{classify_single, classify_array} less_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y; } @@ -487,67 +487,67 @@ not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), I less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] < y[i]; + out[i] = x[i] < y[i] } - return; + return } less_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] <= y[i]; + out[i] = x[i] <= y[i] } - return; + return } greater_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] > y[i]; + out[i] = x[i] > y[i] } - return; + return } greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] >= y[i]; + out[i] = x[i] >= y[i] } - return; + return } equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] == y[i]; + out[i] = x[i] == y[i] } - return; + return } not_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..<N { - out[i] = x[i] != y[i]; + out[i] = x[i] != y[i] } - return; + return } -less_than :: proc{less_than_single, less_than_array}; -less_than_equal :: proc{less_than_equal_single, less_than_equal_array}; -greater_than :: proc{greater_than_single, greater_than_array}; -greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array}; -equal :: proc{equal_single, equal_array}; -not_equal :: proc{not_equal_single, not_equal_array}; +less_than :: proc{less_than_single, less_than_array} +less_than_equal :: proc{less_than_equal_single, less_than_equal_array} +greater_than :: proc{greater_than_single, greater_than_array} +greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array} +equal :: proc{equal_single, equal_array} +not_equal :: proc{not_equal_single, not_equal_array} any :: proc(x: $A/[$N]bool) -> (out: bool) { for e in x { if x { - return true; + return true } } - return false; + return false } all :: proc(x: $A/[$N]bool) -> (out: bool) { for e in x { if !e { - return false; + return false } } - return true; + return true } not :: proc(x: $A/[$N]bool) -> (out: A) { for e, i in x { - out[i] = !e; + out[i] = !e } - return; + return } diff --git a/core/math/linalg/general.odin b/core/math/linalg/general.odin index a053b75fd..241a50f28 100644 --- a/core/math/linalg/general.odin +++ b/core/math/linalg/general.odin @@ -5,178 +5,178 @@ import "core:intrinsics" // Generic -TAU :: 6.28318530717958647692528676655900576; -PI :: 3.14159265358979323846264338327950288; +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 -E :: 2.71828182845904523536; +E :: 2.71828182845904523536 -τ :: TAU; -π :: PI; -e :: E; +τ :: TAU +π :: PI +e :: E -SQRT_TWO :: 1.41421356237309504880168872420969808; -SQRT_THREE :: 1.73205080756887729352744634150587236; -SQRT_FIVE :: 2.23606797749978969640917366873127623; +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 -LN2 :: 0.693147180559945309417232121458176568; -LN10 :: 2.30258509299404568401799145468436421; +LN2 :: 0.693147180559945309417232121458176568 +LN10 :: 2.30258509299404568401799145468436421 -MAX_F64_PRECISION :: 16; // Maximum number of meaningful digits after the decimal point for 'f64' -MAX_F32_PRECISION :: 8; // Maximum number of meaningful digits after the decimal point for 'f32' +MAX_F64_PRECISION :: 16 // Maximum number of meaningful digits after the decimal point for 'f64' +MAX_F32_PRECISION :: 8 // Maximum number of meaningful digits after the decimal point for 'f32' -RAD_PER_DEG :: TAU/360.0; -DEG_PER_RAD :: 360.0/TAU; +RAD_PER_DEG :: TAU/360.0 +DEG_PER_RAD :: 360.0/TAU -@private IS_NUMERIC :: intrinsics.type_is_numeric; -@private IS_QUATERNION :: intrinsics.type_is_quaternion; -@private IS_ARRAY :: intrinsics.type_is_array; -@private IS_FLOAT :: intrinsics.type_is_float; -@private BASE_TYPE :: intrinsics.type_base_type; -@private ELEM_TYPE :: intrinsics.type_elem_type; +@private IS_NUMERIC :: intrinsics.type_is_numeric +@private IS_QUATERNION :: intrinsics.type_is_quaternion +@private IS_ARRAY :: intrinsics.type_is_array +@private IS_FLOAT :: intrinsics.type_is_float +@private BASE_TYPE :: intrinsics.type_base_type +@private ELEM_TYPE :: intrinsics.type_elem_type scalar_dot :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) { - return a * b; + return a * b } vector_dot :: proc(a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check { for i in 0..<N { - c += a[i] * b[i]; + c += a[i] * b[i] } - return; + return } quaternion64_dot :: proc(a, b: $T/quaternion64) -> (c: f16) { - return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z; + return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z } quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) { - return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z; + return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z } quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) { - return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z; + return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z } -dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot}; +dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot} -inner_product :: dot; +inner_product :: dot outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) #no_bounds_check { for i in 0..<M { for j in 0..<N { - out[i][j] = a[i]*b[j]; + out[i][j] = a[i]*b[j] } } - return; + return } quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0); + return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0) } scalar_cross :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) { - return a * b; + return a * b } vector_cross2 :: proc(a, b: $T/[2]$E) -> E where IS_NUMERIC(E) { - return a[0]*b[1] - b[0]*a[1]; + return a[0]*b[1] - b[0]*a[1] } vector_cross3 :: proc(a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) { - c[0] = a[1]*b[2] - b[1]*a[2]; - c[1] = a[2]*b[0] - b[2]*a[0]; - c[2] = a[0]*b[1] - b[0]*a[1]; - return; + c[0] = a[1]*b[2] - b[1]*a[2] + c[1] = a[2]*b[0] - b[2]*a[0] + c[2] = a[0]*b[1] - b[0]*a[1] + return } quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) { - q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; - q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; - q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; - q3.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; - return; + q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y + q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z + q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x + q3.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z + return } -vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3}; -cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross}; +vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3} +cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross} vector_normalize :: proc(v: $T/[$N]$E) -> T where IS_NUMERIC(E) { - return v / length(v); + return v / length(v) } quaternion_normalize :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return q/abs(q); + return q/abs(q) } -normalize :: proc{vector_normalize, quaternion_normalize}; +normalize :: proc{vector_normalize, quaternion_normalize} vector_normalize0 :: proc(v: $T/[$N]$E) -> T where IS_NUMERIC(E) { - m := length(v); - return 0 if m == 0 else v/m; + m := length(v) + return 0 if m == 0 else v/m } quaternion_normalize0 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - m := abs(q); - return 0 if m == 0 else q/m; + m := abs(q) + return 0 if m == 0 else q/m } -normalize0 :: proc{vector_normalize0, quaternion_normalize0}; +normalize0 :: proc{vector_normalize0, quaternion_normalize0} vector_length :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) { - return math.sqrt(dot(v, v)); + return math.sqrt(dot(v, v)) } vector_length2 :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) { - return dot(v, v); + return dot(v, v) } quaternion_length :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return abs(q); + return abs(q) } quaternion_length2 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) { - return dot(q, q); + return dot(q, q) } scalar_triple_product :: proc(a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) { // a . (b x c) // b . (c x a) // c . (a x b) - return dot(a, cross(b, c)); + return dot(a, cross(b, c)) } vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) { // a x (b x c) // (a . c)b - (a . b)c - return cross(a, cross(b, c)); + return cross(a, cross(b, c)) } -length :: proc{vector_length, quaternion_length}; -length2 :: proc{vector_length2, quaternion_length2}; +length :: proc{vector_length, quaternion_length} +length2 :: proc{vector_length2, quaternion_length2} projection :: proc(x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) { - return dot(x, normal) / dot(normal, normal) * normal; + return dot(x, normal) / dot(normal, normal) * normal } identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check { for i in 0..<N { - m[i][i] = E(1); + m[i][i] = E(1) } - return m; + return m } trace :: proc(m: $T/[$N][N]$E) -> (tr: E) { for i in 0..<N { - tr += m[i][i]; + tr += m[i][i] } - return; + return } transpose :: proc(a: $T/[$N][$M]$E) -> (m: (T when N == M else [M][N]E)) #no_bounds_check { for j in 0..<M { for i in 0..<N { - m[j][i] = a[i][j]; + m[j][i] = a[i][j] } } - return; + return } matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M) @@ -184,21 +184,21 @@ matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M) for i in 0..<N { for k in 0..<N { for j in 0..<N { - c[k][i] += a[j][i] * b[k][j]; + c[k][i] += a[j][i] * b[k][j] } } } - return; + return } matrix_comp_mul :: proc(a, b: $M/[$J][$I]$E) -> (c: M) where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { for j in 0..<J { for i in 0..<I { - c[j][i] = a[j][i] * b[j][i]; + c[j][i] = a[j][i] * b[j][i] } } - return; + return } matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E) @@ -206,11 +206,11 @@ matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E) for k in 0..<K { for j in 0..<J { for i in 0..<I { - c[k][i] += a[j][i] * b[k][j]; + c[k][i] += a[j][i] * b[k][j] } } } - return; + return } @@ -218,44 +218,44 @@ matrix_mul_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B) where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check { for i in 0..<I { for j in 0..<J { - c[j] += a[i][j] * b[i]; + c[j] += a[i][j] * b[i] } } - return; + return } quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) { - return q1 * q2; + return q1 * q2 } quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V { - Raw_Quaternion :: struct {xyz: [3]f16, r: f16}; + Raw_Quaternion :: struct {xyz: [3]f16, r: f16} - q := transmute(Raw_Quaternion)q; - v := transmute([3]f16)v; + q := transmute(Raw_Quaternion)q + v := transmute([3]f16)v - t := cross(2*q.xyz, v); - return V(v + q.r*t + cross(q.xyz, t)); + t := cross(2*q.xyz, v) + return V(v + q.r*t + cross(q.xyz, t)) } quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V { - Raw_Quaternion :: struct {xyz: [3]f32, r: f32}; + Raw_Quaternion :: struct {xyz: [3]f32, r: f32} - q := transmute(Raw_Quaternion)q; - v := transmute([3]f32)v; + q := transmute(Raw_Quaternion)q + v := transmute([3]f32)v - t := cross(2*q.xyz, v); - return V(v + q.r*t + cross(q.xyz, t)); + t := cross(2*q.xyz, v) + return V(v + q.r*t + cross(q.xyz, t)) } quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V { - Raw_Quaternion :: struct {xyz: [3]f64, r: f64}; + Raw_Quaternion :: struct {xyz: [3]f64, r: f64} - q := transmute(Raw_Quaternion)q; - v := transmute([3]f64)v; + q := transmute(Raw_Quaternion)q + v := transmute([3]f64)v - t := cross(2*q.xyz, v); - return V(v + q.r*t + cross(q.xyz, t)); + t := cross(2*q.xyz, v) + return V(v + q.r*t + cross(q.xyz, t)) } -quaternion_mul_vector3 :: proc{quaternion64_mul_vector3, quaternion128_mul_vector3, quaternion256_mul_vector3}; +quaternion_mul_vector3 :: proc{quaternion64_mul_vector3, quaternion128_mul_vector3, quaternion256_mul_vector3} mul :: proc{ matrix_mul, @@ -265,16 +265,16 @@ mul :: proc{ quaternion128_mul_vector3, quaternion256_mul_vector3, quaternion_mul_quaternion, -}; +} vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check { - return &v[0]; + return &v[0] } matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check { - return &m[0][0]; + return &m[0][0] } -to_ptr :: proc{vector_to_ptr, matrix_to_ptr}; +to_ptr :: proc{vector_to_ptr, matrix_to_ptr} @@ -283,60 +283,60 @@ to_ptr :: proc{vector_to_ptr, matrix_to_ptr}; // Splines vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T { - cos_alpha := dot(x, y); - alpha := math.acos(cos_alpha); - sin_alpha := math.sin(alpha); + cos_alpha := dot(x, y) + alpha := math.acos(cos_alpha) + sin_alpha := math.sin(alpha) - t1 := math.sin((1 - a) * alpha) / sin_alpha; - t2 := math.sin(a * alpha) / sin_alpha; + t1 := math.sin((1 - a) * alpha) / sin_alpha + t2 := math.sin(a * alpha) / sin_alpha - return x * t1 + y * t2; + return x * t1 + y * t2 } catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T { - s2 := s*s; - s3 := s2*s; + s2 := s*s + s3 := s2*s - f1 := -s3 + 2 * s2 - s; - f2 := 3 * s3 - 5 * s2 + 2; - f3 := -3 * s3 + 4 * s2 + s; - f4 := s3 - s2; + f1 := -s3 + 2 * s2 - s + f2 := 3 * s3 - 5 * s2 + 2 + f3 := -3 * s3 + 4 * s2 + s + f4 := s3 - s2 - return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5; + return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5 } hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T { - s2 := s*s; - s3 := s2*s; + s2 := s*s + s3 := s2*s - f1 := 2 * s3 - 3 * s2 + 1; - f2 := -2 * s3 + 3 * s2; - f3 := s3 - 2 * s2 + s; - f4 := s3 - s2; + f1 := 2 * s3 - 3 * s2 + 1 + f2 := -2 * s3 + 3 * s2 + f3 := s3 - 2 * s2 + s + f4 := s3 - s2 - return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2; + return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2 } cubic :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T { - return ((v1 * s + v2) * s + v3) * s + v4; + return ((v1 * s + v2) * s + v3) * s + v4 } array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check { for i in 0..<N { - w[i] = Elem_Type(v[i]); + w[i] = Elem_Type(v[i]) } - return; + return } matrix_cast :: proc(v: $A/[$M][$N]$T, $Elem_Type: typeid) -> (w: [M][N]Elem_Type) #no_bounds_check { for i in 0..<M { for j in 0..<N { - w[i][j] = Elem_Type(v[i][j]); + w[i][j] = Elem_Type(v[i][j]) } } - return; + return } to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32); } diff --git a/core/math/linalg/specific.odin b/core/math/linalg/specific.odin index 7d0d9dc7e..333d17e44 100644 --- a/core/math/linalg/specific.odin +++ b/core/math/linalg/specific.odin @@ -2,2452 +2,2452 @@ package linalg import "core:math" -F16_EPSILON :: 1e-3; -F32_EPSILON :: 1e-7; -F64_EPSILON :: 1e-15; - -Vector2f16 :: distinct [2]f16; -Vector3f16 :: distinct [3]f16; -Vector4f16 :: distinct [4]f16; - -Matrix1x1f16 :: distinct [1][1]f16; -Matrix1x2f16 :: distinct [1][2]f16; -Matrix1x3f16 :: distinct [1][3]f16; -Matrix1x4f16 :: distinct [1][4]f16; - -Matrix2x1f16 :: distinct [2][1]f16; -Matrix2x2f16 :: distinct [2][2]f16; -Matrix2x3f16 :: distinct [2][3]f16; -Matrix2x4f16 :: distinct [2][4]f16; - -Matrix3x1f16 :: distinct [3][1]f16; -Matrix3x2f16 :: distinct [3][2]f16; -Matrix3x3f16 :: distinct [3][3]f16; -Matrix3x4f16 :: distinct [3][4]f16; - -Matrix4x1f16 :: distinct [4][1]f16; -Matrix4x2f16 :: distinct [4][2]f16; -Matrix4x3f16 :: distinct [4][3]f16; -Matrix4x4f16 :: distinct [4][4]f16; - -Matrix1f16 :: Matrix1x1f16; -Matrix2f16 :: Matrix2x2f16; -Matrix3f16 :: Matrix3x3f16; -Matrix4f16 :: Matrix4x4f16; - -Vector2f32 :: distinct [2]f32; -Vector3f32 :: distinct [3]f32; -Vector4f32 :: distinct [4]f32; - -Matrix1x1f32 :: distinct [1][1]f32; -Matrix1x2f32 :: distinct [1][2]f32; -Matrix1x3f32 :: distinct [1][3]f32; -Matrix1x4f32 :: distinct [1][4]f32; - -Matrix2x1f32 :: distinct [2][1]f32; -Matrix2x2f32 :: distinct [2][2]f32; -Matrix2x3f32 :: distinct [2][3]f32; -Matrix2x4f32 :: distinct [2][4]f32; - -Matrix3x1f32 :: distinct [3][1]f32; -Matrix3x2f32 :: distinct [3][2]f32; -Matrix3x3f32 :: distinct [3][3]f32; -Matrix3x4f32 :: distinct [3][4]f32; - -Matrix4x1f32 :: distinct [4][1]f32; -Matrix4x2f32 :: distinct [4][2]f32; -Matrix4x3f32 :: distinct [4][3]f32; -Matrix4x4f32 :: distinct [4][4]f32; - -Matrix1f32 :: Matrix1x1f32; -Matrix2f32 :: Matrix2x2f32; -Matrix3f32 :: Matrix3x3f32; -Matrix4f32 :: Matrix4x4f32; - -Vector2f64 :: distinct [2]f64; -Vector3f64 :: distinct [3]f64; -Vector4f64 :: distinct [4]f64; - -Matrix1x1f64 :: distinct [1][1]f64; -Matrix1x2f64 :: distinct [1][2]f64; -Matrix1x3f64 :: distinct [1][3]f64; -Matrix1x4f64 :: distinct [1][4]f64; - -Matrix2x1f64 :: distinct [2][1]f64; -Matrix2x2f64 :: distinct [2][2]f64; -Matrix2x3f64 :: distinct [2][3]f64; -Matrix2x4f64 :: distinct [2][4]f64; - -Matrix3x1f64 :: distinct [3][1]f64; -Matrix3x2f64 :: distinct [3][2]f64; -Matrix3x3f64 :: distinct [3][3]f64; -Matrix3x4f64 :: distinct [3][4]f64; - -Matrix4x1f64 :: distinct [4][1]f64; -Matrix4x2f64 :: distinct [4][2]f64; -Matrix4x3f64 :: distinct [4][3]f64; -Matrix4x4f64 :: distinct [4][4]f64; - -Matrix1f64 :: Matrix1x1f64; -Matrix2f64 :: Matrix2x2f64; -Matrix3f64 :: Matrix3x3f64; -Matrix4f64 :: Matrix4x4f64; - -Quaternionf16 :: distinct quaternion64; -Quaternionf32 :: distinct quaternion128; -Quaternionf64 :: distinct quaternion256; - -MATRIX1F16_IDENTITY :: Matrix1f16{{1}}; -MATRIX2F16_IDENTITY :: Matrix2f16{{1, 0}, {0, 1}}; -MATRIX3F16_IDENTITY :: Matrix3f16{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; -MATRIX4F16_IDENTITY :: Matrix4f16{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; - -MATRIX1F32_IDENTITY :: Matrix1f32{{1}}; -MATRIX2F32_IDENTITY :: Matrix2f32{{1, 0}, {0, 1}}; -MATRIX3F32_IDENTITY :: Matrix3f32{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; -MATRIX4F32_IDENTITY :: Matrix4f32{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; - -MATRIX1F64_IDENTITY :: Matrix1f64{{1}}; -MATRIX2F64_IDENTITY :: Matrix2f64{{1, 0}, {0, 1}}; -MATRIX3F64_IDENTITY :: Matrix3f64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; -MATRIX4F64_IDENTITY :: Matrix4f64{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}; - -QUATERNIONF16_IDENTITY :: Quaternionf16(1); -QUATERNIONF32_IDENTITY :: Quaternionf32(1); -QUATERNIONF64_IDENTITY :: Quaternionf64(1); - -VECTOR3F16_X_AXIS :: Vector3f16{1, 0, 0}; -VECTOR3F16_Y_AXIS :: Vector3f16{0, 1, 0}; -VECTOR3F16_Z_AXIS :: Vector3f16{0, 0, 1}; - -VECTOR3F32_X_AXIS :: Vector3f32{1, 0, 0}; -VECTOR3F32_Y_AXIS :: Vector3f32{0, 1, 0}; -VECTOR3F32_Z_AXIS :: Vector3f32{0, 0, 1}; - -VECTOR3F64_X_AXIS :: Vector3f64{1, 0, 0}; -VECTOR3F64_Y_AXIS :: Vector3f64{0, 1, 0}; -VECTOR3F64_Z_AXIS :: Vector3f64{0, 0, 1}; +F16_EPSILON :: 1e-3 +F32_EPSILON :: 1e-7 +F64_EPSILON :: 1e-15 + +Vector2f16 :: distinct [2]f16 +Vector3f16 :: distinct [3]f16 +Vector4f16 :: distinct [4]f16 + +Matrix1x1f16 :: distinct [1][1]f16 +Matrix1x2f16 :: distinct [1][2]f16 +Matrix1x3f16 :: distinct [1][3]f16 +Matrix1x4f16 :: distinct [1][4]f16 + +Matrix2x1f16 :: distinct [2][1]f16 +Matrix2x2f16 :: distinct [2][2]f16 +Matrix2x3f16 :: distinct [2][3]f16 +Matrix2x4f16 :: distinct [2][4]f16 + +Matrix3x1f16 :: distinct [3][1]f16 +Matrix3x2f16 :: distinct [3][2]f16 +Matrix3x3f16 :: distinct [3][3]f16 +Matrix3x4f16 :: distinct [3][4]f16 + +Matrix4x1f16 :: distinct [4][1]f16 +Matrix4x2f16 :: distinct [4][2]f16 +Matrix4x3f16 :: distinct [4][3]f16 +Matrix4x4f16 :: distinct [4][4]f16 + +Matrix1f16 :: Matrix1x1f16 +Matrix2f16 :: Matrix2x2f16 +Matrix3f16 :: Matrix3x3f16 +Matrix4f16 :: Matrix4x4f16 + +Vector2f32 :: distinct [2]f32 +Vector3f32 :: distinct [3]f32 +Vector4f32 :: distinct [4]f32 + +Matrix1x1f32 :: distinct [1][1]f32 +Matrix1x2f32 :: distinct [1][2]f32 +Matrix1x3f32 :: distinct [1][3]f32 +Matrix1x4f32 :: distinct [1][4]f32 + +Matrix2x1f32 :: distinct [2][1]f32 +Matrix2x2f32 :: distinct [2][2]f32 +Matrix2x3f32 :: distinct [2][3]f32 +Matrix2x4f32 :: distinct [2][4]f32 + +Matrix3x1f32 :: distinct [3][1]f32 +Matrix3x2f32 :: distinct [3][2]f32 +Matrix3x3f32 :: distinct [3][3]f32 +Matrix3x4f32 :: distinct [3][4]f32 + +Matrix4x1f32 :: distinct [4][1]f32 +Matrix4x2f32 :: distinct [4][2]f32 +Matrix4x3f32 :: distinct [4][3]f32 +Matrix4x4f32 :: distinct [4][4]f32 + +Matrix1f32 :: Matrix1x1f32 +Matrix2f32 :: Matrix2x2f32 +Matrix3f32 :: Matrix3x3f32 +Matrix4f32 :: Matrix4x4f32 + +Vector2f64 :: distinct [2]f64 +Vector3f64 :: distinct [3]f64 +Vector4f64 :: distinct [4]f64 + +Matrix1x1f64 :: distinct [1][1]f64 +Matrix1x2f64 :: distinct [1][2]f64 +Matrix1x3f64 :: distinct [1][3]f64 +Matrix1x4f64 :: distinct [1][4]f64 + +Matrix2x1f64 :: distinct [2][1]f64 +Matrix2x2f64 :: distinct [2][2]f64 +Matrix2x3f64 :: distinct [2][3]f64 +Matrix2x4f64 :: distinct [2][4]f64 + +Matrix3x1f64 :: distinct [3][1]f64 +Matrix3x2f64 :: distinct [3][2]f64 +Matrix3x3f64 :: distinct [3][3]f64 +Matrix3x4f64 :: distinct [3][4]f64 + +Matrix4x1f64 :: distinct [4][1]f64 +Matrix4x2f64 :: distinct [4][2]f64 +Matrix4x3f64 :: distinct [4][3]f64 +Matrix4x4f64 :: distinct [4][4]f64 + +Matrix1f64 :: Matrix1x1f64 +Matrix2f64 :: Matrix2x2f64 +Matrix3f64 :: Matrix3x3f64 +Matrix4f64 :: Matrix4x4f64 + +Quaternionf16 :: distinct quaternion64 +Quaternionf32 :: distinct quaternion128 +Quaternionf64 :: distinct quaternion256 + +MATRIX1F16_IDENTITY :: Matrix1f16{{1}} +MATRIX2F16_IDENTITY :: Matrix2f16{{1, 0}, {0, 1}} +MATRIX3F16_IDENTITY :: Matrix3f16{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} +MATRIX4F16_IDENTITY :: Matrix4f16{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}} + +MATRIX1F32_IDENTITY :: Matrix1f32{{1}} +MATRIX2F32_IDENTITY :: Matrix2f32{{1, 0}, {0, 1}} +MATRIX3F32_IDENTITY :: Matrix3f32{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} +MATRIX4F32_IDENTITY :: Matrix4f32{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}} + +MATRIX1F64_IDENTITY :: Matrix1f64{{1}} +MATRIX2F64_IDENTITY :: Matrix2f64{{1, 0}, {0, 1}} +MATRIX3F64_IDENTITY :: Matrix3f64{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}} +MATRIX4F64_IDENTITY :: Matrix4f64{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}} + +QUATERNIONF16_IDENTITY :: Quaternionf16(1) +QUATERNIONF32_IDENTITY :: Quaternionf32(1) +QUATERNIONF64_IDENTITY :: Quaternionf64(1) + +VECTOR3F16_X_AXIS :: Vector3f16{1, 0, 0} +VECTOR3F16_Y_AXIS :: Vector3f16{0, 1, 0} +VECTOR3F16_Z_AXIS :: Vector3f16{0, 0, 1} + +VECTOR3F32_X_AXIS :: Vector3f32{1, 0, 0} +VECTOR3F32_Y_AXIS :: Vector3f32{0, 1, 0} +VECTOR3F32_Z_AXIS :: Vector3f32{0, 0, 1} + +VECTOR3F64_X_AXIS :: Vector3f64{1, 0, 0} +VECTOR3F64_Y_AXIS :: Vector3f64{0, 1, 0} +VECTOR3F64_Z_AXIS :: Vector3f64{0, 0, 1} vector2_orthogonal :: proc(v: $V/[2]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) { - return {-v.y, v.x}; + return {-v.y, v.x} } vector3_orthogonal :: proc(v: $V/[3]$E) -> V where !IS_ARRAY(E), IS_FLOAT(E) { - x := abs(v.x); - y := abs(v.y); - z := abs(v.z); + x := abs(v.x) + y := abs(v.y) + z := abs(v.z) - other: V; + other: V if x < y { if x < z { - other = {1, 0, 0}; + other = {1, 0, 0} } else { - other = {0, 0, 1}; + other = {0, 0, 1} } } else { if y < z { - other = {0, 1, 0}; + other = {0, 1, 0} } else { - other = {0, 0, 1}; + other = {0, 0, 1} } } - return normalize(cross(v, other)); + return normalize(cross(v, other)) } -orthogonal :: proc{vector2_orthogonal, vector3_orthogonal}; +orthogonal :: proc{vector2_orthogonal, vector3_orthogonal} vector4_srgb_to_linear_f16 :: proc(col: Vector4f16) -> Vector4f16 { - r := math.pow(col.x, 2.2); - g := math.pow(col.y, 2.2); - b := math.pow(col.z, 2.2); - a := col.w; - return {r, g, b, a}; + r := math.pow(col.x, 2.2) + g := math.pow(col.y, 2.2) + b := math.pow(col.z, 2.2) + a := col.w + return {r, g, b, a} } vector4_srgb_to_linear_f32 :: proc(col: Vector4f32) -> Vector4f32 { - r := math.pow(col.x, 2.2); - g := math.pow(col.y, 2.2); - b := math.pow(col.z, 2.2); - a := col.w; - return {r, g, b, a}; + r := math.pow(col.x, 2.2) + g := math.pow(col.y, 2.2) + b := math.pow(col.z, 2.2) + a := col.w + return {r, g, b, a} } vector4_srgb_to_linear_f64 :: proc(col: Vector4f64) -> Vector4f64 { - r := math.pow(col.x, 2.2); - g := math.pow(col.y, 2.2); - b := math.pow(col.z, 2.2); - a := col.w; - return {r, g, b, a}; + r := math.pow(col.x, 2.2) + g := math.pow(col.y, 2.2) + b := math.pow(col.z, 2.2) + a := col.w + return {r, g, b, a} } vector4_srgb_to_linear :: proc{ vector4_srgb_to_linear_f16, vector4_srgb_to_linear_f32, vector4_srgb_to_linear_f64, -}; +} vector4_linear_to_srgb_f16 :: proc(col: Vector4f16) -> Vector4f16 { - a :: 2.51; - b :: 0.03; - c :: 2.43; - d :: 0.59; - e :: 0.14; + a :: 2.51 + b :: 0.03 + c :: 2.43 + d :: 0.59 + e :: 0.14 - x := col.x; - y := col.y; - z := col.z; + x := col.x + y := col.y + z := col.z - x = (x * (a * x + b)) / (x * (c * x + d) + e); - y = (y * (a * y + b)) / (y * (c * y + d) + e); - z = (z * (a * z + b)) / (z * (c * z + d) + e); + x = (x * (a * x + b)) / (x * (c * x + d) + e) + y = (y * (a * y + b)) / (y * (c * y + d) + e) + z = (z * (a * z + b)) / (z * (c * z + d) + e) - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2); - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2); - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2); + x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) + y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) + z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) - return {x, y, z, col.w}; + return {x, y, z, col.w} } vector4_linear_to_srgb_f32 :: proc(col: Vector4f32) -> Vector4f32 { - a :: 2.51; - b :: 0.03; - c :: 2.43; - d :: 0.59; - e :: 0.14; + a :: 2.51 + b :: 0.03 + c :: 2.43 + d :: 0.59 + e :: 0.14 - x := col.x; - y := col.y; - z := col.z; + x := col.x + y := col.y + z := col.z - x = (x * (a * x + b)) / (x * (c * x + d) + e); - y = (y * (a * y + b)) / (y * (c * y + d) + e); - z = (z * (a * z + b)) / (z * (c * z + d) + e); + x = (x * (a * x + b)) / (x * (c * x + d) + e) + y = (y * (a * y + b)) / (y * (c * y + d) + e) + z = (z * (a * z + b)) / (z * (c * z + d) + e) - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2); - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2); - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2); + x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) + y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) + z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) - return {x, y, z, col.w}; + return {x, y, z, col.w} } vector4_linear_to_srgb_f64 :: proc(col: Vector4f64) -> Vector4f64 { - a :: 2.51; - b :: 0.03; - c :: 2.43; - d :: 0.59; - e :: 0.14; + a :: 2.51 + b :: 0.03 + c :: 2.43 + d :: 0.59 + e :: 0.14 - x := col.x; - y := col.y; - z := col.z; + x := col.x + y := col.y + z := col.z - x = (x * (a * x + b)) / (x * (c * x + d) + e); - y = (y * (a * y + b)) / (y * (c * y + d) + e); - z = (z * (a * z + b)) / (z * (c * z + d) + e); + x = (x * (a * x + b)) / (x * (c * x + d) + e) + y = (y * (a * y + b)) / (y * (c * y + d) + e) + z = (z * (a * z + b)) / (z * (c * z + d) + e) - x = math.pow(clamp(x, 0, 1), 1.0 / 2.2); - y = math.pow(clamp(y, 0, 1), 1.0 / 2.2); - z = math.pow(clamp(z, 0, 1), 1.0 / 2.2); + x = math.pow(clamp(x, 0, 1), 1.0 / 2.2) + y = math.pow(clamp(y, 0, 1), 1.0 / 2.2) + z = math.pow(clamp(z, 0, 1), 1.0 / 2.2) - return {x, y, z, col.w}; + return {x, y, z, col.w} } vector4_linear_to_srgb :: proc{ vector4_linear_to_srgb_f16, vector4_linear_to_srgb_f32, vector4_linear_to_srgb_f64, -}; +} vector4_hsl_to_rgb_f16 :: proc(h, s, l: f16, a: f16 = 1) -> Vector4f16 { hue_to_rgb :: proc(p, q, t: f16) -> f16 { - t := t; + t := t if t < 0 { t += 1; } if t > 1 { t -= 1; } switch { - case t < 1.0/6.0: return p + (q - p) * 6.0 * t; - case t < 1.0/2.0: return q; - case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t); + case t < 1.0/6.0: return p + (q - p) * 6.0 * t + case t < 1.0/2.0: return q + case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t) } - return p; + return p } - r, g, b: f16; + r, g, b: f16 if s == 0 { - r = l; - g = l; - b = l; + r = l + g = l + b = l } else { - q := l * (1+s) if l < 0.5 else l+s - l*s; - p := 2*l - q; - r = hue_to_rgb(p, q, h + 1.0/3.0); - g = hue_to_rgb(p, q, h); - b = hue_to_rgb(p, q, h - 1.0/3.0); + q := l * (1+s) if l < 0.5 else l+s - l*s + p := 2*l - q + r = hue_to_rgb(p, q, h + 1.0/3.0) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1.0/3.0) } - return {r, g, b, a}; + return {r, g, b, a} } vector4_hsl_to_rgb_f32 :: proc(h, s, l: f32, a: f32 = 1) -> Vector4f32 { hue_to_rgb :: proc(p, q, t: f32) -> f32 { - t := t; + t := t if t < 0 { t += 1; } if t > 1 { t -= 1; } switch { - case t < 1.0/6.0: return p + (q - p) * 6.0 * t; - case t < 1.0/2.0: return q; - case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t); + case t < 1.0/6.0: return p + (q - p) * 6.0 * t + case t < 1.0/2.0: return q + case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t) } - return p; + return p } - r, g, b: f32; + r, g, b: f32 if s == 0 { - r = l; - g = l; - b = l; + r = l + g = l + b = l } else { - q := l * (1+s) if l < 0.5 else l+s - l*s; - p := 2*l - q; - r = hue_to_rgb(p, q, h + 1.0/3.0); - g = hue_to_rgb(p, q, h); - b = hue_to_rgb(p, q, h - 1.0/3.0); + q := l * (1+s) if l < 0.5 else l+s - l*s + p := 2*l - q + r = hue_to_rgb(p, q, h + 1.0/3.0) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1.0/3.0) } - return {r, g, b, a}; + return {r, g, b, a} } vector4_hsl_to_rgb_f64 :: proc(h, s, l: f64, a: f64 = 1) -> Vector4f64 { hue_to_rgb :: proc(p, q, t: f64) -> f64 { - t := t; + t := t if t < 0 { t += 1; } if t > 1 { t -= 1; } switch { - case t < 1.0/6.0: return p + (q - p) * 6.0 * t; - case t < 1.0/2.0: return q; - case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t); + case t < 1.0/6.0: return p + (q - p) * 6.0 * t + case t < 1.0/2.0: return q + case t < 2.0/3.0: return p + (q - p) * 6.0 * (2.0/3.0 - t) } - return p; + return p } - r, g, b: f64; + r, g, b: f64 if s == 0 { - r = l; - g = l; - b = l; + r = l + g = l + b = l } else { - q := l * (1+s) if l < 0.5 else l+s - l*s; - p := 2*l - q; - r = hue_to_rgb(p, q, h + 1.0/3.0); - g = hue_to_rgb(p, q, h); - b = hue_to_rgb(p, q, h - 1.0/3.0); + q := l * (1+s) if l < 0.5 else l+s - l*s + p := 2*l - q + r = hue_to_rgb(p, q, h + 1.0/3.0) + g = hue_to_rgb(p, q, h) + b = hue_to_rgb(p, q, h - 1.0/3.0) } - return {r, g, b, a}; + return {r, g, b, a} } vector4_hsl_to_rgb :: proc{ vector4_hsl_to_rgb_f16, vector4_hsl_to_rgb_f32, vector4_hsl_to_rgb_f64, -}; +} vector4_rgb_to_hsl_f16 :: proc(col: Vector4f16) -> Vector4f16 { - r := col.x; - g := col.y; - b := col.z; - a := col.w; - v_min := min(r, g, b); - v_max := max(r, g, b); - h, s, l: f16; - h = 0.0; - s = 0.0; - l = (v_min + v_max) * 0.5; + r := col.x + g := col.y + b := col.z + a := col.w + v_min := min(r, g, b) + v_max := max(r, g, b) + h, s, l: f16 + h = 0.0 + s = 0.0 + l = (v_min + v_max) * 0.5 if v_max != v_min { - d: = v_max - v_min; - s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min); + d: = v_max - v_min + s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min) switch { case v_max == r: - h = (g - b) / d + (6.0 if g < b else 0.0); + h = (g - b) / d + (6.0 if g < b else 0.0) case v_max == g: - h = (b - r) / d + 2.0; + h = (b - r) / d + 2.0 case v_max == b: - h = (r - g) / d + 4.0; + h = (r - g) / d + 4.0 } - h *= 1.0/6.0; + h *= 1.0/6.0 } - return {h, s, l, a}; + return {h, s, l, a} } vector4_rgb_to_hsl_f32 :: proc(col: Vector4f32) -> Vector4f32 { - r := col.x; - g := col.y; - b := col.z; - a := col.w; - v_min := min(r, g, b); - v_max := max(r, g, b); - h, s, l: f32; - h = 0.0; - s = 0.0; - l = (v_min + v_max) * 0.5; + r := col.x + g := col.y + b := col.z + a := col.w + v_min := min(r, g, b) + v_max := max(r, g, b) + h, s, l: f32 + h = 0.0 + s = 0.0 + l = (v_min + v_max) * 0.5 if v_max != v_min { - d: = v_max - v_min; - s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min); + d: = v_max - v_min + s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min) switch { case v_max == r: - h = (g - b) / d + (6.0 if g < b else 0.0); + h = (g - b) / d + (6.0 if g < b else 0.0) case v_max == g: - h = (b - r) / d + 2.0; + h = (b - r) / d + 2.0 case v_max == b: - h = (r - g) / d + 4.0; + h = (r - g) / d + 4.0 } - h *= 1.0/6.0; + h *= 1.0/6.0 } - return {h, s, l, a}; + return {h, s, l, a} } vector4_rgb_to_hsl_f64 :: proc(col: Vector4f64) -> Vector4f64 { - r := col.x; - g := col.y; - b := col.z; - a := col.w; - v_min := min(r, g, b); - v_max := max(r, g, b); - h, s, l: f64; - h = 0.0; - s = 0.0; - l = (v_min + v_max) * 0.5; + r := col.x + g := col.y + b := col.z + a := col.w + v_min := min(r, g, b) + v_max := max(r, g, b) + h, s, l: f64 + h = 0.0 + s = 0.0 + l = (v_min + v_max) * 0.5 if v_max != v_min { - d: = v_max - v_min; - s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min); + d: = v_max - v_min + s = d / (2.0 - v_max - v_min) if l > 0.5 else d / (v_max + v_min) switch { case v_max == r: - h = (g - b) / d + (6.0 if g < b else 0.0); + h = (g - b) / d + (6.0 if g < b else 0.0) case v_max == g: - h = (b - r) / d + 2.0; + h = (b - r) / d + 2.0 case v_max == b: - h = (r - g) / d + 4.0; + h = (r - g) / d + 4.0 } - h *= 1.0/6.0; + h *= 1.0/6.0 } - return {h, s, l, a}; + return {h, s, l, a} } vector4_rgb_to_hsl :: proc{ vector4_rgb_to_hsl_f16, vector4_rgb_to_hsl_f32, vector4_rgb_to_hsl_f64, -}; +} quaternion_angle_axis_f16 :: proc(angle_radians: f16, axis: Vector3f16) -> (q: Quaternionf16) { - t := angle_radians*0.5; - v := normalize(axis) * math.sin(t); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = math.cos(t); - return; + t := angle_radians*0.5 + v := normalize(axis) * math.sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = math.cos(t) + return } quaternion_angle_axis_f32 :: proc(angle_radians: f32, axis: Vector3f32) -> (q: Quaternionf32) { - t := angle_radians*0.5; - v := normalize(axis) * math.sin(t); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = math.cos(t); - return; + t := angle_radians*0.5 + v := normalize(axis) * math.sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = math.cos(t) + return } quaternion_angle_axis_f64 :: proc(angle_radians: f64, axis: Vector3f64) -> (q: Quaternionf64) { - t := angle_radians*0.5; - v := normalize(axis) * math.sin(t); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = math.cos(t); - return; + t := angle_radians*0.5 + v := normalize(axis) * math.sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = math.cos(t) + return } quaternion_angle_axis :: proc{ quaternion_angle_axis_f16, quaternion_angle_axis_f32, quaternion_angle_axis_f64, -}; +} angle_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2; + return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 } - return math.cos(q.x) * 2; + return math.cos(q.x) * 2 } angle_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2; + return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 } - return math.cos(q.x) * 2; + return math.cos(q.x) * 2 } angle_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { if abs(q.w) > math.SQRT_THREE*0.5 { - return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2; + return math.asin(q.x*q.x + q.y*q.y + q.z*q.z) * 2 } - return math.cos(q.x) * 2; + return math.cos(q.x) * 2 } angle_from_quaternion :: proc{ angle_from_quaternion_f16, angle_from_quaternion_f32, angle_from_quaternion_f64, -}; +} axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> Vector3f16 { - t1 := 1 - q.w*q.w; + t1 := 1 - q.w*q.w if t1 < 0 { - return {0, 0, 1}; + return {0, 0, 1} } - t2 := 1.0 / math.sqrt(t1); - return {q.x*t2, q.y*t2, q.z*t2}; + t2 := 1.0 / math.sqrt(t1) + return {q.x*t2, q.y*t2, q.z*t2} } axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> Vector3f32 { - t1 := 1 - q.w*q.w; + t1 := 1 - q.w*q.w if t1 < 0 { - return {0, 0, 1}; + return {0, 0, 1} } - t2 := 1.0 / math.sqrt(t1); - return {q.x*t2, q.y*t2, q.z*t2}; + t2 := 1.0 / math.sqrt(t1) + return {q.x*t2, q.y*t2, q.z*t2} } axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> Vector3f64 { - t1 := 1 - q.w*q.w; + t1 := 1 - q.w*q.w if t1 < 0 { - return {0, 0, 1}; + return {0, 0, 1} } - t2 := 1.0 / math.sqrt(t1); - return {q.x*t2, q.y*t2, q.z*t2}; + t2 := 1.0 / math.sqrt(t1) + return {q.x*t2, q.y*t2, q.z*t2} } axis_from_quaternion :: proc{ axis_from_quaternion_f16, axis_from_quaternion_f32, axis_from_quaternion_f64, -}; +} angle_axis_from_quaternion_f16 :: proc(q: Quaternionf16) -> (angle: f16, axis: Vector3f16) { - angle = angle_from_quaternion(q); - axis = axis_from_quaternion(q); - return; + angle = angle_from_quaternion(q) + axis = axis_from_quaternion(q) + return } angle_axis_from_quaternion_f32 :: proc(q: Quaternionf32) -> (angle: f32, axis: Vector3f32) { - angle = angle_from_quaternion(q); - axis = axis_from_quaternion(q); - return; + angle = angle_from_quaternion(q) + axis = axis_from_quaternion(q) + return } angle_axis_from_quaternion_f64 :: proc(q: Quaternionf64) -> (angle: f64, axis: Vector3f64) { - angle = angle_from_quaternion(q); - axis = axis_from_quaternion(q); - return; + angle = angle_from_quaternion(q) + axis = axis_from_quaternion(q) + return } angle_axis_from_quaternion :: proc { angle_axis_from_quaternion_f16, angle_axis_from_quaternion_f32, angle_axis_from_quaternion_f64, -}; +} quaternion_from_forward_and_up_f16 :: proc(forward, up: Vector3f16) -> Quaternionf16 { - f := normalize(forward); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(forward) + s := normalize(cross(f, up)) + u := cross(s, f) m := Matrix3f16{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } - tr := trace(m); + tr := trace(m) - q: Quaternionf16; + q: Quaternionf16 switch { case tr > 0: - S := 2 * math.sqrt(1 + tr); - q.w = 0.25 * S; - q.x = (m[2][1] - m[1][2]) / S; - q.y = (m[0][2] - m[2][0]) / S; - q.z = (m[1][0] - m[0][1]) / S; + S := 2 * math.sqrt(1 + tr) + q.w = 0.25 * S + q.x = (m[2][1] - m[1][2]) / S + q.y = (m[0][2] - m[2][0]) / S + q.z = (m[1][0] - m[0][1]) / S case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]): - S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]); - q.w = (m[2][1] - m[1][2]) / S; - q.x = 0.25 * S; - q.y = (m[0][1] + m[1][0]) / S; - q.z = (m[0][2] + m[2][0]) / S; + S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]) + q.w = (m[2][1] - m[1][2]) / S + q.x = 0.25 * S + q.y = (m[0][1] + m[1][0]) / S + q.z = (m[0][2] + m[2][0]) / S case m[1][1] > m[2][2]: - S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]); - q.w = (m[0][2] - m[2][0]) / S; - q.x = (m[0][1] + m[1][0]) / S; - q.y = 0.25 * S; - q.z = (m[1][2] + m[2][1]) / S; + S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]) + q.w = (m[0][2] - m[2][0]) / S + q.x = (m[0][1] + m[1][0]) / S + q.y = 0.25 * S + q.z = (m[1][2] + m[2][1]) / S case: - S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]); - q.w = (m[1][0] - m[0][1]) / S; - q.x = (m[0][2] - m[2][0]) / S; - q.y = (m[1][2] + m[2][1]) / S; - q.z = 0.25 * S; + S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]) + q.w = (m[1][0] - m[0][1]) / S + q.x = (m[0][2] - m[2][0]) / S + q.y = (m[1][2] + m[2][1]) / S + q.z = 0.25 * S } - return normalize(q); + return normalize(q) } quaternion_from_forward_and_up_f32 :: proc(forward, up: Vector3f32) -> Quaternionf32 { - f := normalize(forward); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(forward) + s := normalize(cross(f, up)) + u := cross(s, f) m := Matrix3f32{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } - tr := trace(m); + tr := trace(m) - q: Quaternionf32; + q: Quaternionf32 switch { case tr > 0: - S := 2 * math.sqrt(1 + tr); - q.w = 0.25 * S; - q.x = (m[2][1] - m[1][2]) / S; - q.y = (m[0][2] - m[2][0]) / S; - q.z = (m[1][0] - m[0][1]) / S; + S := 2 * math.sqrt(1 + tr) + q.w = 0.25 * S + q.x = (m[2][1] - m[1][2]) / S + q.y = (m[0][2] - m[2][0]) / S + q.z = (m[1][0] - m[0][1]) / S case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]): - S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]); - q.w = (m[2][1] - m[1][2]) / S; - q.x = 0.25 * S; - q.y = (m[0][1] + m[1][0]) / S; - q.z = (m[0][2] + m[2][0]) / S; + S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]) + q.w = (m[2][1] - m[1][2]) / S + q.x = 0.25 * S + q.y = (m[0][1] + m[1][0]) / S + q.z = (m[0][2] + m[2][0]) / S case m[1][1] > m[2][2]: - S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]); - q.w = (m[0][2] - m[2][0]) / S; - q.x = (m[0][1] + m[1][0]) / S; - q.y = 0.25 * S; - q.z = (m[1][2] + m[2][1]) / S; + S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]) + q.w = (m[0][2] - m[2][0]) / S + q.x = (m[0][1] + m[1][0]) / S + q.y = 0.25 * S + q.z = (m[1][2] + m[2][1]) / S case: - S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]); - q.w = (m[1][0] - m[0][1]) / S; - q.x = (m[0][2] - m[2][0]) / S; - q.y = (m[1][2] + m[2][1]) / S; - q.z = 0.25 * S; + S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]) + q.w = (m[1][0] - m[0][1]) / S + q.x = (m[0][2] - m[2][0]) / S + q.y = (m[1][2] + m[2][1]) / S + q.z = 0.25 * S } - return normalize(q); + return normalize(q) } quaternion_from_forward_and_up_f64 :: proc(forward, up: Vector3f64) -> Quaternionf64 { - f := normalize(forward); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(forward) + s := normalize(cross(f, up)) + u := cross(s, f) m := Matrix3f64{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } - tr := trace(m); + tr := trace(m) - q: Quaternionf64; + q: Quaternionf64 switch { case tr > 0: - S := 2 * math.sqrt(1 + tr); - q.w = 0.25 * S; - q.x = (m[2][1] - m[1][2]) / S; - q.y = (m[0][2] - m[2][0]) / S; - q.z = (m[1][0] - m[0][1]) / S; + S := 2 * math.sqrt(1 + tr) + q.w = 0.25 * S + q.x = (m[2][1] - m[1][2]) / S + q.y = (m[0][2] - m[2][0]) / S + q.z = (m[1][0] - m[0][1]) / S case (m[0][0] > m[1][1]) && (m[0][0] > m[2][2]): - S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]); - q.w = (m[2][1] - m[1][2]) / S; - q.x = 0.25 * S; - q.y = (m[0][1] + m[1][0]) / S; - q.z = (m[0][2] + m[2][0]) / S; + S := 2 * math.sqrt(1 + m[0][0] - m[1][1] - m[2][2]) + q.w = (m[2][1] - m[1][2]) / S + q.x = 0.25 * S + q.y = (m[0][1] + m[1][0]) / S + q.z = (m[0][2] + m[2][0]) / S case m[1][1] > m[2][2]: - S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]); - q.w = (m[0][2] - m[2][0]) / S; - q.x = (m[0][1] + m[1][0]) / S; - q.y = 0.25 * S; - q.z = (m[1][2] + m[2][1]) / S; + S := 2 * math.sqrt(1 + m[1][1] - m[0][0] - m[2][2]) + q.w = (m[0][2] - m[2][0]) / S + q.x = (m[0][1] + m[1][0]) / S + q.y = 0.25 * S + q.z = (m[1][2] + m[2][1]) / S case: - S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]); - q.w = (m[1][0] - m[0][1]) / S; - q.x = (m[0][2] - m[2][0]) / S; - q.y = (m[1][2] + m[2][1]) / S; - q.z = 0.25 * S; + S := 2 * math.sqrt(1 + m[2][2] - m[0][0] - m[1][1]) + q.w = (m[1][0] - m[0][1]) / S + q.x = (m[0][2] - m[2][0]) / S + q.y = (m[1][2] + m[2][1]) / S + q.z = 0.25 * S } - return normalize(q); + return normalize(q) } quaternion_from_forward_and_up :: proc{ quaternion_from_forward_and_up_f16, quaternion_from_forward_and_up_f32, quaternion_from_forward_and_up_f64, -}; +} quaternion_look_at_f16 :: proc(eye, centre: Vector3f16, up: Vector3f16) -> Quaternionf16 { - return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)); + return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)) } quaternion_look_at_f32 :: proc(eye, centre: Vector3f32, up: Vector3f32) -> Quaternionf32 { - return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)); + return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)) } quaternion_look_at_f64 :: proc(eye, centre: Vector3f64, up: Vector3f64) -> Quaternionf64 { - return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)); + return quaternion_from_matrix3(matrix3_look_at(eye, centre, up)) } quaternion_look_at :: proc{ quaternion_look_at_f16, quaternion_look_at_f32, quaternion_look_at_f64, -}; +} quaternion_nlerp_f16 :: proc(a, b: Quaternionf16, t: f16) -> (c: Quaternionf16) { - c.x = a.x + (b.x-a.x)*t; - c.y = a.y + (b.y-a.y)*t; - c.z = a.z + (b.z-a.z)*t; - c.w = a.w + (b.w-a.w)*t; - return normalize(c); + c.x = a.x + (b.x-a.x)*t + c.y = a.y + (b.y-a.y)*t + c.z = a.z + (b.z-a.z)*t + c.w = a.w + (b.w-a.w)*t + return normalize(c) } quaternion_nlerp_f32 :: proc(a, b: Quaternionf32, t: f32) -> (c: Quaternionf32) { - c.x = a.x + (b.x-a.x)*t; - c.y = a.y + (b.y-a.y)*t; - c.z = a.z + (b.z-a.z)*t; - c.w = a.w + (b.w-a.w)*t; - return normalize(c); + c.x = a.x + (b.x-a.x)*t + c.y = a.y + (b.y-a.y)*t + c.z = a.z + (b.z-a.z)*t + c.w = a.w + (b.w-a.w)*t + return normalize(c) } quaternion_nlerp_f64 :: proc(a, b: Quaternionf64, t: f64) -> (c: Quaternionf64) { - c.x = a.x + (b.x-a.x)*t; - c.y = a.y + (b.y-a.y)*t; - c.z = a.z + (b.z-a.z)*t; - c.w = a.w + (b.w-a.w)*t; - return normalize(c); + c.x = a.x + (b.x-a.x)*t + c.y = a.y + (b.y-a.y)*t + c.z = a.z + (b.z-a.z)*t + c.w = a.w + (b.w-a.w)*t + return normalize(c) } quaternion_nlerp :: proc{ quaternion_nlerp_f16, quaternion_nlerp_f32, quaternion_nlerp_f64, -}; +} quaternion_slerp_f16 :: proc(x, y: Quaternionf16, t: f16) -> (q: Quaternionf16) { - a, b := x, y; - cos_angle := dot(a, b); + a, b := x, y + cos_angle := dot(a, b) if cos_angle < 0 { - b = -b; - cos_angle = -cos_angle; + b = -b + cos_angle = -cos_angle } if cos_angle > 1 - F32_EPSILON { - q.x = a.x + (b.x-a.x)*t; - q.y = a.y + (b.y-a.y)*t; - q.z = a.z + (b.z-a.z)*t; - q.w = a.w + (b.w-a.w)*t; - return; + q.x = a.x + (b.x-a.x)*t + q.y = a.y + (b.y-a.y)*t + q.z = a.z + (b.z-a.z)*t + q.w = a.w + (b.w-a.w)*t + return } - angle := math.acos(cos_angle); - sin_angle := math.sin(angle); - factor_a := math.sin((1-t) * angle) / sin_angle; - factor_b := math.sin(t * angle) / sin_angle; + angle := math.acos(cos_angle) + sin_angle := math.sin(angle) + factor_a := math.sin((1-t) * angle) / sin_angle + factor_b := math.sin(t * angle) / sin_angle - q.x = factor_a * a.x + factor_b * b.x; - q.y = factor_a * a.y + factor_b * b.y; - q.z = factor_a * a.z + factor_b * b.z; - q.w = factor_a * a.w + factor_b * b.w; - return; + q.x = factor_a * a.x + factor_b * b.x + q.y = factor_a * a.y + factor_b * b.y + q.z = factor_a * a.z + factor_b * b.z + q.w = factor_a * a.w + factor_b * b.w + return } quaternion_slerp_f32 :: proc(x, y: Quaternionf32, t: f32) -> (q: Quaternionf32) { - a, b := x, y; - cos_angle := dot(a, b); + a, b := x, y + cos_angle := dot(a, b) if cos_angle < 0 { - b = -b; - cos_angle = -cos_angle; + b = -b + cos_angle = -cos_angle } if cos_angle > 1 - F32_EPSILON { - q.x = a.x + (b.x-a.x)*t; - q.y = a.y + (b.y-a.y)*t; - q.z = a.z + (b.z-a.z)*t; - q.w = a.w + (b.w-a.w)*t; - return; + q.x = a.x + (b.x-a.x)*t + q.y = a.y + (b.y-a.y)*t + q.z = a.z + (b.z-a.z)*t + q.w = a.w + (b.w-a.w)*t + return } - angle := math.acos(cos_angle); - sin_angle := math.sin(angle); - factor_a := math.sin((1-t) * angle) / sin_angle; - factor_b := math.sin(t * angle) / sin_angle; + angle := math.acos(cos_angle) + sin_angle := math.sin(angle) + factor_a := math.sin((1-t) * angle) / sin_angle + factor_b := math.sin(t * angle) / sin_angle - q.x = factor_a * a.x + factor_b * b.x; - q.y = factor_a * a.y + factor_b * b.y; - q.z = factor_a * a.z + factor_b * b.z; - q.w = factor_a * a.w + factor_b * b.w; - return; + q.x = factor_a * a.x + factor_b * b.x + q.y = factor_a * a.y + factor_b * b.y + q.z = factor_a * a.z + factor_b * b.z + q.w = factor_a * a.w + factor_b * b.w + return } quaternion_slerp_f64 :: proc(x, y: Quaternionf64, t: f64) -> (q: Quaternionf64) { - a, b := x, y; - cos_angle := dot(a, b); + a, b := x, y + cos_angle := dot(a, b) if cos_angle < 0 { - b = -b; - cos_angle = -cos_angle; + b = -b + cos_angle = -cos_angle } if cos_angle > 1 - F64_EPSILON { - q.x = a.x + (b.x-a.x)*t; - q.y = a.y + (b.y-a.y)*t; - q.z = a.z + (b.z-a.z)*t; - q.w = a.w + (b.w-a.w)*t; - return; + q.x = a.x + (b.x-a.x)*t + q.y = a.y + (b.y-a.y)*t + q.z = a.z + (b.z-a.z)*t + q.w = a.w + (b.w-a.w)*t + return } - angle := math.acos(cos_angle); - sin_angle := math.sin(angle); - factor_a := math.sin((1-t) * angle) / sin_angle; - factor_b := math.sin(t * angle) / sin_angle; + angle := math.acos(cos_angle) + sin_angle := math.sin(angle) + factor_a := math.sin((1-t) * angle) / sin_angle + factor_b := math.sin(t * angle) / sin_angle - q.x = factor_a * a.x + factor_b * b.x; - q.y = factor_a * a.y + factor_b * b.y; - q.z = factor_a * a.z + factor_b * b.z; - q.w = factor_a * a.w + factor_b * b.w; - return; + q.x = factor_a * a.x + factor_b * b.x + q.y = factor_a * a.y + factor_b * b.y + q.z = factor_a * a.z + factor_b * b.z + q.w = factor_a * a.w + factor_b * b.w + return } quaternion_slerp :: proc{ quaternion_slerp_f16, quaternion_slerp_f32, quaternion_slerp_f64, -}; +} quaternion_squad_f16 :: proc(q1, q2, s1, s2: Quaternionf16, h: f16) -> Quaternionf16 { - slerp :: quaternion_slerp; - return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h); + slerp :: quaternion_slerp + return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h) } quaternion_squad_f32 :: proc(q1, q2, s1, s2: Quaternionf32, h: f32) -> Quaternionf32 { - slerp :: quaternion_slerp; - return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h); + slerp :: quaternion_slerp + return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h) } quaternion_squad_f64 :: proc(q1, q2, s1, s2: Quaternionf64, h: f64) -> Quaternionf64 { - slerp :: quaternion_slerp; - return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h); + slerp :: quaternion_slerp + return slerp(slerp(q1, q2, h), slerp(s1, s2, h), 2 * (1 - h) * h) } quaternion_squad :: proc{ quaternion_squad_f16, quaternion_squad_f32, quaternion_squad_f64, -}; +} quaternion_from_matrix4_f16 :: proc(m: Matrix4f16) -> (q: Quaternionf16) { - m3: Matrix3f16 = ---; - m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2]; - m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2]; - m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2]; - return quaternion_from_matrix3(m3); + m3: Matrix3f16 = --- + m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2] + m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2] + m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2] + return quaternion_from_matrix3(m3) } quaternion_from_matrix4_f32 :: proc(m: Matrix4f32) -> (q: Quaternionf32) { - m3: Matrix3f32 = ---; - m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2]; - m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2]; - m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2]; - return quaternion_from_matrix3(m3); + m3: Matrix3f32 = --- + m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2] + m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2] + m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2] + return quaternion_from_matrix3(m3) } quaternion_from_matrix4_f64 :: proc(m: Matrix4f64) -> (q: Quaternionf64) { - m3: Matrix3f64 = ---; - m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2]; - m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2]; - m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2]; - return quaternion_from_matrix3(m3); + m3: Matrix3f64 = --- + m3[0][0], m3[0][1], m3[0][2] = m[0][0], m[0][1], m[0][2] + m3[1][0], m3[1][1], m3[1][2] = m[1][0], m[1][1], m[1][2] + m3[2][0], m3[2][1], m3[2][2] = m[2][0], m[2][1], m[2][2] + return quaternion_from_matrix3(m3) } quaternion_from_matrix4 :: proc{ quaternion_from_matrix4_f16, quaternion_from_matrix4_f32, quaternion_from_matrix4_f64, -}; +} quaternion_from_matrix3_f16 :: proc(m: Matrix3f16) -> (q: Quaternionf16) { - four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2]; - four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2]; - four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1]; - four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2]; + four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2] + four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2] + four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1] + four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2] - biggest_index := 0; - four_biggest_squared_minus_1 := four_w_squared_minus_1; + biggest_index := 0 + four_biggest_squared_minus_1 := four_w_squared_minus_1 if four_x_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_x_squared_minus_1; - biggest_index = 1; + four_biggest_squared_minus_1 = four_x_squared_minus_1 + biggest_index = 1 } if four_y_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_y_squared_minus_1; - biggest_index = 2; + four_biggest_squared_minus_1 = four_y_squared_minus_1 + biggest_index = 2 } if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1; - biggest_index = 3; + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 } - biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5; - mult := 0.25 / biggest_val; + biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val - q = 1; + q = 1 switch biggest_index { case 0: - q.w = biggest_val; - q.x = (m[1][2] - m[2][1]) * mult; - q.y = (m[2][0] - m[0][2]) * mult; - q.z = (m[0][1] - m[1][0]) * mult; + q.w = biggest_val + q.x = (m[1][2] - m[2][1]) * mult + q.y = (m[2][0] - m[0][2]) * mult + q.z = (m[0][1] - m[1][0]) * mult case 1: - q.w = (m[1][2] - m[2][1]) * mult; - q.x = biggest_val; - q.y = (m[0][1] + m[1][0]) * mult; - q.z = (m[2][0] + m[0][2]) * mult; + q.w = (m[1][2] - m[2][1]) * mult + q.x = biggest_val + q.y = (m[0][1] + m[1][0]) * mult + q.z = (m[2][0] + m[0][2]) * mult case 2: - q.w = (m[2][0] - m[0][2]) * mult; - q.x = (m[0][1] + m[1][0]) * mult; - q.y = biggest_val; - q.z = (m[1][2] + m[2][1]) * mult; + q.w = (m[2][0] - m[0][2]) * mult + q.x = (m[0][1] + m[1][0]) * mult + q.y = biggest_val + q.z = (m[1][2] + m[2][1]) * mult case 3: - q.w = (m[0][1] - m[1][0]) * mult; - q.x = (m[2][0] + m[0][2]) * mult; - q.y = (m[1][2] + m[2][1]) * mult; - q.z = biggest_val; + q.w = (m[0][1] - m[1][0]) * mult + q.x = (m[2][0] + m[0][2]) * mult + q.y = (m[1][2] + m[2][1]) * mult + q.z = biggest_val } - return; + return } quaternion_from_matrix3_f32 :: proc(m: Matrix3f32) -> (q: Quaternionf32) { - four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2]; - four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2]; - four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1]; - four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2]; + four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2] + four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2] + four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1] + four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2] - biggest_index := 0; - four_biggest_squared_minus_1 := four_w_squared_minus_1; + biggest_index := 0 + four_biggest_squared_minus_1 := four_w_squared_minus_1 if four_x_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_x_squared_minus_1; - biggest_index = 1; + four_biggest_squared_minus_1 = four_x_squared_minus_1 + biggest_index = 1 } if four_y_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_y_squared_minus_1; - biggest_index = 2; + four_biggest_squared_minus_1 = four_y_squared_minus_1 + biggest_index = 2 } if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1; - biggest_index = 3; + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 } - biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5; - mult := 0.25 / biggest_val; + biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val - q = 1; + q = 1 switch biggest_index { case 0: - q.w = biggest_val; - q.x = (m[1][2] - m[2][1]) * mult; - q.y = (m[2][0] - m[0][2]) * mult; - q.z = (m[0][1] - m[1][0]) * mult; + q.w = biggest_val + q.x = (m[1][2] - m[2][1]) * mult + q.y = (m[2][0] - m[0][2]) * mult + q.z = (m[0][1] - m[1][0]) * mult case 1: - q.w = (m[1][2] - m[2][1]) * mult; - q.x = biggest_val; - q.y = (m[0][1] + m[1][0]) * mult; - q.z = (m[2][0] + m[0][2]) * mult; + q.w = (m[1][2] - m[2][1]) * mult + q.x = biggest_val + q.y = (m[0][1] + m[1][0]) * mult + q.z = (m[2][0] + m[0][2]) * mult case 2: - q.w = (m[2][0] - m[0][2]) * mult; - q.x = (m[0][1] + m[1][0]) * mult; - q.y = biggest_val; - q.z = (m[1][2] + m[2][1]) * mult; + q.w = (m[2][0] - m[0][2]) * mult + q.x = (m[0][1] + m[1][0]) * mult + q.y = biggest_val + q.z = (m[1][2] + m[2][1]) * mult case 3: - q.w = (m[0][1] - m[1][0]) * mult; - q.x = (m[2][0] + m[0][2]) * mult; - q.y = (m[1][2] + m[2][1]) * mult; - q.z = biggest_val; + q.w = (m[0][1] - m[1][0]) * mult + q.x = (m[2][0] + m[0][2]) * mult + q.y = (m[1][2] + m[2][1]) * mult + q.z = biggest_val } - return; + return } quaternion_from_matrix3_f64 :: proc(m: Matrix3f64) -> (q: Quaternionf64) { - four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2]; - four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2]; - four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1]; - four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2]; + four_x_squared_minus_1 := m[0][0] - m[1][1] - m[2][2] + four_y_squared_minus_1 := m[1][1] - m[0][0] - m[2][2] + four_z_squared_minus_1 := m[2][2] - m[0][0] - m[1][1] + four_w_squared_minus_1 := m[0][0] + m[1][1] + m[2][2] - biggest_index := 0; - four_biggest_squared_minus_1 := four_w_squared_minus_1; + biggest_index := 0 + four_biggest_squared_minus_1 := four_w_squared_minus_1 if four_x_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_x_squared_minus_1; - biggest_index = 1; + four_biggest_squared_minus_1 = four_x_squared_minus_1 + biggest_index = 1 } if four_y_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_y_squared_minus_1; - biggest_index = 2; + four_biggest_squared_minus_1 = four_y_squared_minus_1 + biggest_index = 2 } if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1; - biggest_index = 3; + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 } - biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5; - mult := 0.25 / biggest_val; + biggest_val := math.sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val - q = 1; + q = 1 switch biggest_index { case 0: - q.w = biggest_val; - q.x = (m[1][2] - m[2][1]) * mult; - q.y = (m[2][0] - m[0][2]) * mult; - q.z = (m[0][1] - m[1][0]) * mult; + q.w = biggest_val + q.x = (m[1][2] - m[2][1]) * mult + q.y = (m[2][0] - m[0][2]) * mult + q.z = (m[0][1] - m[1][0]) * mult case 1: - q.w = (m[1][2] - m[2][1]) * mult; - q.x = biggest_val; - q.y = (m[0][1] + m[1][0]) * mult; - q.z = (m[2][0] + m[0][2]) * mult; + q.w = (m[1][2] - m[2][1]) * mult + q.x = biggest_val + q.y = (m[0][1] + m[1][0]) * mult + q.z = (m[2][0] + m[0][2]) * mult case 2: - q.w = (m[2][0] - m[0][2]) * mult; - q.x = (m[0][1] + m[1][0]) * mult; - q.y = biggest_val; - q.z = (m[1][2] + m[2][1]) * mult; + q.w = (m[2][0] - m[0][2]) * mult + q.x = (m[0][1] + m[1][0]) * mult + q.y = biggest_val + q.z = (m[1][2] + m[2][1]) * mult case 3: - q.w = (m[0][1] - m[1][0]) * mult; - q.x = (m[2][0] + m[0][2]) * mult; - q.y = (m[1][2] + m[2][1]) * mult; - q.z = biggest_val; + q.w = (m[0][1] - m[1][0]) * mult + q.x = (m[2][0] + m[0][2]) * mult + q.y = (m[1][2] + m[2][1]) * mult + q.z = biggest_val } - return; + return } quaternion_from_matrix3 :: proc{ quaternion_from_matrix3_f16, quaternion_from_matrix3_f32, quaternion_from_matrix3_f64, -}; +} quaternion_between_two_vector3_f16 :: proc(from, to: Vector3f16) -> (q: Quaternionf16) { - x := normalize(from); - y := normalize(to); + x := normalize(from) + y := normalize(to) - cos_theta := dot(x, y); + cos_theta := dot(x, y) if abs(cos_theta + 1) < 2*F32_EPSILON { - v := vector3_orthogonal(x); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = 0; - return; - } - v := cross(x, y); - w := cos_theta + 1; - q.w = w; - q.x = v.x; - q.y = v.y; - q.z = v.z; - return normalize(q); + v := vector3_orthogonal(x) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = 0 + return + } + v := cross(x, y) + w := cos_theta + 1 + q.w = w + q.x = v.x + q.y = v.y + q.z = v.z + return normalize(q) } quaternion_between_two_vector3_f32 :: proc(from, to: Vector3f32) -> (q: Quaternionf32) { - x := normalize(from); - y := normalize(to); + x := normalize(from) + y := normalize(to) - cos_theta := dot(x, y); + cos_theta := dot(x, y) if abs(cos_theta + 1) < 2*F32_EPSILON { - v := vector3_orthogonal(x); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = 0; - return; - } - v := cross(x, y); - w := cos_theta + 1; - q.w = w; - q.x = v.x; - q.y = v.y; - q.z = v.z; - return normalize(q); + v := vector3_orthogonal(x) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = 0 + return + } + v := cross(x, y) + w := cos_theta + 1 + q.w = w + q.x = v.x + q.y = v.y + q.z = v.z + return normalize(q) } quaternion_between_two_vector3_f64 :: proc(from, to: Vector3f64) -> (q: Quaternionf64) { - x := normalize(from); - y := normalize(to); + x := normalize(from) + y := normalize(to) - cos_theta := dot(x, y); + cos_theta := dot(x, y) if abs(cos_theta + 1) < 2*F64_EPSILON { - v := vector3_orthogonal(x); - q.x = v.x; - q.y = v.y; - q.z = v.z; - q.w = 0; - return; - } - v := cross(x, y); - w := cos_theta + 1; - q.w = w; - q.x = v.x; - q.y = v.y; - q.z = v.z; - return normalize(q); + v := vector3_orthogonal(x) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = 0 + return + } + v := cross(x, y) + w := cos_theta + 1 + q.w = w + q.x = v.x + q.y = v.y + q.z = v.z + return normalize(q) } quaternion_between_two_vector3 :: proc{ quaternion_between_two_vector3_f16, quaternion_between_two_vector3_f32, quaternion_between_two_vector3_f64, -}; +} matrix2_inverse_transpose_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[0][1] = -m[0][1] * id; - c[1][0] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[0][1] = -m[0][1] * id + c[1][0] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_transpose_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[0][1] = -m[0][1] * id; - c[1][0] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[0][1] = -m[0][1] * id + c[1][0] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_transpose_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[0][1] = -m[0][1] * id; - c[1][0] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[0][1] = -m[0][1] * id + c[1][0] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_transpose :: proc{ matrix2_inverse_transpose_f16, matrix2_inverse_transpose_f32, matrix2_inverse_transpose_f64, -}; +} matrix2_determinant_f16 :: proc(m: Matrix2f16) -> f16 { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m[0][0]*m[1][1] - m[1][0]*m[0][1] } matrix2_determinant_f32 :: proc(m: Matrix2f32) -> f32 { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m[0][0]*m[1][1] - m[1][0]*m[0][1] } matrix2_determinant_f64 :: proc(m: Matrix2f64) -> f64 { - return m[0][0]*m[1][1] - m[1][0]*m[0][1]; + return m[0][0]*m[1][1] - m[1][0]*m[0][1] } matrix2_determinant :: proc{ matrix2_determinant_f16, matrix2_determinant_f32, matrix2_determinant_f64, -}; +} matrix2_inverse_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[1][0] = -m[0][1] * id; - c[0][1] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[1][0] = -m[0][1] * id + c[0][1] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[1][0] = -m[0][1] * id; - c[0][1] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[1][0] = -m[0][1] * id + c[0][1] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) { - d := m[0][0]*m[1][1] - m[1][0]*m[0][1]; - id := 1.0/d; - c[0][0] = +m[1][1] * id; - c[1][0] = -m[0][1] * id; - c[0][1] = -m[1][0] * id; - c[1][1] = +m[0][0] * id; - return c; + d := m[0][0]*m[1][1] - m[1][0]*m[0][1] + id := 1.0/d + c[0][0] = +m[1][1] * id + c[1][0] = -m[0][1] * id + c[0][1] = -m[1][0] * id + c[1][1] = +m[0][0] * id + return c } matrix2_inverse :: proc{ matrix2_inverse_f16, matrix2_inverse_f32, matrix2_inverse_f64, -}; +} matrix2_adjoint_f16 :: proc(m: Matrix2f16) -> (c: Matrix2f16) { - c[0][0] = +m[1][1]; - c[0][1] = -m[1][0]; - c[1][0] = -m[0][1]; - c[1][1] = +m[0][0]; - return c; + c[0][0] = +m[1][1] + c[0][1] = -m[1][0] + c[1][0] = -m[0][1] + c[1][1] = +m[0][0] + return c } matrix2_adjoint_f32 :: proc(m: Matrix2f32) -> (c: Matrix2f32) { - c[0][0] = +m[1][1]; - c[0][1] = -m[1][0]; - c[1][0] = -m[0][1]; - c[1][1] = +m[0][0]; - return c; + c[0][0] = +m[1][1] + c[0][1] = -m[1][0] + c[1][0] = -m[0][1] + c[1][1] = +m[0][0] + return c } matrix2_adjoint_f64 :: proc(m: Matrix2f64) -> (c: Matrix2f64) { - c[0][0] = +m[1][1]; - c[0][1] = -m[1][0]; - c[1][0] = -m[0][1]; - c[1][1] = +m[0][0]; - return c; + c[0][0] = +m[1][1] + c[0][1] = -m[1][0] + c[1][0] = -m[0][1] + c[1][1] = +m[0][0] + return c } matrix2_adjoint :: proc{ matrix2_adjoint_f16, matrix2_adjoint_f32, matrix2_adjoint_f64, -}; +} matrix3_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix3f16) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; - - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); - - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); - - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); - return m; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z + + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) + + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) + + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) + return m } matrix3_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix3f32) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; - - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); - - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); - - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); - return m; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z + + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) + + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) + + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) + return m } matrix3_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix3f64) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; - - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); - - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); - - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); - return m; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z + + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) + + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) + + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) + return m } matrix3_from_quaternion :: proc{ matrix3_from_quaternion_f16, matrix3_from_quaternion_f32, matrix3_from_quaternion_f64, -}; +} matrix3_inverse_f16 :: proc(m: Matrix3f16) -> Matrix3f16 { - return auto_cast transpose(matrix3_inverse_transpose(m)); + return auto_cast transpose(matrix3_inverse_transpose(m)) } matrix3_inverse_f32 :: proc(m: Matrix3f32) -> Matrix3f32 { - return auto_cast transpose(matrix3_inverse_transpose(m)); + return auto_cast transpose(matrix3_inverse_transpose(m)) } matrix3_inverse_f64 :: proc(m: Matrix3f64) -> Matrix3f64 { - return auto_cast transpose(matrix3_inverse_transpose(m)); + return auto_cast transpose(matrix3_inverse_transpose(m)) } matrix3_inverse :: proc{ matrix3_inverse_f16, matrix3_inverse_f32, matrix3_inverse_f64, -}; +} matrix3_determinant_f16 :: proc(m: Matrix3f16) -> f16 { - a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - return a + b + c; + a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]) + return a + b + c } matrix3_determinant_f32 :: proc(m: Matrix3f32) -> f32 { - a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - return a + b + c; + a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]) + return a + b + c } matrix3_determinant_f64 :: proc(m: Matrix3f64) -> f64 { - a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]); - b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]); - c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); - return a + b + c; + a := +m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + b := -m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + c := +m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]) + return a + b + c } matrix3_determinant :: proc{ matrix3_determinant_f16, matrix3_determinant_f32, matrix3_determinant_f64, -}; +} matrix3_adjoint_f16 :: proc(m: Matrix3f16) -> (adjoint: Matrix3f16) { - adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]); - adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); - adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]); - adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); - adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]); - adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); - adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]); - adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); - adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]); - return adjoint; + adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) + adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) + adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) + adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) + adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) + adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) + adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) + adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) + adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) + return adjoint } matrix3_adjoint_f32 :: proc(m: Matrix3f32) -> (adjoint: Matrix3f32) { - adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]); - adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); - adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]); - adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); - adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]); - adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); - adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]); - adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); - adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]); - return adjoint; + adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) + adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) + adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) + adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) + adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) + adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) + adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) + adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) + adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) + return adjoint } matrix3_adjoint_f64 :: proc(m: Matrix3f64) -> (adjoint: Matrix3f64) { - adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]); - adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]); - adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]); - adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]); - adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]); - adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]); - adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]); - adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]); - adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]); - return adjoint; + adjoint[0][0] = +(m[1][1] * m[2][2] - m[1][2] * m[2][1]) + adjoint[1][0] = -(m[0][1] * m[2][2] - m[0][2] * m[2][1]) + adjoint[2][0] = +(m[0][1] * m[1][2] - m[0][2] * m[1][1]) + adjoint[0][1] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) + adjoint[1][1] = +(m[0][0] * m[2][2] - m[0][2] * m[2][0]) + adjoint[2][1] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) + adjoint[0][2] = +(m[1][0] * m[2][1] - m[1][1] * m[2][0]) + adjoint[1][2] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) + adjoint[2][2] = +(m[0][0] * m[1][1] - m[0][1] * m[1][0]) + return adjoint } matrix3_adjoint :: proc{ matrix3_adjoint_f16, matrix3_adjoint_f32, matrix3_adjoint_f64, -}; +} matrix3_inverse_transpose_f16 :: proc(m: Matrix3f16) -> (inverse_transpose: Matrix3f16) { - adjoint := matrix3_adjoint(m); - determinant := matrix3_determinant(m); - inv_determinant := 1.0 / determinant; + adjoint := matrix3_adjoint(m) + determinant := matrix3_determinant(m) + inv_determinant := 1.0 / determinant for i in 0..<3 { for j in 0..<3 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix3_inverse_transpose_f32 :: proc(m: Matrix3f32) -> (inverse_transpose: Matrix3f32) { - adjoint := matrix3_adjoint(m); - determinant := matrix3_determinant(m); - inv_determinant := 1.0 / determinant; + adjoint := matrix3_adjoint(m) + determinant := matrix3_determinant(m) + inv_determinant := 1.0 / determinant for i in 0..<3 { for j in 0..<3 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix3_inverse_transpose_f64 :: proc(m: Matrix3f64) -> (inverse_transpose: Matrix3f64) { - adjoint := matrix3_adjoint(m); - determinant := matrix3_determinant(m); - inv_determinant := 1.0 / determinant; + adjoint := matrix3_adjoint(m) + determinant := matrix3_determinant(m) + inv_determinant := 1.0 / determinant for i in 0..<3 { for j in 0..<3 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix3_inverse_transpose :: proc{ matrix3_inverse_transpose_f16, matrix3_inverse_transpose_f32, matrix3_inverse_transpose_f64, -}; +} matrix3_scale_f16 :: proc(s: Vector3f16) -> (m: Matrix3f16) { - m[0][0] = s[0]; - m[1][1] = s[1]; - m[2][2] = s[2]; - return m; + m[0][0] = s[0] + m[1][1] = s[1] + m[2][2] = s[2] + return m } matrix3_scale_f32 :: proc(s: Vector3f32) -> (m: Matrix3f32) { - m[0][0] = s[0]; - m[1][1] = s[1]; - m[2][2] = s[2]; - return m; + m[0][0] = s[0] + m[1][1] = s[1] + m[2][2] = s[2] + return m } matrix3_scale_f64 :: proc(s: Vector3f64) -> (m: Matrix3f64) { - m[0][0] = s[0]; - m[1][1] = s[1]; - m[2][2] = s[2]; - return m; + m[0][0] = s[0] + m[1][1] = s[1] + m[2][2] = s[2] + return m } matrix3_scale :: proc{ matrix3_scale_f16, matrix3_scale_f32, matrix3_scale_f64, -}; +} matrix3_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> (rot: Matrix3f16) { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] - return rot; + return rot } matrix3_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> (rot: Matrix3f32) { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] - return rot; + return rot } matrix3_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> (rot: Matrix3f64) { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] - return rot; + return rot } matrix3_rotate :: proc{ matrix3_rotate_f16, matrix3_rotate_f32, matrix3_rotate_f64, -}; +} matrix3_look_at_f16 :: proc(eye, centre, up: Vector3f16) -> Matrix3f16 { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) return Matrix3f16{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } } matrix3_look_at_f32 :: proc(eye, centre, up: Vector3f32) -> Matrix3f32 { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) return Matrix3f32{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } } matrix3_look_at_f64 :: proc(eye, centre, up: Vector3f64) -> Matrix3f64 { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) return Matrix3f64{ {+s.x, +u.x, -f.x}, {+s.y, +u.y, -f.y}, {+s.z, +u.z, -f.z}, - }; + } } matrix3_look_at :: proc{ matrix3_look_at_f16, matrix3_look_at_f32, matrix3_look_at_f64, -}; +} matrix4_from_quaternion_f16 :: proc(q: Quaternionf16) -> (m: Matrix4f16) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) - m[3][3] = 1; + m[3][3] = 1 - return m; + return m } matrix4_from_quaternion_f32 :: proc(q: Quaternionf32) -> (m: Matrix4f32) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) - m[3][3] = 1; + m[3][3] = 1 - return m; + return m } matrix4_from_quaternion_f64 :: proc(q: Quaternionf64) -> (m: Matrix4f64) { - qxx := q.x * q.x; - qyy := q.y * q.y; - qzz := q.z * q.z; - qxz := q.x * q.z; - qxy := q.x * q.y; - qyz := q.y * q.z; - qwx := q.w * q.x; - qwy := q.w * q.y; - qwz := q.w * q.z; + qxx := q.x * q.x + qyy := q.y * q.y + qzz := q.z * q.z + qxz := q.x * q.z + qxy := q.x * q.y + qyz := q.y * q.z + qwx := q.w * q.x + qwy := q.w * q.y + qwz := q.w * q.z - m[0][0] = 1 - 2 * (qyy + qzz); - m[0][1] = 2 * (qxy + qwz); - m[0][2] = 2 * (qxz - qwy); + m[0][0] = 1 - 2 * (qyy + qzz) + m[0][1] = 2 * (qxy + qwz) + m[0][2] = 2 * (qxz - qwy) - m[1][0] = 2 * (qxy - qwz); - m[1][1] = 1 - 2 * (qxx + qzz); - m[1][2] = 2 * (qyz + qwx); + m[1][0] = 2 * (qxy - qwz) + m[1][1] = 1 - 2 * (qxx + qzz) + m[1][2] = 2 * (qyz + qwx) - m[2][0] = 2 * (qxz + qwy); - m[2][1] = 2 * (qyz - qwx); - m[2][2] = 1 - 2 * (qxx + qyy); + m[2][0] = 2 * (qxz + qwy) + m[2][1] = 2 * (qyz - qwx) + m[2][2] = 1 - 2 * (qxx + qyy) - m[3][3] = 1; + m[3][3] = 1 - return m; + return m } matrix4_from_quaternion :: proc{ matrix4_from_quaternion_f16, matrix4_from_quaternion_f32, matrix4_from_quaternion_f64, -}; +} matrix4_from_trs_f16 :: proc(t: Vector3f16, r: Quaternionf16, s: Vector3f16) -> Matrix4f16 { - translation := matrix4_translate(t); - rotation := matrix4_from_quaternion(r); - scale := matrix4_scale(s); - return mul(translation, mul(rotation, scale)); + translation := matrix4_translate(t) + rotation := matrix4_from_quaternion(r) + scale := matrix4_scale(s) + return mul(translation, mul(rotation, scale)) } matrix4_from_trs_f32 :: proc(t: Vector3f32, r: Quaternionf32, s: Vector3f32) -> Matrix4f32 { - translation := matrix4_translate(t); - rotation := matrix4_from_quaternion(r); - scale := matrix4_scale(s); - return mul(translation, mul(rotation, scale)); + translation := matrix4_translate(t) + rotation := matrix4_from_quaternion(r) + scale := matrix4_scale(s) + return mul(translation, mul(rotation, scale)) } matrix4_from_trs_f64 :: proc(t: Vector3f64, r: Quaternionf64, s: Vector3f64) -> Matrix4f64 { - translation := matrix4_translate(t); - rotation := matrix4_from_quaternion(r); - scale := matrix4_scale(s); - return mul(translation, mul(rotation, scale)); + translation := matrix4_translate(t) + rotation := matrix4_from_quaternion(r) + scale := matrix4_scale(s) + return mul(translation, mul(rotation, scale)) } matrix4_from_trs :: proc{ matrix4_from_trs_f16, matrix4_from_trs_f32, matrix4_from_trs_f64, -}; +} matrix4_inverse_f16 :: proc(m: Matrix4f16) -> Matrix4f16 { - return auto_cast transpose(matrix4_inverse_transpose(m)); + return auto_cast transpose(matrix4_inverse_transpose(m)) } matrix4_inverse_f32 :: proc(m: Matrix4f32) -> Matrix4f32 { - return auto_cast transpose(matrix4_inverse_transpose(m)); + return auto_cast transpose(matrix4_inverse_transpose(m)) } matrix4_inverse_f64 :: proc(m: Matrix4f64) -> Matrix4f64 { - return auto_cast transpose(matrix4_inverse_transpose(m)); + return auto_cast transpose(matrix4_inverse_transpose(m)) } matrix4_inverse :: proc{ matrix4_inverse_f16, matrix4_inverse_f32, matrix4_inverse_f64, -}; +} matrix4_minor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 { - cut_down: Matrix3f16; + cut_down: Matrix3f16 for i in 0..<3 { - col := i if i < c else i+1; + col := i if i < c else i+1 for j in 0..<3 { - row := j if j < r else j+1; - cut_down[i][j] = m[col][row]; + row := j if j < r else j+1 + cut_down[i][j] = m[col][row] } } - return matrix3_determinant(cut_down); + return matrix3_determinant(cut_down) } matrix4_minor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 { - cut_down: Matrix3f32; + cut_down: Matrix3f32 for i in 0..<3 { - col := i if i < c else i+1; + col := i if i < c else i+1 for j in 0..<3 { - row := j if j < r else j+1; - cut_down[i][j] = m[col][row]; + row := j if j < r else j+1 + cut_down[i][j] = m[col][row] } } - return matrix3_determinant(cut_down); + return matrix3_determinant(cut_down) } matrix4_minor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 { - cut_down: Matrix3f64; + cut_down: Matrix3f64 for i in 0..<3 { - col := i if i < c else i+1; + col := i if i < c else i+1 for j in 0..<3 { - row := j if j < r else j+1; - cut_down[i][j] = m[col][row]; + row := j if j < r else j+1 + cut_down[i][j] = m[col][row] } } - return matrix3_determinant(cut_down); + return matrix3_determinant(cut_down) } matrix4_minor :: proc{ matrix4_minor_f16, matrix4_minor_f32, matrix4_minor_f64, -}; +} matrix4_cofactor_f16 :: proc(m: Matrix4f16, c, r: int) -> f16 { - sign, minor: f16; - sign = 1 if (c + r) % 2 == 0 else -1; - minor = matrix4_minor(m, c, r); - return sign * minor; + sign, minor: f16 + sign = 1 if (c + r) % 2 == 0 else -1 + minor = matrix4_minor(m, c, r) + return sign * minor } matrix4_cofactor_f32 :: proc(m: Matrix4f32, c, r: int) -> f32 { - sign, minor: f32; - sign = 1 if (c + r) % 2 == 0 else -1; - minor = matrix4_minor(m, c, r); - return sign * minor; + sign, minor: f32 + sign = 1 if (c + r) % 2 == 0 else -1 + minor = matrix4_minor(m, c, r) + return sign * minor } matrix4_cofactor_f64 :: proc(m: Matrix4f64, c, r: int) -> f64 { - sign, minor: f64; - sign = 1 if (c + r) % 2 == 0 else -1; - minor = matrix4_minor(m, c, r); - return sign * minor; + sign, minor: f64 + sign = 1 if (c + r) % 2 == 0 else -1 + minor = matrix4_minor(m, c, r) + return sign * minor } matrix4_cofactor :: proc{ matrix4_cofactor_f16, matrix4_cofactor_f32, matrix4_cofactor_f64, -}; +} matrix4_adjoint_f16 :: proc(m: Matrix4f16) -> (adjoint: Matrix4f16) { for i in 0..<4 { for j in 0..<4 { - adjoint[i][j] = matrix4_cofactor(m, i, j); + adjoint[i][j] = matrix4_cofactor(m, i, j) } } - return; + return } matrix4_adjoint_f32 :: proc(m: Matrix4f32) -> (adjoint: Matrix4f32) { for i in 0..<4 { for j in 0..<4 { - adjoint[i][j] = matrix4_cofactor(m, i, j); + adjoint[i][j] = matrix4_cofactor(m, i, j) } } - return; + return } matrix4_adjoint_f64 :: proc(m: Matrix4f64) -> (adjoint: Matrix4f64) { for i in 0..<4 { for j in 0..<4 { - adjoint[i][j] = matrix4_cofactor(m, i, j); + adjoint[i][j] = matrix4_cofactor(m, i, j) } } - return; + return } matrix4_adjoint :: proc{ matrix4_adjoint_f16, matrix4_adjoint_f32, matrix4_adjoint_f64, -}; +} matrix4_determinant_f16 :: proc(m: Matrix4f16) -> (determinant: f16) { - adjoint := matrix4_adjoint(m); + adjoint := matrix4_adjoint(m) for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - return; + return } matrix4_determinant_f32 :: proc(m: Matrix4f32) -> (determinant: f32) { - adjoint := matrix4_adjoint(m); + adjoint := matrix4_adjoint(m) for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - return; + return } matrix4_determinant_f64 :: proc(m: Matrix4f64) -> (determinant: f64) { - adjoint := matrix4_adjoint(m); + adjoint := matrix4_adjoint(m) for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - return; + return } matrix4_determinant :: proc{ matrix4_determinant_f16, matrix4_determinant_f32, matrix4_determinant_f64, -}; +} matrix4_inverse_transpose_f16 :: proc(m: Matrix4f16) -> (inverse_transpose: Matrix4f16) { - adjoint := matrix4_adjoint(m); - determinant: f16 = 0; + adjoint := matrix4_adjoint(m) + determinant: f16 = 0 for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - inv_determinant := 1.0 / determinant; + inv_determinant := 1.0 / determinant for i in 0..<4 { for j in 0..<4 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix4_inverse_transpose_f32 :: proc(m: Matrix4f32) -> (inverse_transpose: Matrix4f32) { - adjoint := matrix4_adjoint(m); - determinant: f32 = 0; + adjoint := matrix4_adjoint(m) + determinant: f32 = 0 for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - inv_determinant := 1.0 / determinant; + inv_determinant := 1.0 / determinant for i in 0..<4 { for j in 0..<4 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix4_inverse_transpose_f64 :: proc(m: Matrix4f64) -> (inverse_transpose: Matrix4f64) { - adjoint := matrix4_adjoint(m); - determinant: f64 = 0; + adjoint := matrix4_adjoint(m) + determinant: f64 = 0 for i in 0..<4 { - determinant += m[i][0] * adjoint[i][0]; + determinant += m[i][0] * adjoint[i][0] } - inv_determinant := 1.0 / determinant; + inv_determinant := 1.0 / determinant for i in 0..<4 { for j in 0..<4 { - inverse_transpose[i][j] = adjoint[i][j] * inv_determinant; + inverse_transpose[i][j] = adjoint[i][j] * inv_determinant } } - return; + return } matrix4_inverse_transpose :: proc{ matrix4_inverse_transpose_f16, matrix4_inverse_transpose_f32, matrix4_inverse_transpose_f64, -}; +} matrix4_translate_f16 :: proc(v: Vector3f16) -> Matrix4f16 { - m := MATRIX4F16_IDENTITY; - m[3][0] = v[0]; - m[3][1] = v[1]; - m[3][2] = v[2]; - return m; + m := MATRIX4F16_IDENTITY + m[3][0] = v[0] + m[3][1] = v[1] + m[3][2] = v[2] + return m } matrix4_translate_f32 :: proc(v: Vector3f32) -> Matrix4f32 { - m := MATRIX4F32_IDENTITY; - m[3][0] = v[0]; - m[3][1] = v[1]; - m[3][2] = v[2]; - return m; + m := MATRIX4F32_IDENTITY + m[3][0] = v[0] + m[3][1] = v[1] + m[3][2] = v[2] + return m } matrix4_translate_f64 :: proc(v: Vector3f64) -> Matrix4f64 { - m := MATRIX4F64_IDENTITY; - m[3][0] = v[0]; - m[3][1] = v[1]; - m[3][2] = v[2]; - return m; + m := MATRIX4F64_IDENTITY + m[3][0] = v[0] + m[3][1] = v[1] + m[3][2] = v[2] + return m } matrix4_translate :: proc{ matrix4_translate_f16, matrix4_translate_f32, matrix4_translate_f64, -}; +} matrix4_rotate_f16 :: proc(angle_radians: f16, v: Vector3f16) -> Matrix4f16 { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot := MATRIX4F16_IDENTITY; + rot := MATRIX4F16_IDENTITY - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; - rot[0][3] = 0; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] + rot[0][3] = 0 - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; - rot[1][3] = 0; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] + rot[1][3] = 0 - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; - rot[2][3] = 0; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] + rot[2][3] = 0 - return rot; + return rot } matrix4_rotate_f32 :: proc(angle_radians: f32, v: Vector3f32) -> Matrix4f32 { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot := MATRIX4F32_IDENTITY; + rot := MATRIX4F32_IDENTITY - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; - rot[0][3] = 0; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] + rot[0][3] = 0 - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; - rot[1][3] = 0; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] + rot[1][3] = 0 - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; - rot[2][3] = 0; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] + rot[2][3] = 0 - return rot; + return rot } matrix4_rotate_f64 :: proc(angle_radians: f64, v: Vector3f64) -> Matrix4f64 { - c := math.cos(angle_radians); - s := math.sin(angle_radians); + c := math.cos(angle_radians) + s := math.sin(angle_radians) - a := normalize(v); - t := a * (1-c); + a := normalize(v) + t := a * (1-c) - rot := MATRIX4F64_IDENTITY; + rot := MATRIX4F64_IDENTITY - rot[0][0] = c + t[0]*a[0]; - rot[0][1] = 0 + t[0]*a[1] + s*a[2]; - rot[0][2] = 0 + t[0]*a[2] - s*a[1]; - rot[0][3] = 0; + rot[0][0] = c + t[0]*a[0] + rot[0][1] = 0 + t[0]*a[1] + s*a[2] + rot[0][2] = 0 + t[0]*a[2] - s*a[1] + rot[0][3] = 0 - rot[1][0] = 0 + t[1]*a[0] - s*a[2]; - rot[1][1] = c + t[1]*a[1]; - rot[1][2] = 0 + t[1]*a[2] + s*a[0]; - rot[1][3] = 0; + rot[1][0] = 0 + t[1]*a[0] - s*a[2] + rot[1][1] = c + t[1]*a[1] + rot[1][2] = 0 + t[1]*a[2] + s*a[0] + rot[1][3] = 0 - rot[2][0] = 0 + t[2]*a[0] + s*a[1]; - rot[2][1] = 0 + t[2]*a[1] - s*a[0]; - rot[2][2] = c + t[2]*a[2]; - rot[2][3] = 0; + rot[2][0] = 0 + t[2]*a[0] + s*a[1] + rot[2][1] = 0 + t[2]*a[1] - s*a[0] + rot[2][2] = c + t[2]*a[2] + rot[2][3] = 0 - return rot; + return rot } matrix4_rotate :: proc{ matrix4_rotate_f16, matrix4_rotate_f32, matrix4_rotate_f64, -}; +} matrix4_scale_f16 :: proc(v: Vector3f16) -> (m: Matrix4f16) { - m[0][0] = v[0]; - m[1][1] = v[1]; - m[2][2] = v[2]; - m[3][3] = 1; - return; + m[0][0] = v[0] + m[1][1] = v[1] + m[2][2] = v[2] + m[3][3] = 1 + return } matrix4_scale_f32 :: proc(v: Vector3f32) -> (m: Matrix4f32) { - m[0][0] = v[0]; - m[1][1] = v[1]; - m[2][2] = v[2]; - m[3][3] = 1; - return; + m[0][0] = v[0] + m[1][1] = v[1] + m[2][2] = v[2] + m[3][3] = 1 + return } matrix4_scale_f64 :: proc(v: Vector3f64) -> (m: Matrix4f64) { - m[0][0] = v[0]; - m[1][1] = v[1]; - m[2][2] = v[2]; - m[3][3] = 1; - return; + m[0][0] = v[0] + m[1][1] = v[1] + m[2][2] = v[2] + m[3][3] = 1 + return } matrix4_scale :: proc{ matrix4_scale_f16, matrix4_scale_f32, matrix4_scale_f64, -}; +} matrix4_look_at_f16 :: proc(eye, centre, up: Vector3f16, flip_z_axis := true) -> (m: Matrix4f16) { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) - fe := dot(f, eye); + fe := dot(f, eye) return { {+s.x, +u.x, -f.x, 0}, {+s.y, +u.y, -f.y, 0}, {+s.z, +u.z, -f.z, 0}, {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1}, - }; + } } matrix4_look_at_f32 :: proc(eye, centre, up: Vector3f32, flip_z_axis := true) -> (m: Matrix4f32) { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) - fe := dot(f, eye); + fe := dot(f, eye) return { {+s.x, +u.x, -f.x, 0}, {+s.y, +u.y, -f.y, 0}, {+s.z, +u.z, -f.z, 0}, {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1}, - }; + } } matrix4_look_at_f64 :: proc(eye, centre, up: Vector3f64, flip_z_axis := true) -> (m: Matrix4f64) { - f := normalize(centre - eye); - s := normalize(cross(f, up)); - u := cross(s, f); + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) - fe := dot(f, eye); + fe := dot(f, eye) return { {+s.x, +u.x, -f.x, 0}, {+s.y, +u.y, -f.y, 0}, {+s.z, +u.z, -f.z, 0}, {-dot(s, eye), -dot(u, eye), +fe if flip_z_axis else -fe, 1}, - }; + } } matrix4_look_at :: proc{ matrix4_look_at_f16, matrix4_look_at_f32, matrix4_look_at_f64, -}; +} matrix4_perspective_f16 :: proc(fovy, aspect, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +(far + near) / (far - near); - m[2][3] = +1; - m[3][2] = -2*far*near / (far - near); + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +(far + near) / (far - near) + m[2][3] = +1 + m[3][2] = -2*far*near / (far - near) if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_perspective_f32 :: proc(fovy, aspect, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +(far + near) / (far - near); - m[2][3] = +1; - m[3][2] = -2*far*near / (far - near); + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +(far + near) / (far - near) + m[2][3] = +1 + m[3][2] = -2*far*near / (far - near) if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_perspective_f64 :: proc(fovy, aspect, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +(far + near) / (far - near); - m[2][3] = +1; - m[3][2] = -2*far*near / (far - near); + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +(far + near) / (far - near) + m[2][3] = +1 + m[3][2] = -2*far*near / (far - near) if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_perspective :: proc{ matrix4_perspective_f16, matrix4_perspective_f32, matrix4_perspective_f64, -}; +} matrix_ortho3d_f16 :: proc(left, right, bottom, top, near, far: f16, flip_z_axis := true) -> (m: Matrix4f16) { - m[0][0] = +2 / (right - left); - m[1][1] = +2 / (top - bottom); - m[2][2] = +2 / (far - near); - m[3][0] = -(right + left) / (right - left); - m[3][1] = -(top + bottom) / (top - bottom); - m[3][2] = -(far + near) / (far- near); - m[3][3] = 1; + m[0][0] = +2 / (right - left) + m[1][1] = +2 / (top - bottom) + m[2][2] = +2 / (far - near) + m[3][0] = -(right + left) / (right - left) + m[3][1] = -(top + bottom) / (top - bottom) + m[3][2] = -(far + near) / (far- near) + m[3][3] = 1 if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix_ortho3d_f32 :: proc(left, right, bottom, top, near, far: f32, flip_z_axis := true) -> (m: Matrix4f32) { - m[0][0] = +2 / (right - left); - m[1][1] = +2 / (top - bottom); - m[2][2] = +2 / (far - near); - m[3][0] = -(right + left) / (right - left); - m[3][1] = -(top + bottom) / (top - bottom); - m[3][2] = -(far + near) / (far- near); - m[3][3] = 1; + m[0][0] = +2 / (right - left) + m[1][1] = +2 / (top - bottom) + m[2][2] = +2 / (far - near) + m[3][0] = -(right + left) / (right - left) + m[3][1] = -(top + bottom) / (top - bottom) + m[3][2] = -(far + near) / (far- near) + m[3][3] = 1 if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix_ortho3d_f64 :: proc(left, right, bottom, top, near, far: f64, flip_z_axis := true) -> (m: Matrix4f64) { - m[0][0] = +2 / (right - left); - m[1][1] = +2 / (top - bottom); - m[2][2] = +2 / (far - near); - m[3][0] = -(right + left) / (right - left); - m[3][1] = -(top + bottom) / (top - bottom); - m[3][2] = -(far + near) / (far- near); - m[3][3] = 1; + m[0][0] = +2 / (right - left) + m[1][1] = +2 / (top - bottom) + m[2][2] = +2 / (far - near) + m[3][0] = -(right + left) / (right - left) + m[3][1] = -(top + bottom) / (top - bottom) + m[3][2] = -(far + near) / (far- near) + m[3][3] = 1 if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix_ortho3d :: proc{ matrix_ortho3d_f16, matrix_ortho3d_f32, matrix_ortho3d_f64, -}; +} matrix4_infinite_perspective_f16 :: proc(fovy, aspect, near: f16, flip_z_axis := true) -> (m: Matrix4f16) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +1; - m[2][3] = +1; - m[3][2] = -2*near; + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +1 + m[2][3] = +1 + m[3][2] = -2*near if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_infinite_perspective_f32 :: proc(fovy, aspect, near: f32, flip_z_axis := true) -> (m: Matrix4f32) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +1; - m[2][3] = +1; - m[3][2] = -2*near; + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +1 + m[2][3] = +1 + m[3][2] = -2*near if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_infinite_perspective_f64 :: proc(fovy, aspect, near: f64, flip_z_axis := true) -> (m: Matrix4f64) { - tan_half_fovy := math.tan(0.5 * fovy); - m[0][0] = 1 / (aspect*tan_half_fovy); - m[1][1] = 1 / (tan_half_fovy); - m[2][2] = +1; - m[2][3] = +1; - m[3][2] = -2*near; + tan_half_fovy := math.tan(0.5 * fovy) + m[0][0] = 1 / (aspect*tan_half_fovy) + m[1][1] = 1 / (tan_half_fovy) + m[2][2] = +1 + m[2][3] = +1 + m[3][2] = -2*near if flip_z_axis { - m[2] = -m[2]; + m[2] = -m[2] } - return; + return } matrix4_infinite_perspective :: proc{ matrix4_infinite_perspective_f16, matrix4_infinite_perspective_f32, matrix4_infinite_perspective_f64, -}; +} matrix2_from_scalar_f16 :: proc(f: f16) -> (m: Matrix2f16) { - m[0][0], m[0][1] = f, 0; - m[1][0], m[1][1] = 0, f; - return; + m[0][0], m[0][1] = f, 0 + m[1][0], m[1][1] = 0, f + return } matrix2_from_scalar_f32 :: proc(f: f32) -> (m: Matrix2f32) { - m[0][0], m[0][1] = f, 0; - m[1][0], m[1][1] = 0, f; - return; + m[0][0], m[0][1] = f, 0 + m[1][0], m[1][1] = 0, f + return } matrix2_from_scalar_f64 :: proc(f: f64) -> (m: Matrix2f64) { - m[0][0], m[0][1] = f, 0; - m[1][0], m[1][1] = 0, f; - return; + m[0][0], m[0][1] = f, 0 + m[1][0], m[1][1] = 0, f + return } matrix2_from_scalar :: proc{ matrix2_from_scalar_f16, matrix2_from_scalar_f32, matrix2_from_scalar_f64, -}; +} matrix3_from_scalar_f16 :: proc(f: f16) -> (m: Matrix3f16) { - m[0][0], m[0][1], m[0][2] = f, 0, 0; - m[1][0], m[1][1], m[1][2] = 0, f, 0; - m[2][0], m[2][1], m[2][2] = 0, 0, f; - return; + m[0][0], m[0][1], m[0][2] = f, 0, 0 + m[1][0], m[1][1], m[1][2] = 0, f, 0 + m[2][0], m[2][1], m[2][2] = 0, 0, f + return } matrix3_from_scalar_f32 :: proc(f: f32) -> (m: Matrix3f32) { - m[0][0], m[0][1], m[0][2] = f, 0, 0; - m[1][0], m[1][1], m[1][2] = 0, f, 0; - m[2][0], m[2][1], m[2][2] = 0, 0, f; - return; + m[0][0], m[0][1], m[0][2] = f, 0, 0 + m[1][0], m[1][1], m[1][2] = 0, f, 0 + m[2][0], m[2][1], m[2][2] = 0, 0, f + return } matrix3_from_scalar_f64 :: proc(f: f64) -> (m: Matrix3f64) { - m[0][0], m[0][1], m[0][2] = f, 0, 0; - m[1][0], m[1][1], m[1][2] = 0, f, 0; - m[2][0], m[2][1], m[2][2] = 0, 0, f; - return; + m[0][0], m[0][1], m[0][2] = f, 0, 0 + m[1][0], m[1][1], m[1][2] = 0, f, 0 + m[2][0], m[2][1], m[2][2] = 0, 0, f + return } matrix3_from_scalar :: proc{ matrix3_from_scalar_f16, matrix3_from_scalar_f32, matrix3_from_scalar_f64, -}; +} matrix4_from_scalar_f16 :: proc(f: f16) -> (m: Matrix4f16) { - m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0; - m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0; - m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0; - m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f; - return; + m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0 + m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0 + m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0 + m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f + return } matrix4_from_scalar_f32 :: proc(f: f32) -> (m: Matrix4f32) { - m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0; - m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0; - m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0; - m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f; - return; + m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0 + m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0 + m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0 + m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f + return } matrix4_from_scalar_f64 :: proc(f: f64) -> (m: Matrix4f64) { - m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0; - m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0; - m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0; - m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f; - return; + m[0][0], m[0][1], m[0][2], m[0][3] = f, 0, 0, 0 + m[1][0], m[1][1], m[1][2], m[1][3] = 0, f, 0, 0 + m[2][0], m[2][1], m[2][2], m[2][3] = 0, 0, f, 0 + m[3][0], m[3][1], m[3][2], m[3][3] = 0, 0, 0, f + return } matrix4_from_scalar :: proc{ matrix4_from_scalar_f16, matrix4_from_scalar_f32, matrix4_from_scalar_f64, -}; +} matrix2_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix2f16) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix2f32) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix2f64) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix3 :: proc{ matrix2_from_matrix3_f16, matrix2_from_matrix3_f32, matrix2_from_matrix3_f64, -}; +} matrix2_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix2f16) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix2f32) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix2f64) { - r[0][0], r[0][1] = m[0][0], m[0][1]; - r[1][0], r[1][1] = m[1][0], m[1][1]; - return; + r[0][0], r[0][1] = m[0][0], m[0][1] + r[1][0], r[1][1] = m[1][0], m[1][1] + return } matrix2_from_matrix4 :: proc{ matrix2_from_matrix4_f16, matrix2_from_matrix4_f32, matrix2_from_matrix4_f64, -}; +} matrix3_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix3f16) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0; - r[2][0], r[2][1], r[2][2] = 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0 + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0 + r[2][0], r[2][1], r[2][2] = 0, 0, 1 + return } matrix3_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix3f32) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0; - r[2][0], r[2][1], r[2][2] = 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0 + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0 + r[2][0], r[2][1], r[2][2] = 0, 0, 1 + return } matrix3_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix3f64) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0; - r[2][0], r[2][1], r[2][2] = 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], 0 + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], 0 + r[2][0], r[2][1], r[2][2] = 0, 0, 1 + return } matrix3_from_matrix2 :: proc{ matrix3_from_matrix2_f16, matrix3_from_matrix2_f32, matrix3_from_matrix2_f64, -}; +} matrix3_from_matrix4_f16 :: proc(m: Matrix4f16) -> (r: Matrix3f16) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2]; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2]; - r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2]; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2] + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2] + r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2] + return } matrix3_from_matrix4_f32 :: proc(m: Matrix4f32) -> (r: Matrix3f32) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2]; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2]; - r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2]; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2] + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2] + r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2] + return } matrix3_from_matrix4_f64 :: proc(m: Matrix4f64) -> (r: Matrix3f64) { - r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2]; - r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2]; - r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2]; - return; + r[0][0], r[0][1], r[0][2] = m[0][0], m[0][1], m[0][2] + r[1][0], r[1][1], r[1][2] = m[1][0], m[1][1], m[1][2] + r[2][0], r[2][1], r[2][2] = m[2][0], m[2][1], m[2][2] + return } matrix3_from_matrix4 :: proc{ matrix3_from_matrix4_f16, matrix3_from_matrix4_f32, matrix3_from_matrix4_f64, -}; +} matrix4_from_matrix2_f16 :: proc(m: Matrix2f16) -> (r: Matrix4f16) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0; - r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0 + r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix2_f32 :: proc(m: Matrix2f32) -> (r: Matrix4f32) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0; - r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0 + r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix2_f64 :: proc(m: Matrix2f64) -> (r: Matrix4f64) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0; - r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], 0, 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], 0, 0 + r[2][0], r[2][1], r[2][2], r[2][3] = 0, 0, 1, 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix2 :: proc{ matrix4_from_matrix2_f16, matrix4_from_matrix2_f32, matrix4_from_matrix2_f64, -}; +} matrix4_from_matrix3_f16 :: proc(m: Matrix3f16) -> (r: Matrix4f16) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0; - r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0 + r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix3_f32 :: proc(m: Matrix3f32) -> (r: Matrix4f32) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0; - r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0 + r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix3_f64 :: proc(m: Matrix3f64) -> (r: Matrix4f64) { - r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0; - r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0; - r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0; - r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1; - return; + r[0][0], r[0][1], r[0][2], r[0][3] = m[0][0], m[0][1], m[0][2], 0 + r[1][0], r[1][1], r[1][2], r[1][3] = m[1][0], m[1][1], m[1][2], 0 + r[2][0], r[2][1], r[2][2], r[2][3] = m[2][0], m[2][1], m[2][2], 0 + r[3][0], r[3][1], r[3][2], r[3][3] = 0, 0, 0, 1 + return } matrix4_from_matrix3 :: proc{ matrix4_from_matrix3_f16, matrix4_from_matrix3_f32, matrix4_from_matrix3_f64, -}; +} quaternion_from_scalar_f16 :: proc(f: f16) -> (q: Quaternionf16) { - q.w = f; - return; + q.w = f + return } quaternion_from_scalar_f32 :: proc(f: f32) -> (q: Quaternionf32) { - q.w = f; - return; + q.w = f + return } quaternion_from_scalar_f64 :: proc(f: f64) -> (q: Quaternionf64) { - q.w = f; - return; + q.w = f + return } quaternion_from_scalar :: proc{ quaternion_from_scalar_f16, quaternion_from_scalar_f32, quaternion_from_scalar_f64, -}; +} -to_matrix2f16 :: proc{matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16}; -to_matrix3f16 :: proc{matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16}; -to_matrix4f16 :: proc{matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16}; -to_quaternionf16 :: proc{quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16}; +to_matrix2f16 :: proc{matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16} +to_matrix3f16 :: proc{matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16} +to_matrix4f16 :: proc{matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16} +to_quaternionf16 :: proc{quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16} -to_matrix2f32 :: proc{matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32}; -to_matrix3f32 :: proc{matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32}; -to_matrix4f32 :: proc{matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32}; -to_quaternionf32 :: proc{quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32}; +to_matrix2f32 :: proc{matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32} +to_matrix3f32 :: proc{matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32} +to_matrix4f32 :: proc{matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32} +to_quaternionf32 :: proc{quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32} -to_matrix2f64 :: proc{matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64}; -to_matrix3f64 :: proc{matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64}; -to_matrix4f64 :: proc{matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64}; -to_quaternionf64 :: proc{quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64}; +to_matrix2f64 :: proc{matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64} +to_matrix3f64 :: proc{matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64} +to_matrix4f64 :: proc{matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64} +to_quaternionf64 :: proc{quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64} @@ -2457,250 +2457,250 @@ to_matrix2f :: proc{ matrix2_from_scalar_f16, matrix2_from_matrix3_f16, matrix2_from_matrix4_f16, matrix2_from_scalar_f32, matrix2_from_matrix3_f32, matrix2_from_matrix4_f32, matrix2_from_scalar_f64, matrix2_from_matrix3_f64, matrix2_from_matrix4_f64, -}; +} to_matrix3 :: proc{ matrix3_from_scalar_f16, matrix3_from_matrix2_f16, matrix3_from_matrix4_f16, matrix3_from_quaternion_f16, matrix3_from_scalar_f32, matrix3_from_matrix2_f32, matrix3_from_matrix4_f32, matrix3_from_quaternion_f32, matrix3_from_scalar_f64, matrix3_from_matrix2_f64, matrix3_from_matrix4_f64, matrix3_from_quaternion_f64, -}; +} to_matrix4 :: proc{ matrix4_from_scalar_f16, matrix4_from_matrix2_f16, matrix4_from_matrix3_f16, matrix4_from_quaternion_f16, matrix4_from_scalar_f32, matrix4_from_matrix2_f32, matrix4_from_matrix3_f32, matrix4_from_quaternion_f32, matrix4_from_scalar_f64, matrix4_from_matrix2_f64, matrix4_from_matrix3_f64, matrix4_from_quaternion_f64, -}; +} to_quaternion :: proc{ quaternion_from_scalar_f16, quaternion_from_matrix3_f16, quaternion_from_matrix4_f16, quaternion_from_scalar_f32, quaternion_from_matrix3_f32, quaternion_from_matrix4_f32, quaternion_from_scalar_f64, quaternion_from_matrix3_f64, quaternion_from_matrix4_f64, -}; +} matrix2_orthonormalize_f16 :: proc(m: Matrix2f16) -> (r: Matrix2f16) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - return; + return } matrix2_orthonormalize_f32 :: proc(m: Matrix2f32) -> (r: Matrix2f32) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - return; + return } matrix2_orthonormalize_f64 :: proc(m: Matrix2f64) -> (r: Matrix2f64) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - return; + return } matrix2_orthonormalize :: proc{ matrix2_orthonormalize_f16, matrix2_orthonormalize_f32, matrix2_orthonormalize_f64, -}; +} matrix3_orthonormalize_f16 :: proc(m: Matrix3f16) -> (r: Matrix3f16) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - d1 := dot(r[1], r[2]); - d0 = dot(r[0], r[2]); - r[2] -= r[0]*d0 + r[1]*d1; - r[2] = normalize(r[2]); + d1 := dot(r[1], r[2]) + d0 = dot(r[0], r[2]) + r[2] -= r[0]*d0 + r[1]*d1 + r[2] = normalize(r[2]) - return; + return } matrix3_orthonormalize_f32 :: proc(m: Matrix3f32) -> (r: Matrix3f32) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - d1 := dot(r[1], r[2]); - d0 = dot(r[0], r[2]); - r[2] -= r[0]*d0 + r[1]*d1; - r[2] = normalize(r[2]); + d1 := dot(r[1], r[2]) + d0 = dot(r[0], r[2]) + r[2] -= r[0]*d0 + r[1]*d1 + r[2] = normalize(r[2]) - return; + return } matrix3_orthonormalize_f64 :: proc(m: Matrix3f64) -> (r: Matrix3f64) { - r[0] = normalize(m[0]); + r[0] = normalize(m[0]) - d0 := dot(r[0], r[1]); - r[1] -= r[0] * d0; - r[1] = normalize(r[1]); + d0 := dot(r[0], r[1]) + r[1] -= r[0] * d0 + r[1] = normalize(r[1]) - d1 := dot(r[1], r[2]); - d0 = dot(r[0], r[2]); - r[2] -= r[0]*d0 + r[1]*d1; - r[2] = normalize(r[2]); + d1 := dot(r[1], r[2]) + d0 = dot(r[0], r[2]) + r[2] -= r[0]*d0 + r[1]*d1 + r[2] = normalize(r[2]) - return; + return } matrix3_orthonormalize :: proc{ matrix3_orthonormalize_f16, matrix3_orthonormalize_f32, matrix3_orthonormalize_f64, -}; +} vector3_orthonormalize_f16 :: proc(x, y: Vector3f16) -> (z: Vector3f16) { - return normalize(x - y * dot(y, x)); + return normalize(x - y * dot(y, x)) } vector3_orthonormalize_f32 :: proc(x, y: Vector3f32) -> (z: Vector3f32) { - return normalize(x - y * dot(y, x)); + return normalize(x - y * dot(y, x)) } vector3_orthonormalize_f64 :: proc(x, y: Vector3f64) -> (z: Vector3f64) { - return normalize(x - y * dot(y, x)); + return normalize(x - y * dot(y, x)) } vector3_orthonormalize :: proc{ vector3_orthonormalize_f16, vector3_orthonormalize_f32, vector3_orthonormalize_f64, -}; +} orthonormalize :: proc{ matrix2_orthonormalize_f16, matrix3_orthonormalize_f16, vector3_orthonormalize_f16, matrix2_orthonormalize_f32, matrix3_orthonormalize_f32, vector3_orthonormalize_f32, matrix2_orthonormalize_f64, matrix3_orthonormalize_f64, vector3_orthonormalize_f64, -}; +} matrix4_orientation_f16 :: proc(normal, up: Vector3f16) -> Matrix4f16 { if all(equal(normal, up)) { - return MATRIX4F16_IDENTITY; + return MATRIX4F16_IDENTITY } - rotation_axis := cross(up, normal); - angle := math.acos(dot(normal, up)); + rotation_axis := cross(up, normal) + angle := math.acos(dot(normal, up)) - return matrix4_rotate(angle, rotation_axis); + return matrix4_rotate(angle, rotation_axis) } matrix4_orientation_f32 :: proc(normal, up: Vector3f32) -> Matrix4f32 { if all(equal(normal, up)) { - return MATRIX4F32_IDENTITY; + return MATRIX4F32_IDENTITY } - rotation_axis := cross(up, normal); - angle := math.acos(dot(normal, up)); + rotation_axis := cross(up, normal) + angle := math.acos(dot(normal, up)) - return matrix4_rotate(angle, rotation_axis); + return matrix4_rotate(angle, rotation_axis) } matrix4_orientation_f64 :: proc(normal, up: Vector3f64) -> Matrix4f64 { if all(equal(normal, up)) { - return MATRIX4F64_IDENTITY; + return MATRIX4F64_IDENTITY } - rotation_axis := cross(up, normal); - angle := math.acos(dot(normal, up)); + rotation_axis := cross(up, normal) + angle := math.acos(dot(normal, up)) - return matrix4_rotate(angle, rotation_axis); + return matrix4_rotate(angle, rotation_axis) } matrix4_orientation :: proc{ matrix4_orientation_f16, matrix4_orientation_f32, matrix4_orientation_f64, -}; +} euclidean_from_polar_f16 :: proc(polar: Vector2f16) -> Vector3f16 { - latitude, longitude := polar.x, polar.y; - cx, sx := math.cos(latitude), math.sin(latitude); - cy, sy := math.cos(longitude), math.sin(longitude); + latitude, longitude := polar.x, polar.y + cx, sx := math.cos(latitude), math.sin(latitude) + cy, sy := math.cos(longitude), math.sin(longitude) return { cx*sy, sx, cx*cy, - }; + } } euclidean_from_polar_f32 :: proc(polar: Vector2f32) -> Vector3f32 { - latitude, longitude := polar.x, polar.y; - cx, sx := math.cos(latitude), math.sin(latitude); - cy, sy := math.cos(longitude), math.sin(longitude); + latitude, longitude := polar.x, polar.y + cx, sx := math.cos(latitude), math.sin(latitude) + cy, sy := math.cos(longitude), math.sin(longitude) return { cx*sy, sx, cx*cy, - }; + } } euclidean_from_polar_f64 :: proc(polar: Vector2f64) -> Vector3f64 { - latitude, longitude := polar.x, polar.y; - cx, sx := math.cos(latitude), math.sin(latitude); - cy, sy := math.cos(longitude), math.sin(longitude); + latitude, longitude := polar.x, polar.y + cx, sx := math.cos(latitude), math.sin(latitude) + cy, sy := math.cos(longitude), math.sin(longitude) return { cx*sy, sx, cx*cy, - }; + } } euclidean_from_polar :: proc{ euclidean_from_polar_f16, euclidean_from_polar_f32, euclidean_from_polar_f64, -}; +} polar_from_euclidean_f16 :: proc(euclidean: Vector3f16) -> Vector3f16 { - n := length(euclidean); - tmp := euclidean / n; + n := length(euclidean) + tmp := euclidean / n - xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z); + xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z) return { math.asin(tmp.y), math.atan2(tmp.x, tmp.z), xz_dist, - }; + } } polar_from_euclidean_f32 :: proc(euclidean: Vector3f32) -> Vector3f32 { - n := length(euclidean); - tmp := euclidean / n; + n := length(euclidean) + tmp := euclidean / n - xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z); + xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z) return { math.asin(tmp.y), math.atan2(tmp.x, tmp.z), xz_dist, - }; + } } polar_from_euclidean_f64 :: proc(euclidean: Vector3f64) -> Vector3f64 { - n := length(euclidean); - tmp := euclidean / n; + n := length(euclidean) + tmp := euclidean / n - xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z); + xz_dist := math.sqrt(tmp.x*tmp.x + tmp.z*tmp.z) return { math.asin(tmp.y), math.atan2(tmp.x, tmp.z), xz_dist, - }; + } } polar_from_euclidean :: proc{ polar_from_euclidean_f16, polar_from_euclidean_f32, polar_from_euclidean_f64, -}; +} diff --git a/core/math/linalg/specific_euler_angles.odin b/core/math/linalg/specific_euler_angles.odin index 000edda12..4d714be54 100644 --- a/core/math/linalg/specific_euler_angles.odin +++ b/core/math/linalg/specific_euler_angles.odin @@ -19,109 +19,109 @@ Euler_Angle_Order :: enum { } -quaternion_from_euler_angles :: proc{quaternion_from_euler_angles_f16, quaternion_from_euler_angles_f32, quaternion_from_euler_angles_f64}; -quaternion_from_euler_angle_x :: proc{quaternion_from_euler_angle_x_f16, quaternion_from_euler_angle_x_f32, quaternion_from_euler_angle_x_f64}; -quaternion_from_euler_angle_y :: proc{quaternion_from_euler_angle_y_f16, quaternion_from_euler_angle_y_f32, quaternion_from_euler_angle_y_f64}; -quaternion_from_euler_angle_z :: proc{quaternion_from_euler_angle_z_f16, quaternion_from_euler_angle_z_f32, quaternion_from_euler_angle_z_f64}; -quaternion_from_pitch_yaw_roll :: proc{quaternion_from_pitch_yaw_roll_f16, quaternion_from_pitch_yaw_roll_f32, quaternion_from_pitch_yaw_roll_f64}; +quaternion_from_euler_angles :: proc{quaternion_from_euler_angles_f16, quaternion_from_euler_angles_f32, quaternion_from_euler_angles_f64} +quaternion_from_euler_angle_x :: proc{quaternion_from_euler_angle_x_f16, quaternion_from_euler_angle_x_f32, quaternion_from_euler_angle_x_f64} +quaternion_from_euler_angle_y :: proc{quaternion_from_euler_angle_y_f16, quaternion_from_euler_angle_y_f32, quaternion_from_euler_angle_y_f64} +quaternion_from_euler_angle_z :: proc{quaternion_from_euler_angle_z_f16, quaternion_from_euler_angle_z_f32, quaternion_from_euler_angle_z_f64} +quaternion_from_pitch_yaw_roll :: proc{quaternion_from_pitch_yaw_roll_f16, quaternion_from_pitch_yaw_roll_f32, quaternion_from_pitch_yaw_roll_f64} -euler_angles_from_quaternion :: proc{euler_angles_from_quaternion_f16, euler_angles_from_quaternion_f32, euler_angles_from_quaternion_f64}; -euler_angles_xyz_from_quaternion :: proc{euler_angles_xyz_from_quaternion_f16, euler_angles_xyz_from_quaternion_f32, euler_angles_xyz_from_quaternion_f64}; -euler_angles_yxz_from_quaternion :: proc{euler_angles_yxz_from_quaternion_f16, euler_angles_yxz_from_quaternion_f32, euler_angles_yxz_from_quaternion_f64}; -euler_angles_xzx_from_quaternion :: proc{euler_angles_xzx_from_quaternion_f16, euler_angles_xzx_from_quaternion_f32, euler_angles_xzx_from_quaternion_f64}; -euler_angles_xyx_from_quaternion :: proc{euler_angles_xyx_from_quaternion_f16, euler_angles_xyx_from_quaternion_f32, euler_angles_xyx_from_quaternion_f64}; -euler_angles_yxy_from_quaternion :: proc{euler_angles_yxy_from_quaternion_f16, euler_angles_yxy_from_quaternion_f32, euler_angles_yxy_from_quaternion_f64}; -euler_angles_yzy_from_quaternion :: proc{euler_angles_yzy_from_quaternion_f16, euler_angles_yzy_from_quaternion_f32, euler_angles_yzy_from_quaternion_f64}; -euler_angles_zyz_from_quaternion :: proc{euler_angles_zyz_from_quaternion_f16, euler_angles_zyz_from_quaternion_f32, euler_angles_zyz_from_quaternion_f64}; -euler_angles_zxz_from_quaternion :: proc{euler_angles_zxz_from_quaternion_f16, euler_angles_zxz_from_quaternion_f32, euler_angles_zxz_from_quaternion_f64}; -euler_angles_xzy_from_quaternion :: proc{euler_angles_xzy_from_quaternion_f16, euler_angles_xzy_from_quaternion_f32, euler_angles_xzy_from_quaternion_f64}; -euler_angles_yzx_from_quaternion :: proc{euler_angles_yzx_from_quaternion_f16, euler_angles_yzx_from_quaternion_f32, euler_angles_yzx_from_quaternion_f64}; -euler_angles_zyx_from_quaternion :: proc{euler_angles_zyx_from_quaternion_f16, euler_angles_zyx_from_quaternion_f32, euler_angles_zyx_from_quaternion_f64}; -euler_angles_zxy_from_quaternion :: proc{euler_angles_zxy_from_quaternion_f16, euler_angles_zxy_from_quaternion_f32, euler_angles_zxy_from_quaternion_f64}; +euler_angles_from_quaternion :: proc{euler_angles_from_quaternion_f16, euler_angles_from_quaternion_f32, euler_angles_from_quaternion_f64} +euler_angles_xyz_from_quaternion :: proc{euler_angles_xyz_from_quaternion_f16, euler_angles_xyz_from_quaternion_f32, euler_angles_xyz_from_quaternion_f64} +euler_angles_yxz_from_quaternion :: proc{euler_angles_yxz_from_quaternion_f16, euler_angles_yxz_from_quaternion_f32, euler_angles_yxz_from_quaternion_f64} +euler_angles_xzx_from_quaternion :: proc{euler_angles_xzx_from_quaternion_f16, euler_angles_xzx_from_quaternion_f32, euler_angles_xzx_from_quaternion_f64} +euler_angles_xyx_from_quaternion :: proc{euler_angles_xyx_from_quaternion_f16, euler_angles_xyx_from_quaternion_f32, euler_angles_xyx_from_quaternion_f64} +euler_angles_yxy_from_quaternion :: proc{euler_angles_yxy_from_quaternion_f16, euler_angles_yxy_from_quaternion_f32, euler_angles_yxy_from_quaternion_f64} +euler_angles_yzy_from_quaternion :: proc{euler_angles_yzy_from_quaternion_f16, euler_angles_yzy_from_quaternion_f32, euler_angles_yzy_from_quaternion_f64} +euler_angles_zyz_from_quaternion :: proc{euler_angles_zyz_from_quaternion_f16, euler_angles_zyz_from_quaternion_f32, euler_angles_zyz_from_quaternion_f64} +euler_angles_zxz_from_quaternion :: proc{euler_angles_zxz_from_quaternion_f16, euler_angles_zxz_from_quaternion_f32, euler_angles_zxz_from_quaternion_f64} +euler_angles_xzy_from_quaternion :: proc{euler_angles_xzy_from_quaternion_f16, euler_angles_xzy_from_quaternion_f32, euler_angles_xzy_from_quaternion_f64} +euler_angles_yzx_from_quaternion :: proc{euler_angles_yzx_from_quaternion_f16, euler_angles_yzx_from_quaternion_f32, euler_angles_yzx_from_quaternion_f64} +euler_angles_zyx_from_quaternion :: proc{euler_angles_zyx_from_quaternion_f16, euler_angles_zyx_from_quaternion_f32, euler_angles_zyx_from_quaternion_f64} +euler_angles_zxy_from_quaternion :: proc{euler_angles_zxy_from_quaternion_f16, euler_angles_zxy_from_quaternion_f32, euler_angles_zxy_from_quaternion_f64} -roll_from_quaternion :: proc{roll_from_quaternion_f16, roll_from_quaternion_f32, roll_from_quaternion_f64}; -pitch_from_quaternion :: proc{pitch_from_quaternion_f16, pitch_from_quaternion_f32, pitch_from_quaternion_f64}; -yaw_from_quaternion :: proc{yaw_from_quaternion_f16, yaw_from_quaternion_f32, yaw_from_quaternion_f64}; -pitch_yaw_roll_from_quaternion :: proc{pitch_yaw_roll_from_quaternion_f16, pitch_yaw_roll_from_quaternion_f32, pitch_yaw_roll_from_quaternion_f64}; +roll_from_quaternion :: proc{roll_from_quaternion_f16, roll_from_quaternion_f32, roll_from_quaternion_f64} +pitch_from_quaternion :: proc{pitch_from_quaternion_f16, pitch_from_quaternion_f32, pitch_from_quaternion_f64} +yaw_from_quaternion :: proc{yaw_from_quaternion_f16, yaw_from_quaternion_f32, yaw_from_quaternion_f64} +pitch_yaw_roll_from_quaternion :: proc{pitch_yaw_roll_from_quaternion_f16, pitch_yaw_roll_from_quaternion_f32, pitch_yaw_roll_from_quaternion_f64} -matrix3_from_euler_angles :: proc{matrix3_from_euler_angles_f16, matrix3_from_euler_angles_f32, matrix3_from_euler_angles_f64}; -matrix3_from_euler_angle_x :: proc{matrix3_from_euler_angle_x_f16, matrix3_from_euler_angle_x_f32, matrix3_from_euler_angle_x_f64}; -matrix3_from_euler_angle_y :: proc{matrix3_from_euler_angle_y_f16, matrix3_from_euler_angle_y_f32, matrix3_from_euler_angle_y_f64}; -matrix3_from_euler_angle_z :: proc{matrix3_from_euler_angle_z_f16, matrix3_from_euler_angle_z_f32, matrix3_from_euler_angle_z_f64}; -matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f16, matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64}; -matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f16, matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64}; -matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f16, matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64}; -matrix3_from_euler_angles_xy :: proc{matrix3_from_euler_angles_xy_f16, matrix3_from_euler_angles_xy_f32, matrix3_from_euler_angles_xy_f64}; -matrix3_from_euler_angles_yx :: proc{matrix3_from_euler_angles_yx_f16, matrix3_from_euler_angles_yx_f32, matrix3_from_euler_angles_yx_f64}; -matrix3_from_euler_angles_xz :: proc{matrix3_from_euler_angles_xz_f16, matrix3_from_euler_angles_xz_f32, matrix3_from_euler_angles_xz_f64}; -matrix3_from_euler_angles_zx :: proc{matrix3_from_euler_angles_zx_f16, matrix3_from_euler_angles_zx_f32, matrix3_from_euler_angles_zx_f64}; -matrix3_from_euler_angles_yz :: proc{matrix3_from_euler_angles_yz_f16, matrix3_from_euler_angles_yz_f32, matrix3_from_euler_angles_yz_f64}; -matrix3_from_euler_angles_zy :: proc{matrix3_from_euler_angles_zy_f16, matrix3_from_euler_angles_zy_f32, matrix3_from_euler_angles_zy_f64}; -matrix3_from_euler_angles_xyz :: proc{matrix3_from_euler_angles_xyz_f16, matrix3_from_euler_angles_xyz_f32, matrix3_from_euler_angles_xyz_f64}; -matrix3_from_euler_angles_yxz :: proc{matrix3_from_euler_angles_yxz_f16, matrix3_from_euler_angles_yxz_f32, matrix3_from_euler_angles_yxz_f64}; -matrix3_from_euler_angles_xzx :: proc{matrix3_from_euler_angles_xzx_f16, matrix3_from_euler_angles_xzx_f32, matrix3_from_euler_angles_xzx_f64}; -matrix3_from_euler_angles_xyx :: proc{matrix3_from_euler_angles_xyx_f16, matrix3_from_euler_angles_xyx_f32, matrix3_from_euler_angles_xyx_f64}; -matrix3_from_euler_angles_yxy :: proc{matrix3_from_euler_angles_yxy_f16, matrix3_from_euler_angles_yxy_f32, matrix3_from_euler_angles_yxy_f64}; -matrix3_from_euler_angles_yzy :: proc{matrix3_from_euler_angles_yzy_f16, matrix3_from_euler_angles_yzy_f32, matrix3_from_euler_angles_yzy_f64}; -matrix3_from_euler_angles_zyz :: proc{matrix3_from_euler_angles_zyz_f16, matrix3_from_euler_angles_zyz_f32, matrix3_from_euler_angles_zyz_f64}; -matrix3_from_euler_angles_zxz :: proc{matrix3_from_euler_angles_zxz_f16, matrix3_from_euler_angles_zxz_f32, matrix3_from_euler_angles_zxz_f64}; -matrix3_from_euler_angles_xzy :: proc{matrix3_from_euler_angles_xzy_f16, matrix3_from_euler_angles_xzy_f32, matrix3_from_euler_angles_xzy_f64}; -matrix3_from_euler_angles_yzx :: proc{matrix3_from_euler_angles_yzx_f16, matrix3_from_euler_angles_yzx_f32, matrix3_from_euler_angles_yzx_f64}; -matrix3_from_euler_angles_zyx :: proc{matrix3_from_euler_angles_zyx_f16, matrix3_from_euler_angles_zyx_f32, matrix3_from_euler_angles_zyx_f64}; -matrix3_from_euler_angles_zxy :: proc{matrix3_from_euler_angles_zxy_f16, matrix3_from_euler_angles_zxy_f32, matrix3_from_euler_angles_zxy_f64}; -matrix3_from_yaw_pitch_roll :: proc{matrix3_from_yaw_pitch_roll_f16, matrix3_from_yaw_pitch_roll_f32, matrix3_from_yaw_pitch_roll_f64}; +matrix3_from_euler_angles :: proc{matrix3_from_euler_angles_f16, matrix3_from_euler_angles_f32, matrix3_from_euler_angles_f64} +matrix3_from_euler_angle_x :: proc{matrix3_from_euler_angle_x_f16, matrix3_from_euler_angle_x_f32, matrix3_from_euler_angle_x_f64} +matrix3_from_euler_angle_y :: proc{matrix3_from_euler_angle_y_f16, matrix3_from_euler_angle_y_f32, matrix3_from_euler_angle_y_f64} +matrix3_from_euler_angle_z :: proc{matrix3_from_euler_angle_z_f16, matrix3_from_euler_angle_z_f32, matrix3_from_euler_angle_z_f64} +matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f16, matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64} +matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f16, matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64} +matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f16, matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64} +matrix3_from_euler_angles_xy :: proc{matrix3_from_euler_angles_xy_f16, matrix3_from_euler_angles_xy_f32, matrix3_from_euler_angles_xy_f64} +matrix3_from_euler_angles_yx :: proc{matrix3_from_euler_angles_yx_f16, matrix3_from_euler_angles_yx_f32, matrix3_from_euler_angles_yx_f64} +matrix3_from_euler_angles_xz :: proc{matrix3_from_euler_angles_xz_f16, matrix3_from_euler_angles_xz_f32, matrix3_from_euler_angles_xz_f64} +matrix3_from_euler_angles_zx :: proc{matrix3_from_euler_angles_zx_f16, matrix3_from_euler_angles_zx_f32, matrix3_from_euler_angles_zx_f64} +matrix3_from_euler_angles_yz :: proc{matrix3_from_euler_angles_yz_f16, matrix3_from_euler_angles_yz_f32, matrix3_from_euler_angles_yz_f64} +matrix3_from_euler_angles_zy :: proc{matrix3_from_euler_angles_zy_f16, matrix3_from_euler_angles_zy_f32, matrix3_from_euler_angles_zy_f64} +matrix3_from_euler_angles_xyz :: proc{matrix3_from_euler_angles_xyz_f16, matrix3_from_euler_angles_xyz_f32, matrix3_from_euler_angles_xyz_f64} +matrix3_from_euler_angles_yxz :: proc{matrix3_from_euler_angles_yxz_f16, matrix3_from_euler_angles_yxz_f32, matrix3_from_euler_angles_yxz_f64} +matrix3_from_euler_angles_xzx :: proc{matrix3_from_euler_angles_xzx_f16, matrix3_from_euler_angles_xzx_f32, matrix3_from_euler_angles_xzx_f64} +matrix3_from_euler_angles_xyx :: proc{matrix3_from_euler_angles_xyx_f16, matrix3_from_euler_angles_xyx_f32, matrix3_from_euler_angles_xyx_f64} +matrix3_from_euler_angles_yxy :: proc{matrix3_from_euler_angles_yxy_f16, matrix3_from_euler_angles_yxy_f32, matrix3_from_euler_angles_yxy_f64} +matrix3_from_euler_angles_yzy :: proc{matrix3_from_euler_angles_yzy_f16, matrix3_from_euler_angles_yzy_f32, matrix3_from_euler_angles_yzy_f64} +matrix3_from_euler_angles_zyz :: proc{matrix3_from_euler_angles_zyz_f16, matrix3_from_euler_angles_zyz_f32, matrix3_from_euler_angles_zyz_f64} +matrix3_from_euler_angles_zxz :: proc{matrix3_from_euler_angles_zxz_f16, matrix3_from_euler_angles_zxz_f32, matrix3_from_euler_angles_zxz_f64} +matrix3_from_euler_angles_xzy :: proc{matrix3_from_euler_angles_xzy_f16, matrix3_from_euler_angles_xzy_f32, matrix3_from_euler_angles_xzy_f64} +matrix3_from_euler_angles_yzx :: proc{matrix3_from_euler_angles_yzx_f16, matrix3_from_euler_angles_yzx_f32, matrix3_from_euler_angles_yzx_f64} +matrix3_from_euler_angles_zyx :: proc{matrix3_from_euler_angles_zyx_f16, matrix3_from_euler_angles_zyx_f32, matrix3_from_euler_angles_zyx_f64} +matrix3_from_euler_angles_zxy :: proc{matrix3_from_euler_angles_zxy_f16, matrix3_from_euler_angles_zxy_f32, matrix3_from_euler_angles_zxy_f64} +matrix3_from_yaw_pitch_roll :: proc{matrix3_from_yaw_pitch_roll_f16, matrix3_from_yaw_pitch_roll_f32, matrix3_from_yaw_pitch_roll_f64} -euler_angles_from_matrix3 :: proc{euler_angles_from_matrix3_f16, euler_angles_from_matrix3_f32, euler_angles_from_matrix3_f64}; -euler_angles_xyz_from_matrix3 :: proc{euler_angles_xyz_from_matrix3_f16, euler_angles_xyz_from_matrix3_f32, euler_angles_xyz_from_matrix3_f64}; -euler_angles_yxz_from_matrix3 :: proc{euler_angles_yxz_from_matrix3_f16, euler_angles_yxz_from_matrix3_f32, euler_angles_yxz_from_matrix3_f64}; -euler_angles_xzx_from_matrix3 :: proc{euler_angles_xzx_from_matrix3_f16, euler_angles_xzx_from_matrix3_f32, euler_angles_xzx_from_matrix3_f64}; -euler_angles_xyx_from_matrix3 :: proc{euler_angles_xyx_from_matrix3_f16, euler_angles_xyx_from_matrix3_f32, euler_angles_xyx_from_matrix3_f64}; -euler_angles_yxy_from_matrix3 :: proc{euler_angles_yxy_from_matrix3_f16, euler_angles_yxy_from_matrix3_f32, euler_angles_yxy_from_matrix3_f64}; -euler_angles_yzy_from_matrix3 :: proc{euler_angles_yzy_from_matrix3_f16, euler_angles_yzy_from_matrix3_f32, euler_angles_yzy_from_matrix3_f64}; -euler_angles_zyz_from_matrix3 :: proc{euler_angles_zyz_from_matrix3_f16, euler_angles_zyz_from_matrix3_f32, euler_angles_zyz_from_matrix3_f64}; -euler_angles_zxz_from_matrix3 :: proc{euler_angles_zxz_from_matrix3_f16, euler_angles_zxz_from_matrix3_f32, euler_angles_zxz_from_matrix3_f64}; -euler_angles_xzy_from_matrix3 :: proc{euler_angles_xzy_from_matrix3_f16, euler_angles_xzy_from_matrix3_f32, euler_angles_xzy_from_matrix3_f64}; -euler_angles_yzx_from_matrix3 :: proc{euler_angles_yzx_from_matrix3_f16, euler_angles_yzx_from_matrix3_f32, euler_angles_yzx_from_matrix3_f64}; -euler_angles_zyx_from_matrix3 :: proc{euler_angles_zyx_from_matrix3_f16, euler_angles_zyx_from_matrix3_f32, euler_angles_zyx_from_matrix3_f64}; -euler_angles_zxy_from_matrix3 :: proc{euler_angles_zxy_from_matrix3_f16, euler_angles_zxy_from_matrix3_f32, euler_angles_zxy_from_matrix3_f64}; +euler_angles_from_matrix3 :: proc{euler_angles_from_matrix3_f16, euler_angles_from_matrix3_f32, euler_angles_from_matrix3_f64} +euler_angles_xyz_from_matrix3 :: proc{euler_angles_xyz_from_matrix3_f16, euler_angles_xyz_from_matrix3_f32, euler_angles_xyz_from_matrix3_f64} +euler_angles_yxz_from_matrix3 :: proc{euler_angles_yxz_from_matrix3_f16, euler_angles_yxz_from_matrix3_f32, euler_angles_yxz_from_matrix3_f64} +euler_angles_xzx_from_matrix3 :: proc{euler_angles_xzx_from_matrix3_f16, euler_angles_xzx_from_matrix3_f32, euler_angles_xzx_from_matrix3_f64} +euler_angles_xyx_from_matrix3 :: proc{euler_angles_xyx_from_matrix3_f16, euler_angles_xyx_from_matrix3_f32, euler_angles_xyx_from_matrix3_f64} +euler_angles_yxy_from_matrix3 :: proc{euler_angles_yxy_from_matrix3_f16, euler_angles_yxy_from_matrix3_f32, euler_angles_yxy_from_matrix3_f64} +euler_angles_yzy_from_matrix3 :: proc{euler_angles_yzy_from_matrix3_f16, euler_angles_yzy_from_matrix3_f32, euler_angles_yzy_from_matrix3_f64} +euler_angles_zyz_from_matrix3 :: proc{euler_angles_zyz_from_matrix3_f16, euler_angles_zyz_from_matrix3_f32, euler_angles_zyz_from_matrix3_f64} +euler_angles_zxz_from_matrix3 :: proc{euler_angles_zxz_from_matrix3_f16, euler_angles_zxz_from_matrix3_f32, euler_angles_zxz_from_matrix3_f64} +euler_angles_xzy_from_matrix3 :: proc{euler_angles_xzy_from_matrix3_f16, euler_angles_xzy_from_matrix3_f32, euler_angles_xzy_from_matrix3_f64} +euler_angles_yzx_from_matrix3 :: proc{euler_angles_yzx_from_matrix3_f16, euler_angles_yzx_from_matrix3_f32, euler_angles_yzx_from_matrix3_f64} +euler_angles_zyx_from_matrix3 :: proc{euler_angles_zyx_from_matrix3_f16, euler_angles_zyx_from_matrix3_f32, euler_angles_zyx_from_matrix3_f64} +euler_angles_zxy_from_matrix3 :: proc{euler_angles_zxy_from_matrix3_f16, euler_angles_zxy_from_matrix3_f32, euler_angles_zxy_from_matrix3_f64} -matrix4_from_euler_angles :: proc{matrix4_from_euler_angles_f16, matrix4_from_euler_angles_f32, matrix4_from_euler_angles_f64}; -matrix4_from_euler_angle_x :: proc{matrix4_from_euler_angle_x_f16, matrix4_from_euler_angle_x_f32, matrix4_from_euler_angle_x_f64}; -matrix4_from_euler_angle_y :: proc{matrix4_from_euler_angle_y_f16, matrix4_from_euler_angle_y_f32, matrix4_from_euler_angle_y_f64}; -matrix4_from_euler_angle_z :: proc{matrix4_from_euler_angle_z_f16, matrix4_from_euler_angle_z_f32, matrix4_from_euler_angle_z_f64}; -matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f16, matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64}; -matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f16, matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64}; -matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f16, matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64}; -matrix4_from_euler_angles_xy :: proc{matrix4_from_euler_angles_xy_f16, matrix4_from_euler_angles_xy_f32, matrix4_from_euler_angles_xy_f64}; -matrix4_from_euler_angles_yx :: proc{matrix4_from_euler_angles_yx_f16, matrix4_from_euler_angles_yx_f32, matrix4_from_euler_angles_yx_f64}; -matrix4_from_euler_angles_xz :: proc{matrix4_from_euler_angles_xz_f16, matrix4_from_euler_angles_xz_f32, matrix4_from_euler_angles_xz_f64}; -matrix4_from_euler_angles_zx :: proc{matrix4_from_euler_angles_zx_f16, matrix4_from_euler_angles_zx_f32, matrix4_from_euler_angles_zx_f64}; -matrix4_from_euler_angles_yz :: proc{matrix4_from_euler_angles_yz_f16, matrix4_from_euler_angles_yz_f32, matrix4_from_euler_angles_yz_f64}; -matrix4_from_euler_angles_zy :: proc{matrix4_from_euler_angles_zy_f16, matrix4_from_euler_angles_zy_f32, matrix4_from_euler_angles_zy_f64}; -matrix4_from_euler_angles_xyz :: proc{matrix4_from_euler_angles_xyz_f16, matrix4_from_euler_angles_xyz_f32, matrix4_from_euler_angles_xyz_f64}; -matrix4_from_euler_angles_yxz :: proc{matrix4_from_euler_angles_yxz_f16, matrix4_from_euler_angles_yxz_f32, matrix4_from_euler_angles_yxz_f64}; -matrix4_from_euler_angles_xzx :: proc{matrix4_from_euler_angles_xzx_f16, matrix4_from_euler_angles_xzx_f32, matrix4_from_euler_angles_xzx_f64}; -matrix4_from_euler_angles_xyx :: proc{matrix4_from_euler_angles_xyx_f16, matrix4_from_euler_angles_xyx_f32, matrix4_from_euler_angles_xyx_f64}; -matrix4_from_euler_angles_yxy :: proc{matrix4_from_euler_angles_yxy_f16, matrix4_from_euler_angles_yxy_f32, matrix4_from_euler_angles_yxy_f64}; -matrix4_from_euler_angles_yzy :: proc{matrix4_from_euler_angles_yzy_f16, matrix4_from_euler_angles_yzy_f32, matrix4_from_euler_angles_yzy_f64}; -matrix4_from_euler_angles_zyz :: proc{matrix4_from_euler_angles_zyz_f16, matrix4_from_euler_angles_zyz_f32, matrix4_from_euler_angles_zyz_f64}; -matrix4_from_euler_angles_zxz :: proc{matrix4_from_euler_angles_zxz_f16, matrix4_from_euler_angles_zxz_f32, matrix4_from_euler_angles_zxz_f64}; -matrix4_from_euler_angles_xzy :: proc{matrix4_from_euler_angles_xzy_f16, matrix4_from_euler_angles_xzy_f32, matrix4_from_euler_angles_xzy_f64}; -matrix4_from_euler_angles_yzx :: proc{matrix4_from_euler_angles_yzx_f16, matrix4_from_euler_angles_yzx_f32, matrix4_from_euler_angles_yzx_f64}; -matrix4_from_euler_angles_zyx :: proc{matrix4_from_euler_angles_zyx_f16, matrix4_from_euler_angles_zyx_f32, matrix4_from_euler_angles_zyx_f64}; -matrix4_from_euler_angles_zxy :: proc{matrix4_from_euler_angles_zxy_f16, matrix4_from_euler_angles_zxy_f32, matrix4_from_euler_angles_zxy_f64}; -matrix4_from_yaw_pitch_roll :: proc{matrix4_from_yaw_pitch_roll_f16, matrix4_from_yaw_pitch_roll_f32, matrix4_from_yaw_pitch_roll_f64}; +matrix4_from_euler_angles :: proc{matrix4_from_euler_angles_f16, matrix4_from_euler_angles_f32, matrix4_from_euler_angles_f64} +matrix4_from_euler_angle_x :: proc{matrix4_from_euler_angle_x_f16, matrix4_from_euler_angle_x_f32, matrix4_from_euler_angle_x_f64} +matrix4_from_euler_angle_y :: proc{matrix4_from_euler_angle_y_f16, matrix4_from_euler_angle_y_f32, matrix4_from_euler_angle_y_f64} +matrix4_from_euler_angle_z :: proc{matrix4_from_euler_angle_z_f16, matrix4_from_euler_angle_z_f32, matrix4_from_euler_angle_z_f64} +matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f16, matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64} +matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f16, matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64} +matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f16, matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64} +matrix4_from_euler_angles_xy :: proc{matrix4_from_euler_angles_xy_f16, matrix4_from_euler_angles_xy_f32, matrix4_from_euler_angles_xy_f64} +matrix4_from_euler_angles_yx :: proc{matrix4_from_euler_angles_yx_f16, matrix4_from_euler_angles_yx_f32, matrix4_from_euler_angles_yx_f64} +matrix4_from_euler_angles_xz :: proc{matrix4_from_euler_angles_xz_f16, matrix4_from_euler_angles_xz_f32, matrix4_from_euler_angles_xz_f64} +matrix4_from_euler_angles_zx :: proc{matrix4_from_euler_angles_zx_f16, matrix4_from_euler_angles_zx_f32, matrix4_from_euler_angles_zx_f64} +matrix4_from_euler_angles_yz :: proc{matrix4_from_euler_angles_yz_f16, matrix4_from_euler_angles_yz_f32, matrix4_from_euler_angles_yz_f64} +matrix4_from_euler_angles_zy :: proc{matrix4_from_euler_angles_zy_f16, matrix4_from_euler_angles_zy_f32, matrix4_from_euler_angles_zy_f64} +matrix4_from_euler_angles_xyz :: proc{matrix4_from_euler_angles_xyz_f16, matrix4_from_euler_angles_xyz_f32, matrix4_from_euler_angles_xyz_f64} +matrix4_from_euler_angles_yxz :: proc{matrix4_from_euler_angles_yxz_f16, matrix4_from_euler_angles_yxz_f32, matrix4_from_euler_angles_yxz_f64} +matrix4_from_euler_angles_xzx :: proc{matrix4_from_euler_angles_xzx_f16, matrix4_from_euler_angles_xzx_f32, matrix4_from_euler_angles_xzx_f64} +matrix4_from_euler_angles_xyx :: proc{matrix4_from_euler_angles_xyx_f16, matrix4_from_euler_angles_xyx_f32, matrix4_from_euler_angles_xyx_f64} +matrix4_from_euler_angles_yxy :: proc{matrix4_from_euler_angles_yxy_f16, matrix4_from_euler_angles_yxy_f32, matrix4_from_euler_angles_yxy_f64} +matrix4_from_euler_angles_yzy :: proc{matrix4_from_euler_angles_yzy_f16, matrix4_from_euler_angles_yzy_f32, matrix4_from_euler_angles_yzy_f64} +matrix4_from_euler_angles_zyz :: proc{matrix4_from_euler_angles_zyz_f16, matrix4_from_euler_angles_zyz_f32, matrix4_from_euler_angles_zyz_f64} +matrix4_from_euler_angles_zxz :: proc{matrix4_from_euler_angles_zxz_f16, matrix4_from_euler_angles_zxz_f32, matrix4_from_euler_angles_zxz_f64} +matrix4_from_euler_angles_xzy :: proc{matrix4_from_euler_angles_xzy_f16, matrix4_from_euler_angles_xzy_f32, matrix4_from_euler_angles_xzy_f64} +matrix4_from_euler_angles_yzx :: proc{matrix4_from_euler_angles_yzx_f16, matrix4_from_euler_angles_yzx_f32, matrix4_from_euler_angles_yzx_f64} +matrix4_from_euler_angles_zyx :: proc{matrix4_from_euler_angles_zyx_f16, matrix4_from_euler_angles_zyx_f32, matrix4_from_euler_angles_zyx_f64} +matrix4_from_euler_angles_zxy :: proc{matrix4_from_euler_angles_zxy_f16, matrix4_from_euler_angles_zxy_f32, matrix4_from_euler_angles_zxy_f64} +matrix4_from_yaw_pitch_roll :: proc{matrix4_from_yaw_pitch_roll_f16, matrix4_from_yaw_pitch_roll_f32, matrix4_from_yaw_pitch_roll_f64} -euler_angles_from_matrix4 :: proc{euler_angles_from_matrix4_f16, euler_angles_from_matrix4_f32, euler_angles_from_matrix4_f64}; -euler_angles_xyz_from_matrix4 :: proc{euler_angles_xyz_from_matrix4_f16, euler_angles_xyz_from_matrix4_f32, euler_angles_xyz_from_matrix4_f64}; -euler_angles_yxz_from_matrix4 :: proc{euler_angles_yxz_from_matrix4_f16, euler_angles_yxz_from_matrix4_f32, euler_angles_yxz_from_matrix4_f64}; -euler_angles_xzx_from_matrix4 :: proc{euler_angles_xzx_from_matrix4_f16, euler_angles_xzx_from_matrix4_f32, euler_angles_xzx_from_matrix4_f64}; -euler_angles_xyx_from_matrix4 :: proc{euler_angles_xyx_from_matrix4_f16, euler_angles_xyx_from_matrix4_f32, euler_angles_xyx_from_matrix4_f64}; -euler_angles_yxy_from_matrix4 :: proc{euler_angles_yxy_from_matrix4_f16, euler_angles_yxy_from_matrix4_f32, euler_angles_yxy_from_matrix4_f64}; -euler_angles_yzy_from_matrix4 :: proc{euler_angles_yzy_from_matrix4_f16, euler_angles_yzy_from_matrix4_f32, euler_angles_yzy_from_matrix4_f64}; -euler_angles_zyz_from_matrix4 :: proc{euler_angles_zyz_from_matrix4_f16, euler_angles_zyz_from_matrix4_f32, euler_angles_zyz_from_matrix4_f64}; -euler_angles_zxz_from_matrix4 :: proc{euler_angles_zxz_from_matrix4_f16, euler_angles_zxz_from_matrix4_f32, euler_angles_zxz_from_matrix4_f64}; -euler_angles_xzy_from_matrix4 :: proc{euler_angles_xzy_from_matrix4_f16, euler_angles_xzy_from_matrix4_f32, euler_angles_xzy_from_matrix4_f64}; -euler_angles_yzx_from_matrix4 :: proc{euler_angles_yzx_from_matrix4_f16, euler_angles_yzx_from_matrix4_f32, euler_angles_yzx_from_matrix4_f64}; -euler_angles_zyx_from_matrix4 :: proc{euler_angles_zyx_from_matrix4_f16, euler_angles_zyx_from_matrix4_f32, euler_angles_zyx_from_matrix4_f64}; -euler_angles_zxy_from_matrix4 :: proc{euler_angles_zxy_from_matrix4_f16, euler_angles_zxy_from_matrix4_f32, euler_angles_zxy_from_matrix4_f64}; +euler_angles_from_matrix4 :: proc{euler_angles_from_matrix4_f16, euler_angles_from_matrix4_f32, euler_angles_from_matrix4_f64} +euler_angles_xyz_from_matrix4 :: proc{euler_angles_xyz_from_matrix4_f16, euler_angles_xyz_from_matrix4_f32, euler_angles_xyz_from_matrix4_f64} +euler_angles_yxz_from_matrix4 :: proc{euler_angles_yxz_from_matrix4_f16, euler_angles_yxz_from_matrix4_f32, euler_angles_yxz_from_matrix4_f64} +euler_angles_xzx_from_matrix4 :: proc{euler_angles_xzx_from_matrix4_f16, euler_angles_xzx_from_matrix4_f32, euler_angles_xzx_from_matrix4_f64} +euler_angles_xyx_from_matrix4 :: proc{euler_angles_xyx_from_matrix4_f16, euler_angles_xyx_from_matrix4_f32, euler_angles_xyx_from_matrix4_f64} +euler_angles_yxy_from_matrix4 :: proc{euler_angles_yxy_from_matrix4_f16, euler_angles_yxy_from_matrix4_f32, euler_angles_yxy_from_matrix4_f64} +euler_angles_yzy_from_matrix4 :: proc{euler_angles_yzy_from_matrix4_f16, euler_angles_yzy_from_matrix4_f32, euler_angles_yzy_from_matrix4_f64} +euler_angles_zyz_from_matrix4 :: proc{euler_angles_zyz_from_matrix4_f16, euler_angles_zyz_from_matrix4_f32, euler_angles_zyz_from_matrix4_f64} +euler_angles_zxz_from_matrix4 :: proc{euler_angles_zxz_from_matrix4_f16, euler_angles_zxz_from_matrix4_f32, euler_angles_zxz_from_matrix4_f64} +euler_angles_xzy_from_matrix4 :: proc{euler_angles_xzy_from_matrix4_f16, euler_angles_xzy_from_matrix4_f32, euler_angles_xzy_from_matrix4_f64} +euler_angles_yzx_from_matrix4 :: proc{euler_angles_yzx_from_matrix4_f16, euler_angles_yzx_from_matrix4_f32, euler_angles_yzx_from_matrix4_f64} +euler_angles_zyx_from_matrix4 :: proc{euler_angles_zyx_from_matrix4_f16, euler_angles_zyx_from_matrix4_f32, euler_angles_zyx_from_matrix4_f64} +euler_angles_zxy_from_matrix4 :: proc{euler_angles_zxy_from_matrix4_f16, euler_angles_zxy_from_matrix4_f32, euler_angles_zxy_from_matrix4_f64} diff --git a/core/math/linalg/specific_euler_angles_f16.odin b/core/math/linalg/specific_euler_angles_f16.odin index bcfac6039..d0fb1beb3 100644 --- a/core/math/linalg/specific_euler_angles_f16.odin +++ b/core/math/linalg/specific_euler_angles_f16.odin @@ -4,206 +4,206 @@ import "core:math" euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m) } - return; + return } euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m) } - return; + return } euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m) } - return; + return } matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) { switch order { - case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) { switch order { - case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 { - X :: quaternion_from_euler_angle_x; - Y :: quaternion_from_euler_angle_y; - Z :: quaternion_from_euler_angle_z; + X :: quaternion_from_euler_angle_x + Y :: quaternion_from_euler_angle_y + Z :: quaternion_from_euler_angle_z - q1, q2, q3: Quaternionf16; + q1, q2, q3: Quaternionf16 switch order { - case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3); - case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3); - case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3); - case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3); - case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3); - case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3); - case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3); - case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3); - case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3); - case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3); - case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3); + case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3) + case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3) + case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3) + case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3) + case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3) + case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3) + case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3) + case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3) + case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3) + case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3) + case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3) + case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3) } - return q1 * (q2 * q3); + return q1 * (q2 * q3) } // Quaternionf16s quaternion_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (q: Quaternionf16) { - return quaternion_angle_axis_f16(angle_x, {1, 0, 0}); + return quaternion_angle_axis_f16(angle_x, {1, 0, 0}) } quaternion_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (q: Quaternionf16) { - return quaternion_angle_axis_f16(angle_y, {0, 1, 0}); + return quaternion_angle_axis_f16(angle_y, {0, 1, 0}) } quaternion_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (q: Quaternionf16) { - return quaternion_angle_axis_f16(angle_z, {0, 0, 1}); + return quaternion_angle_axis_f16(angle_z, {0, 0, 1}) } quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf16 { - a, b, c := pitch, yaw, roll; + a, b, c := pitch, yaw, roll - ca, sa := math.cos(a*0.5), math.sin(a*0.5); - cb, sb := math.cos(b*0.5), math.sin(b*0.5); - cc, sc := math.cos(c*0.5), math.sin(c*0.5); + ca, sa := math.cos(a*0.5), math.sin(a*0.5) + cb, sb := math.cos(b*0.5), math.sin(b*0.5) + cc, sc := math.cos(c*0.5), math.sin(c*0.5) - q: Quaternionf16; - q.x = sa*cb*cc - ca*sb*sc; - q.y = ca*sb*cc + sa*cb*sc; - q.z = ca*cb*sc - sa*sb*cc; - q.w = ca*cb*cc + sa*sb*sc; - return q; + q: Quaternionf16 + q.x = sa*cb*cc - ca*sb*sc + q.y = ca*sb*cc + sa*cb*sc + q.z = ca*cb*sc - sa*sb*cc + q.w = ca*cb*cc + sa*sb*sc + return q } roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { - return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z); + return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) } pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { - y := 2 * (q.y*q.z + q.w*q.w); - x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + y := 2 * (q.y*q.z + q.w*q.w) + x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z if abs(x) <= F16_EPSILON && abs(y) <= F16_EPSILON { - return 2 * math.atan2(q.x, q.w); + return 2 * math.atan2(q.x, q.w) } - return math.atan2(y, x); + return math.atan2(y, x) } yaw_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 { - return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)); + return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) } pitch_yaw_roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> (pitch, yaw, roll: f16) { - pitch = pitch_from_quaternion(q); - yaw = yaw_from_quaternion(q); - roll = roll_from_quaternion(q); - return; + pitch = pitch_from_quaternion(q) + yaw = yaw_from_quaternion(q) + roll = roll_from_quaternion(q) + return } euler_angles_xyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) { - return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) } @@ -211,524 +211,524 @@ euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + return } matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + return } matrix3_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) } matrix3_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix3f16) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) } matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + return } matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return } matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + return } matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + return } matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + return } matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + return } matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return m } euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } @@ -736,621 +736,621 @@ euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) { matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + m[3][3] = 1 + return } matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f16) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + m[3][3] = 1 + return } matrix4_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) } matrix4_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix4f16) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) } matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[0][3] = 0; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[1][3] = 0; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[0][3] = 0 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[1][3] = 0 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[1][3] = 0; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[1][3] = 0 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[0][3] = 0; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[1][3] = 0; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[0][3] = 0 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[1][3] = 0 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[0][3] = 0; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[0][3] = 0 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[0][3] = 0; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[0][3] = 0 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[1][3] = 0; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[1][3] = 0 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[0][3] = 0; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[1][3] = 0; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[0][3] = 0 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[1][3] = 0 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[0][3] = 0; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[1][3] = 0; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[0][3] = 0 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[1][3] = 0 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[0][3] = 0; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[0][3] = 0 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[0][3] = 0; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[1][3] = 0; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[0][3] = 0 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[1][3] = 0 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[0][3] = 0; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[0][3] = 0 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return m } euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } diff --git a/core/math/linalg/specific_euler_angles_f32.odin b/core/math/linalg/specific_euler_angles_f32.odin index e7069bd81..6ae1b0fa0 100644 --- a/core/math/linalg/specific_euler_angles_f32.odin +++ b/core/math/linalg/specific_euler_angles_f32.odin @@ -4,206 +4,206 @@ import "core:math" euler_angles_from_matrix3_f32 :: proc(m: Matrix3f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m) } - return; + return } euler_angles_from_matrix4_f32 :: proc(m: Matrix4f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m) } - return; + return } euler_angles_from_quaternion_f32 :: proc(m: Quaternionf32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m) } - return; + return } matrix3_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix3f32) { switch order { - case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } matrix4_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix4f32) { switch order { - case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } quaternion_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> Quaternionf32 { - X :: quaternion_from_euler_angle_x; - Y :: quaternion_from_euler_angle_y; - Z :: quaternion_from_euler_angle_z; + X :: quaternion_from_euler_angle_x + Y :: quaternion_from_euler_angle_y + Z :: quaternion_from_euler_angle_z - q1, q2, q3: Quaternionf32; + q1, q2, q3: Quaternionf32 switch order { - case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3); - case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3); - case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3); - case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3); - case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3); - case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3); - case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3); - case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3); - case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3); - case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3); - case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3); + case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3) + case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3) + case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3) + case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3) + case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3) + case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3) + case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3) + case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3) + case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3) + case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3) + case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3) + case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3) } - return q1 * (q2 * q3); + return q1 * (q2 * q3) } // Quaternionf32s quaternion_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (q: Quaternionf32) { - return quaternion_angle_axis_f32(angle_x, {1, 0, 0}); + return quaternion_angle_axis_f32(angle_x, {1, 0, 0}) } quaternion_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (q: Quaternionf32) { - return quaternion_angle_axis_f32(angle_y, {0, 1, 0}); + return quaternion_angle_axis_f32(angle_y, {0, 1, 0}) } quaternion_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (q: Quaternionf32) { - return quaternion_angle_axis_f32(angle_z, {0, 0, 1}); + return quaternion_angle_axis_f32(angle_z, {0, 0, 1}) } quaternion_from_pitch_yaw_roll_f32 :: proc(pitch, yaw, roll: f32) -> Quaternionf32 { - a, b, c := pitch, yaw, roll; + a, b, c := pitch, yaw, roll - ca, sa := math.cos(a*0.5), math.sin(a*0.5); - cb, sb := math.cos(b*0.5), math.sin(b*0.5); - cc, sc := math.cos(c*0.5), math.sin(c*0.5); + ca, sa := math.cos(a*0.5), math.sin(a*0.5) + cb, sb := math.cos(b*0.5), math.sin(b*0.5) + cc, sc := math.cos(c*0.5), math.sin(c*0.5) - q: Quaternionf32; - q.x = sa*cb*cc - ca*sb*sc; - q.y = ca*sb*cc + sa*cb*sc; - q.z = ca*cb*sc - sa*sb*cc; - q.w = ca*cb*cc + sa*sb*sc; - return q; + q: Quaternionf32 + q.x = sa*cb*cc - ca*sb*sc + q.y = ca*sb*cc + sa*cb*sc + q.z = ca*cb*sc - sa*sb*cc + q.w = ca*cb*cc + sa*sb*sc + return q } roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { - return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z); + return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) } pitch_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { - y := 2 * (q.y*q.z + q.w*q.w); - x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + y := 2 * (q.y*q.z + q.w*q.w) + x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z if abs(x) <= F32_EPSILON && abs(y) <= F32_EPSILON { - return 2 * math.atan2(q.x, q.w); + return 2 * math.atan2(q.x, q.w) } - return math.atan2(y, x); + return math.atan2(y, x) } yaw_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 { - return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)); + return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) } pitch_yaw_roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> (pitch, yaw, roll: f32) { - pitch = pitch_from_quaternion(q); - yaw = yaw_from_quaternion(q); - roll = roll_from_quaternion(q); - return; + pitch = pitch_from_quaternion(q) + yaw = yaw_from_quaternion(q) + roll = roll_from_quaternion(q) + return } euler_angles_xyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) { - return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) } @@ -211,524 +211,524 @@ euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f matrix3_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix3f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix3f32) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix3f32) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix3f32) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix3f32) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix3f32) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix3f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + return } matrix3_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix3f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + return } matrix3_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) } matrix3_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix3f32) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) } matrix3_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + return } matrix3_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return } matrix3_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + return } matrix3_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + return } matrix3_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + return } matrix3_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + return } matrix3_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return m } euler_angles_xyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } @@ -736,621 +736,621 @@ euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) { matrix4_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix4f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix4f32) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix4f32) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix4f32) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix4f32) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix4f32) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix4f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + m[3][3] = 1 + return } matrix4_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix4f32) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + m[3][3] = 1 + return } matrix4_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) } matrix4_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix4f32) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) } matrix4_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[0][3] = 0; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[1][3] = 0; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[0][3] = 0 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[1][3] = 0 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[1][3] = 0; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[1][3] = 0 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[0][3] = 0; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[1][3] = 0; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[0][3] = 0 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[1][3] = 0 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[0][3] = 0; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[0][3] = 0 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[0][3] = 0; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[0][3] = 0 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[1][3] = 0; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[1][3] = 0 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[0][3] = 0; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[1][3] = 0; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[0][3] = 0 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[1][3] = 0 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[0][3] = 0; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[1][3] = 0; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[0][3] = 0 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[1][3] = 0 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[0][3] = 0; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[0][3] = 0 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[0][3] = 0; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[1][3] = 0; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[0][3] = 0 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[1][3] = 0 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[0][3] = 0; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[0][3] = 0 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return m } euler_angles_xyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } diff --git a/core/math/linalg/specific_euler_angles_f64.odin b/core/math/linalg/specific_euler_angles_f64.odin index a62c2d5e8..efaddd651 100644 --- a/core/math/linalg/specific_euler_angles_f64.odin +++ b/core/math/linalg/specific_euler_angles_f64.odin @@ -4,206 +4,206 @@ import "core:math" euler_angles_from_matrix3_f64 :: proc(m: Matrix3f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m) } - return; + return } euler_angles_from_matrix4_f64 :: proc(m: Matrix4f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m) } - return; + return } euler_angles_from_quaternion_f64 :: proc(m: Quaternionf64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) { switch order { - case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m); - case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m); - case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m); - case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m); - case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m); - case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m); - case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m); - case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m); - case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m); - case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m); - case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m); - case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m); + case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m) + case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m) + case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m) + case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m) + case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m) + case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m) + case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m) + case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m) + case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m) + case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m) + case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m) + case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m) } - return; + return } matrix3_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix3f64) { switch order { - case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } matrix4_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix4f64) { switch order { - case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3); - case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3); - case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3); - case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3); - case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3); - case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3); - case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3); - case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3); - case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3); - case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3); - case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3); + case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3); + case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3); + case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Z(t3); + case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), X(t3); + case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Y(t3); + case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), X(t3); + case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), X(t3); + case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), X(t3); + case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3) // m1, m2, m3 = Y(t1), X(t2), Y(t3); + case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3) // m1, m2, m3 = Y(t1), Z(t2), Y(t3); + case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3) // m1, m2, m3 = Z(t1), X(t2), Z(t3); + case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3) // m1, m2, m3 = Z(t1), Y(t2), Z(t3); } - return; + return } quaternion_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> Quaternionf64 { - X :: quaternion_from_euler_angle_x; - Y :: quaternion_from_euler_angle_y; - Z :: quaternion_from_euler_angle_z; + X :: quaternion_from_euler_angle_x + Y :: quaternion_from_euler_angle_y + Z :: quaternion_from_euler_angle_z - q1, q2, q3: Quaternionf64; + q1, q2, q3: Quaternionf64 switch order { - case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3); - case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3); - case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3); - case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3); - case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3); - case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3); - case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3); - case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3); - case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3); - case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3); - case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3); - case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3); + case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3) + case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3) + case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3) + case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3) + case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3) + case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3) + case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3) + case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3) + case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3) + case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3) + case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3) + case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3) } - return q1 * (q2 * q3); + return q1 * (q2 * q3) } // Quaternionf64s quaternion_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (q: Quaternionf64) { - return quaternion_angle_axis_f64(angle_x, {1, 0, 0}); + return quaternion_angle_axis_f64(angle_x, {1, 0, 0}) } quaternion_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (q: Quaternionf64) { - return quaternion_angle_axis_f64(angle_y, {0, 1, 0}); + return quaternion_angle_axis_f64(angle_y, {0, 1, 0}) } quaternion_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (q: Quaternionf64) { - return quaternion_angle_axis_f64(angle_z, {0, 0, 1}); + return quaternion_angle_axis_f64(angle_z, {0, 0, 1}) } quaternion_from_pitch_yaw_roll_f64 :: proc(pitch, yaw, roll: f64) -> Quaternionf64 { - a, b, c := pitch, yaw, roll; + a, b, c := pitch, yaw, roll - ca, sa := math.cos(a*0.5), math.sin(a*0.5); - cb, sb := math.cos(b*0.5), math.sin(b*0.5); - cc, sc := math.cos(c*0.5), math.sin(c*0.5); + ca, sa := math.cos(a*0.5), math.sin(a*0.5) + cb, sb := math.cos(b*0.5), math.sin(b*0.5) + cc, sc := math.cos(c*0.5), math.sin(c*0.5) - q: Quaternionf64; - q.x = sa*cb*cc - ca*sb*sc; - q.y = ca*sb*cc + sa*cb*sc; - q.z = ca*cb*sc - sa*sb*cc; - q.w = ca*cb*cc + sa*sb*sc; - return q; + q: Quaternionf64 + q.x = sa*cb*cc - ca*sb*sc + q.y = ca*sb*cc + sa*cb*sc + q.z = ca*cb*sc - sa*sb*cc + q.w = ca*cb*cc + sa*sb*sc + return q } roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { - return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z); + return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z) } pitch_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { - y := 2 * (q.y*q.z + q.w*q.w); - x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z; + y := 2 * (q.y*q.z + q.w*q.w) + x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z if abs(x) <= F64_EPSILON && abs(y) <= F64_EPSILON { - return 2 * math.atan2(q.x, q.w); + return 2 * math.atan2(q.x, q.w) } - return math.atan2(y, x); + return math.atan2(y, x) } yaw_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 { - return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)); + return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1)) } pitch_yaw_roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> (pitch, yaw, roll: f64) { - pitch = pitch_from_quaternion(q); - yaw = yaw_from_quaternion(q); - roll = roll_from_quaternion(q); - return; + pitch = pitch_from_quaternion(q) + yaw = yaw_from_quaternion(q) + roll = roll_from_quaternion(q) + return } euler_angles_xyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_xzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_yzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q)) } euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) { - return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)); + return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q)) } @@ -211,524 +211,524 @@ euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f matrix3_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix3f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix3f64) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix3f64) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix3f64) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + return } matrix3_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix3f64) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + return } matrix3_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix3f64) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + return } matrix3_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix3f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + return } matrix3_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix3f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + return } matrix3_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x)) } matrix3_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)); + return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z)) } matrix3_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix3f64) { - return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)); + return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y)) } matrix3_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + return } matrix3_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return } matrix3_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + return } matrix3_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + return } matrix3_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + return } matrix3_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + return } matrix3_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + return } matrix3_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + return } matrix3_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + return } matrix3_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + return m } euler_angles_xyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } @@ -736,621 +736,621 @@ euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) { matrix4_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix4f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix4f64) { - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix4f64) { - cos_z, sin_z := math.cos(angle_z), math.sin(angle_z); - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z, sin_z := math.cos(angle_z), math.sin(angle_z) + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix4f64) { - cos_x := math.cos(angle_x) * angular_velocity_x; - sin_x := math.sin(angle_x) * angular_velocity_x; - m[0][0] = 1; - m[1][1] = +cos_x; - m[2][1] = +sin_x; - m[1][2] = -sin_x; - m[2][2] = +cos_x; - m[3][3] = 1; - return; + cos_x := math.cos(angle_x) * angular_velocity_x + sin_x := math.sin(angle_x) * angular_velocity_x + m[0][0] = 1 + m[1][1] = +cos_x + m[2][1] = +sin_x + m[1][2] = -sin_x + m[2][2] = +cos_x + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix4f64) { - cos_y := math.cos(angle_y) * angular_velocity_y; - sin_y := math.sin(angle_y) * angular_velocity_y; - m[0][0] = +cos_y; - m[2][0] = -sin_y; - m[1][1] = 1; - m[0][2] = +sin_y; - m[2][2] = +cos_y; - m[3][3] = 1; - return; + cos_y := math.cos(angle_y) * angular_velocity_y + sin_y := math.sin(angle_y) * angular_velocity_y + m[0][0] = +cos_y + m[2][0] = -sin_y + m[1][1] = 1 + m[0][2] = +sin_y + m[2][2] = +cos_y + m[3][3] = 1 + return } matrix4_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix4f64) { - cos_z := math.cos(angle_z) * angular_velocity_z; - sin_z := math.sin(angle_z) * angular_velocity_z; - m[0][0] = +cos_z; - m[1][0] = +sin_z; - m[1][1] = +cos_z; - m[0][1] = -sin_z; - m[2][2] = 1; - m[3][3] = 1; - return; + cos_z := math.cos(angle_z) * angular_velocity_z + sin_z := math.sin(angle_z) * angular_velocity_z + m[0][0] = +cos_z + m[1][0] = +sin_z + m[1][1] = +cos_z + m[0][1] = -sin_z + m[2][2] = 1 + m[3][3] = 1 + return } matrix4_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix4f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[1][0] = -sin_x * - sin_y; - m[2][0] = -cos_x * - sin_y; - m[1][1] = cos_x; - m[2][1] = sin_x; - m[0][2] = sin_y; - m[1][2] = -sin_x * cos_y; - m[2][2] = cos_x * cos_y; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[1][0] = -sin_x * - sin_y + m[2][0] = -cos_x * - sin_y + m[1][1] = cos_x + m[2][1] = sin_x + m[0][2] = sin_y + m[1][2] = -sin_x * cos_y + m[2][2] = cos_x * cos_y + m[3][3] = 1 + return } matrix4_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix4f64) { - cos_x, sin_x := math.cos(angle_x), math.sin(angle_x); - cos_y, sin_y := math.cos(angle_y), math.sin(angle_y); - m[0][0] = cos_y; - m[2][0] = -sin_y; - m[0][1] = sin_y*sin_x; - m[1][1] = cos_x; - m[2][1] = cos_y*sin_x; - m[0][2] = sin_y*cos_x; - m[1][2] = -sin_x; - m[2][2] = cos_y*cos_x; - m[3][3] = 1; - return; + cos_x, sin_x := math.cos(angle_x), math.sin(angle_x) + cos_y, sin_y := math.cos(angle_y), math.sin(angle_y) + m[0][0] = cos_y + m[2][0] = -sin_y + m[0][1] = sin_y*sin_x + m[1][1] = cos_x + m[2][1] = cos_y*sin_x + m[0][2] = sin_y*cos_x + m[1][2] = -sin_x + m[2][2] = cos_y*cos_x + m[3][3] = 1 + return } matrix4_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x)) } matrix4_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)); + return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z)) } matrix4_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix4f64) { - return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)); + return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y)) } matrix4_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(-t1); - c2 := math.cos(-t2); - c3 := math.cos(-t3); - s1 := math.sin(-t1); - s2 := math.sin(-t2); - s3 := math.sin(-t3); - - m[0][0] = c2 * c3; - m[0][1] =-c1 * s3 + s1 * s2 * c3; - m[0][2] = s1 * s3 + c1 * s2 * c3; - m[0][3] = 0; - m[1][0] = c2 * s3; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] =-s1 * c3 + c1 * s2 * s3; - m[1][3] = 0; - m[2][0] =-s2; - m[2][1] = s1 * c2; - m[2][2] = c1 * c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(-t1) + c2 := math.cos(-t2) + c3 := math.cos(-t3) + s1 := math.sin(-t1) + s2 := math.sin(-t2) + s3 := math.sin(-t3) + + m[0][0] = c2 * c3 + m[0][1] =-c1 * s3 + s1 * s2 * c3 + m[0][2] = s1 * s3 + c1 * s2 * c3 + m[0][3] = 0 + m[1][0] = c2 * s3 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] =-s1 * c3 + c1 * s2 * s3 + m[1][3] = 0 + m[2][0] =-s2 + m[2][1] = s1 * c2 + m[2][2] = c1 * c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = c1 * s2; - m[0][2] = s1 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s2; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c1 * s3 + c2 * c3 * s1; - m[1][3] = 0; - m[2][0] = s2 * s3; - m[2][1] =-c3 * s1 - c1 * c2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = c1 * s2 + m[0][2] = s1 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s2 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c1 * s3 + c2 * c3 * s1 + m[1][3] = 0 + m[2][0] = s2 * s3 + m[2][1] =-c3 * s1 - c1 * c2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2; - m[0][1] = s1 * s2; - m[0][2] =-c1 * s2; - m[0][3] = 0; - m[1][0] = s2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = c3 * s1 + c1 * c2 * s3; - m[1][3] = 0; - m[2][0] = c3 * s2; - m[2][1] =-c1 * s3 - c2 * c3 * s1; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 + m[0][1] = s1 * s2 + m[0][2] =-c1 * s2 + m[0][3] = 0 + m[1][0] = s2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = c3 * s1 + c1 * c2 * s3 + m[1][3] = 0 + m[2][0] = c3 * s2 + m[2][1] =-c1 * s3 - c2 * c3 * s1 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = s2* s3; - m[0][2] =-c3 * s1 - c1 * c2 * s3; - m[0][3] = 0; - m[1][0] = s1 * s2; - m[1][1] = c2; - m[1][2] = c1 * s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c2 * c3 * s1; - m[2][1] =-c3 * s2; - m[2][2] = c1 * c2 * c3 - s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = s2* s3 + m[0][2] =-c3 * s1 - c1 * c2 * s3 + m[0][3] = 0 + m[1][0] = s1 * s2 + m[1][1] = c2 + m[1][2] = c1 * s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c2 * c3 * s1 + m[2][1] =-c3 * s2 + m[2][2] = c1 * c2 * c3 - s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c3 * s2; - m[0][2] =-c1 * s3 - c2 * c3 * s1; - m[0][3] = 0; - m[1][0] =-c1 * s2; - m[1][1] = c2; - m[1][2] = s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * c2 * s3; - m[2][1] = s2 * s3; - m[2][2] = c1 * c3 - c2 * s1 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c3 * s2 + m[0][2] =-c1 * s3 - c2 * c3 * s1 + m[0][3] = 0 + m[1][0] =-c1 * s2 + m[1][1] = c2 + m[1][2] = s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * c2 * s3 + m[2][1] = s2 * s3 + m[2][2] = c1 * c3 - c2 * s1 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2 * c3 - s1 * s3; - m[0][1] = c1 * s3 + c2 * c3 * s1; - m[0][2] =-c3 * s2; - m[0][3] = 0; - m[1][0] =-c3 * s1 - c1 * c2 * s3; - m[1][1] = c1 * c3 - c2 * s1 * s3; - m[1][2] = s2 * s3; - m[1][3] = 0; - m[2][0] = c1 * s2; - m[2][1] = s1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 * c3 - s1 * s3 + m[0][1] = c1 * s3 + c2 * c3 * s1 + m[0][2] =-c3 * s2 + m[0][3] = 0 + m[1][0] =-c3 * s1 - c1 * c2 * s3 + m[1][1] = c1 * c3 - c2 * s1 * s3 + m[1][2] = s2 * s3 + m[1][3] = 0 + m[2][0] = c1 * s2 + m[2][1] = s1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - c2 * s1 * s3; - m[0][1] = c3 * s1 + c1 * c2 * s3; - m[0][2] = s2 *s3; - m[0][3] = 0; - m[1][0] =-c1 * s3 - c2 * c3 * s1; - m[1][1] = c1 * c2 * c3 - s1 * s3; - m[1][2] = c3 * s2; - m[1][3] = 0; - m[2][0] = s1 * s2; - m[2][1] =-c1 * s2; - m[2][2] = c2; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - c2 * s1 * s3 + m[0][1] = c3 * s1 + c1 * c2 * s3 + m[0][2] = s2 *s3 + m[0][3] = 0 + m[1][0] =-c1 * s3 - c2 * c3 * s1 + m[1][1] = c1 * c2 * c3 - s1 * s3 + m[1][2] = c3 * s2 + m[1][3] = 0 + m[2][0] = s1 * s2 + m[2][1] =-c1 * s2 + m[2][2] = c2 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c2 * c3; - m[0][1] = s1 * s3 + c1 * c3 * s2; - m[0][2] = c3 * s1 * s2 - c1 * s3; - m[0][3] = 0; - m[1][0] =-s2; - m[1][1] = c1 * c2; - m[1][2] = c2 * s1; - m[1][3] = 0; - m[2][0] = c2 * s3; - m[2][1] = c1 * s2 * s3 - c3 * s1; - m[2][2] = c1 * c3 + s1 * s2 *s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c2 * c3 + m[0][1] = s1 * s3 + c1 * c3 * s2 + m[0][2] = c3 * s1 * s2 - c1 * s3 + m[0][3] = 0 + m[1][0] =-s2 + m[1][1] = c1 * c2 + m[1][2] = c2 * s1 + m[1][3] = 0 + m[2][0] = c2 * s3 + m[2][1] = c1 * s2 * s3 - c3 * s1 + m[2][2] = c1 * c3 + s1 * s2 *s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = s2; - m[0][2] =-c2 * s1; - m[0][3] = 0; - m[1][0] = s1 * s3 - c1 * c3 * s2; - m[1][1] = c2 * c3; - m[1][2] = c1 * s3 + c3 * s1 * s2; - m[1][3] = 0; - m[2][0] = c3 * s1 + c1 * s2 * s3; - m[2][1] =-c2 * s3; - m[2][2] = c1 * c3 - s1 * s2 * s3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = s2 + m[0][2] =-c2 * s1 + m[0][3] = 0 + m[1][0] = s1 * s3 - c1 * c3 * s2 + m[1][1] = c2 * c3 + m[1][2] = c1 * s3 + c3 * s1 * s2 + m[1][3] = 0 + m[2][0] = c3 * s1 + c1 * s2 * s3 + m[2][1] =-c2 * s3 + m[2][2] = c1 * c3 - s1 * s2 * s3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c2; - m[0][1] = c2 * s1; - m[0][2] =-s2; - m[0][3] = 0; - m[1][0] = c1 * s2 * s3 - c3 * s1; - m[1][1] = c1 * c3 + s1 * s2 * s3; - m[1][2] = c2 * s3; - m[1][3] = 0; - m[2][0] = s1 * s3 + c1 * c3 * s2; - m[2][1] = c3 * s1 * s2 - c1 * s3; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c2 + m[0][1] = c2 * s1 + m[0][2] =-s2 + m[0][3] = 0 + m[1][0] = c1 * s2 * s3 - c3 * s1 + m[1][1] = c1 * c3 + s1 * s2 * s3 + m[1][2] = c2 * s3 + m[1][3] = 0 + m[2][0] = s1 * s3 + c1 * c3 * s2 + m[2][1] = c3 * s1 * s2 - c1 * s3 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) { - c1 := math.cos(t1); - s1 := math.sin(t1); - c2 := math.cos(t2); - s2 := math.sin(t2); - c3 := math.cos(t3); - s3 := math.sin(t3); - - m[0][0] = c1 * c3 - s1 * s2 * s3; - m[0][1] = c3 * s1 + c1 * s2 * s3; - m[0][2] =-c2 * s3; - m[0][3] = 0; - m[1][0] =-c2 * s1; - m[1][1] = c1 * c2; - m[1][2] = s2; - m[1][3] = 0; - m[2][0] = c1 * s3 + c3 * s1 * s2; - m[2][1] = s1 * s3 - c1 * c3 * s2; - m[2][2] = c2 * c3; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return; + c1 := math.cos(t1) + s1 := math.sin(t1) + c2 := math.cos(t2) + s2 := math.sin(t2) + c3 := math.cos(t3) + s3 := math.sin(t3) + + m[0][0] = c1 * c3 - s1 * s2 * s3 + m[0][1] = c3 * s1 + c1 * s2 * s3 + m[0][2] =-c2 * s3 + m[0][3] = 0 + m[1][0] =-c2 * s1 + m[1][1] = c1 * c2 + m[1][2] = s2 + m[1][3] = 0 + m[2][0] = c1 * s3 + c3 * s1 * s2 + m[2][1] = s1 * s3 - c1 * c3 * s2 + m[2][2] = c2 * c3 + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return } matrix4_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) { - ch := math.cos(yaw); - sh := math.sin(yaw); - cp := math.cos(pitch); - sp := math.sin(pitch); - cb := math.cos(roll); - sb := math.sin(roll); - - m[0][0] = ch * cb + sh * sp * sb; - m[0][1] = sb * cp; - m[0][2] = -sh * cb + ch * sp * sb; - m[0][3] = 0; - m[1][0] = -ch * sb + sh * sp * cb; - m[1][1] = cb * cp; - m[1][2] = sb * sh + ch * sp * cb; - m[1][3] = 0; - m[2][0] = sh * cp; - m[2][1] = -sp; - m[2][2] = ch * cp; - m[2][3] = 0; - m[3][0] = 0; - m[3][1] = 0; - m[3][2] = 0; - m[3][3] = 1; - return m; + ch := math.cos(yaw) + sh := math.sin(yaw) + cp := math.cos(pitch) + sp := math.sin(pitch) + cb := math.cos(roll) + sb := math.sin(roll) + + m[0][0] = ch * cb + sh * sp * sb + m[0][1] = sb * cp + m[0][2] = -sh * cb + ch * sp * sb + m[0][3] = 0 + m[1][0] = -ch * sb + sh * sp * cb + m[1][1] = cb * cp + m[1][2] = sb * sh + ch * sp * cb + m[1][3] = 0 + m[2][0] = sh * cp + m[2][1] = -sp + m[2][2] = ch * cp + m[2][3] = 0 + m[3][0] = 0 + m[3][1] = 0 + m[3][2] = 0 + m[3][3] = 1 + return m } euler_angles_xyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][2]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]); - T2 := math.atan2(-m[2][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]); - t1 = -T1; - t2 = -T2; - t3 = -T3; - return; + T1 := math.atan2(m[2][1], m[2][2]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]) + T2 := math.atan2(-m[2][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]) + t1 = -T1 + t2 = -T2 + t3 = -T3 + return } euler_angles_yxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], m[2][2]); - C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]); - T2 := math.atan2(-m[2][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], m[2][2]) + C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]) + T2 := math.atan2(-m[2][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][2], m[0][1]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][2], m[0][1]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], -m[0][2]); - S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]); - T2 := math.atan2(S2, m[0][0]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], -m[0][2]) + S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]) + T2 := math.atan2(S2, m[0][0]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][0], m[1][2]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][0], m[1][2]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], -m[1][0]); - S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]); - T2 := math.atan2(S2, m[1][1]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], -m[1][0]) + S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]) + T2 := math.atan2(S2, m[1][1]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][1], m[2][0]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][1], m[2][0]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[2][0], -m[2][1]); - S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]); - T2 := math.atan2(S2, m[2][2]); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[2][0], -m[2][1]) + S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]) + T2 := math.atan2(S2, m[2][2]) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_xzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[1][2], m[1][1]); - C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]); - T2 := math.atan2(-m[1][0], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[1][2], m[1][1]) + C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]) + T2 := math.atan2(-m[1][0], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_yzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[0][2], m[0][0]); - C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]); - T2 := math.atan2(m[0][1], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[0][2], m[0][0]) + C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]) + T2 := math.atan2(m[0][1], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(m[0][1], m[0][0]); - C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]); - T2 := math.atan2(-m[0][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(m[0][1], m[0][0]) + C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]) + T2 := math.atan2(-m[0][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]) + t1 = T1 + t2 = T2 + t3 = T3 + return } euler_angles_zxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) { - T1 := math.atan2(-m[1][0], m[1][1]); - C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]); - T2 := math.atan2(m[1][2], C2); - S1 := math.sin(T1); - C1 := math.cos(T1); - T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]); - t1 = T1; - t2 = T2; - t3 = T3; - return; + T1 := math.atan2(-m[1][0], m[1][1]) + C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]) + T2 := math.atan2(m[1][2], C2) + S1 := math.sin(T1) + C1 := math.cos(T1) + T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]) + t1 = T1 + t2 = T2 + t3 = T3 + return } diff --git a/core/math/linalg/swizzle.odin b/core/math/linalg/swizzle.odin index 335d22b9b..f035a5276 100644 --- a/core/math/linalg/swizzle.odin +++ b/core/math/linalg/swizzle.odin @@ -33,110 +33,110 @@ Vector4_Components :: enum u8 { } scalar_f32_swizzle1 :: proc(f: f32, c0: Scalar_Components) -> f32 { - return f; + return f } scalar_f32_swizzle2 :: proc(f: f32, c0, c1: Scalar_Components) -> Vector2f32 { - return {f, f}; + return {f, f} } scalar_f32_swizzle3 :: proc(f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 { - return {f, f, f}; + return {f, f, f} } scalar_f32_swizzle4 :: proc(f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 { - return {f, f, f, f}; + return {f, f, f, f} } vector2f32_swizzle1 :: proc(v: Vector2f32, c0: Vector2_Components) -> f32 { - return v[c0]; + return v[c0] } vector2f32_swizzle2 :: proc(v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector2f32_swizzle3 :: proc(v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector2f32_swizzle4 :: proc(v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector3f32_swizzle1 :: proc(v: Vector3f32, c0: Vector3_Components) -> f32 { - return v[c0]; + return v[c0] } vector3f32_swizzle2 :: proc(v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector3f32_swizzle3 :: proc(v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector3f32_swizzle4 :: proc(v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector4f32_swizzle1 :: proc(v: Vector4f32, c0: Vector4_Components) -> f32 { - return v[c0]; + return v[c0] } vector4f32_swizzle2 :: proc(v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector4f32_swizzle3 :: proc(v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector4f32_swizzle4 :: proc(v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } scalar_f64_swizzle1 :: proc(f: f64, c0: Scalar_Components) -> f64 { - return f; + return f } scalar_f64_swizzle2 :: proc(f: f64, c0, c1: Scalar_Components) -> Vector2f64 { - return {f, f}; + return {f, f} } scalar_f64_swizzle3 :: proc(f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 { - return {f, f, f}; + return {f, f, f} } scalar_f64_swizzle4 :: proc(f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 { - return {f, f, f, f}; + return {f, f, f, f} } vector2f64_swizzle1 :: proc(v: Vector2f64, c0: Vector2_Components) -> f64 { - return v[c0]; + return v[c0] } vector2f64_swizzle2 :: proc(v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector2f64_swizzle3 :: proc(v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector2f64_swizzle4 :: proc(v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector3f64_swizzle1 :: proc(v: Vector3f64, c0: Vector3_Components) -> f64 { - return v[c0]; + return v[c0] } vector3f64_swizzle2 :: proc(v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector3f64_swizzle3 :: proc(v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector3f64_swizzle4 :: proc(v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } vector4f64_swizzle1 :: proc(v: Vector4f64, c0: Vector4_Components) -> f64 { - return v[c0]; + return v[c0] } vector4f64_swizzle2 :: proc(v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 { - return {v[c0], v[c1]}; + return {v[c0], v[c1]} } vector4f64_swizzle3 :: proc(v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 { - return {v[c0], v[c1], v[c2]}; + return {v[c0], v[c1], v[c2]} } vector4f64_swizzle4 :: proc(v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 { - return {v[c0], v[c1], v[c2], v[c3]}; + return {v[c0], v[c1], v[c2], v[c3]} } @@ -151,7 +151,7 @@ scalar_swizzle :: proc{ scalar_f64_swizzle2, scalar_f64_swizzle3, scalar_f64_swizzle4, -}; +} vector2_swizzle :: proc{ vector2f32_swizzle1, @@ -162,7 +162,7 @@ vector2_swizzle :: proc{ vector2f64_swizzle2, vector2f64_swizzle3, vector2f64_swizzle4, -}; +} vector3_swizzle :: proc{ vector3f32_swizzle1, @@ -173,7 +173,7 @@ vector3_swizzle :: proc{ vector3f64_swizzle2, vector3f64_swizzle3, vector3f64_swizzle4, -}; +} vector4_swizzle :: proc{ vector4f32_swizzle1, @@ -184,7 +184,7 @@ vector4_swizzle :: proc{ vector4f64_swizzle2, vector4f64_swizzle3, vector4f64_swizzle4, -}; +} swizzle :: proc{ scalar_f32_swizzle1, @@ -219,4 +219,4 @@ swizzle :: proc{ vector4f64_swizzle2, vector4f64_swizzle3, vector4f64_swizzle4, -}; +} diff --git a/core/math/math.odin b/core/math/math.odin index 28b0c42fc..6a094cfd4 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -1,7 +1,7 @@ package math import "core:intrinsics" -_ :: intrinsics; +_ :: intrinsics Float_Class :: enum { Normal, // an ordinary nonzero floating point value @@ -11,89 +11,89 @@ Float_Class :: enum { NaN, // Not-A-Number (NaN) Inf, // positive infinity Neg_Inf, // negative infinity -}; +} -TAU :: 6.28318530717958647692528676655900576; -PI :: 3.14159265358979323846264338327950288; +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 -E :: 2.71828182845904523536; +E :: 2.71828182845904523536 -τ :: TAU; -π :: PI; -e :: E; +τ :: TAU +π :: PI +e :: E -SQRT_TWO :: 1.41421356237309504880168872420969808; -SQRT_THREE :: 1.73205080756887729352744634150587236; -SQRT_FIVE :: 2.23606797749978969640917366873127623; +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 -LN2 :: 0.693147180559945309417232121458176568; -LN10 :: 2.30258509299404568401799145468436421; +LN2 :: 0.693147180559945309417232121458176568 +LN10 :: 2.30258509299404568401799145468436421 -MAX_F64_PRECISION :: 16; // Maximum number of meaningful digits after the decimal point for 'f64' -MAX_F32_PRECISION :: 8; // Maximum number of meaningful digits after the decimal point for 'f32' -MAX_F16_PRECISION :: 4; // Maximum number of meaningful digits after the decimal point for 'f16' +MAX_F64_PRECISION :: 16 // Maximum number of meaningful digits after the decimal point for 'f64' +MAX_F32_PRECISION :: 8 // Maximum number of meaningful digits after the decimal point for 'f32' +MAX_F16_PRECISION :: 4 // Maximum number of meaningful digits after the decimal point for 'f16' -RAD_PER_DEG :: TAU/360.0; -DEG_PER_RAD :: 360.0/TAU; +RAD_PER_DEG :: TAU/360.0 +DEG_PER_RAD :: 360.0/TAU @(default_calling_convention="none") foreign _ { @(link_name="llvm.sqrt.f16") - sqrt_f16 :: proc(x: f16) -> f16 ---; + sqrt_f16 :: proc(x: f16) -> f16 --- @(link_name="llvm.sqrt.f32") - sqrt_f32 :: proc(x: f32) -> f32 ---; + sqrt_f32 :: proc(x: f32) -> f32 --- @(link_name="llvm.sqrt.f64") - sqrt_f64 :: proc(x: f64) -> f64 ---; + sqrt_f64 :: proc(x: f64) -> f64 --- @(link_name="llvm.sin.f16") - sin_f16 :: proc(θ: f16) -> f16 ---; + sin_f16 :: proc(θ: f16) -> f16 --- @(link_name="llvm.sin.f32") - sin_f32 :: proc(θ: f32) -> f32 ---; + sin_f32 :: proc(θ: f32) -> f32 --- @(link_name="llvm.sin.f64") - sin_f64 :: proc(θ: f64) -> f64 ---; + sin_f64 :: proc(θ: f64) -> f64 --- @(link_name="llvm.cos.f16") - cos_f16 :: proc(θ: f16) -> f16 ---; + cos_f16 :: proc(θ: f16) -> f16 --- @(link_name="llvm.cos.f32") - cos_f32 :: proc(θ: f32) -> f32 ---; + cos_f32 :: proc(θ: f32) -> f32 --- @(link_name="llvm.cos.f64") - cos_f64 :: proc(θ: f64) -> f64 ---; + cos_f64 :: proc(θ: f64) -> f64 --- @(link_name="llvm.pow.f16") - pow_f16 :: proc(x, power: f16) -> f16 ---; + pow_f16 :: proc(x, power: f16) -> f16 --- @(link_name="llvm.pow.f32") - pow_f32 :: proc(x, power: f32) -> f32 ---; + pow_f32 :: proc(x, power: f32) -> f32 --- @(link_name="llvm.pow.f64") - pow_f64 :: proc(x, power: f64) -> f64 ---; + pow_f64 :: proc(x, power: f64) -> f64 --- @(link_name="llvm.fmuladd.f16") - fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---; + fmuladd_f16 :: proc(a, b, c: f16) -> f16 --- @(link_name="llvm.fmuladd.f32") - fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---; + fmuladd_f32 :: proc(a, b, c: f32) -> f32 --- @(link_name="llvm.fmuladd.f64") - fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---; + fmuladd_f64 :: proc(a, b, c: f64) -> f64 --- @(link_name="llvm.log.f16") - ln_f16 :: proc(x: f16) -> f16 ---; + ln_f16 :: proc(x: f16) -> f16 --- @(link_name="llvm.log.f32") - ln_f32 :: proc(x: f32) -> f32 ---; + ln_f32 :: proc(x: f32) -> f32 --- @(link_name="llvm.log.f64") - ln_f64 :: proc(x: f64) -> f64 ---; + ln_f64 :: proc(x: f64) -> f64 --- @(link_name="llvm.exp.f16") - exp_f16 :: proc(x: f16) -> f16 ---; + exp_f16 :: proc(x: f16) -> f16 --- @(link_name="llvm.exp.f32") - exp_f32 :: proc(x: f32) -> f32 ---; + exp_f32 :: proc(x: f32) -> f32 --- @(link_name="llvm.exp.f64") - exp_f64 :: proc(x: f64) -> f64 ---; + exp_f64 :: proc(x: f64) -> f64 --- @(link_name="llvm.ldexp.f16") - ldexp_f16 :: proc(val: f16, exp: i32) -> f16 ---; + ldexp_f16 :: proc(val: f16, exp: i32) -> f16 --- @(link_name="llvm.ldexp.f32") - ldexp_f32 :: proc(val: f32, exp: i32) -> f32 ---; + ldexp_f32 :: proc(val: f32, exp: i32) -> f32 --- @(link_name="llvm.ldexp.f64") - ldexp_f64 :: proc(val: f64, exp: i32) -> f64 ---; + ldexp_f64 :: proc(val: f64, exp: i32) -> f64 --- } sqrt_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(sqrt_f16(f16(x))); } @@ -106,7 +106,7 @@ sqrt :: proc{ sqrt_f16, sqrt_f16le, sqrt_f16be, sqrt_f32, sqrt_f32le, sqrt_f32be, sqrt_f64, sqrt_f64le, sqrt_f64be, -}; +} sin_f16le :: proc(θ: f16le) -> f16le { return #force_inline f16le(sin_f16(f16(θ))); } sin_f16be :: proc(θ: f16be) -> f16be { return #force_inline f16be(sin_f16(f16(θ))); } @@ -118,7 +118,7 @@ sin :: proc{ sin_f16, sin_f16le, sin_f16be, sin_f32, sin_f32le, sin_f32be, sin_f64, sin_f64le, sin_f64be, -}; +} cos_f16le :: proc(θ: f16le) -> f16le { return #force_inline f16le(cos_f16(f16(θ))); } cos_f16be :: proc(θ: f16be) -> f16be { return #force_inline f16be(cos_f16(f16(θ))); } @@ -130,7 +130,7 @@ cos :: proc{ cos_f16, cos_f16le, cos_f16be, cos_f32, cos_f32le, cos_f32be, cos_f64, cos_f64le, cos_f64be, -}; +} pow_f16le :: proc(x, power: f16le) -> f16le { return #force_inline f16le(pow_f16(f16(x), f16(power))); } pow_f16be :: proc(x, power: f16be) -> f16be { return #force_inline f16be(pow_f16(f16(x), f16(power))); } @@ -142,7 +142,7 @@ pow :: proc{ pow_f16, pow_f16le, pow_f16be, pow_f32, pow_f32le, pow_f32be, pow_f64, pow_f64le, pow_f64be, -}; +} fmuladd_f16le :: proc(a, b, c: f16le) -> f16le { return #force_inline f16le(fmuladd_f16(f16(a), f16(b), f16(c))); } fmuladd_f16be :: proc(a, b, c: f16be) -> f16be { return #force_inline f16be(fmuladd_f16(f16(a), f16(b), f16(c))); } @@ -154,7 +154,7 @@ fmuladd :: proc{ fmuladd_f16, fmuladd_f16le, fmuladd_f16be, fmuladd_f32, fmuladd_f32le, fmuladd_f32be, fmuladd_f64, fmuladd_f64le, fmuladd_f64be, -}; +} ln_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(ln_f16(f16(x))); } ln_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(ln_f16(f16(x))); } @@ -166,7 +166,7 @@ ln :: proc{ ln_f16, ln_f16le, ln_f16be, ln_f32, ln_f32le, ln_f32be, ln_f64, ln_f64le, ln_f64be, -}; +} exp_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(exp_f16(f16(x))); } exp_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(exp_f16(f16(x))); } @@ -178,7 +178,7 @@ exp :: proc{ exp_f16, exp_f16le, exp_f16be, exp_f32, exp_f32le, exp_f32be, exp_f64, exp_f64le, exp_f64be, -}; +} ldexp_f16le :: proc(val: f16le, exp: i32) -> f16le { return #force_inline f16le(ldexp_f16(f16(val), exp)); } ldexp_f16be :: proc(val: f16be, exp: i32) -> f16be { return #force_inline f16be(ldexp_f16(f16(val), exp)); } @@ -190,7 +190,7 @@ ldexp :: proc{ ldexp_f16, ldexp_f16le, ldexp_f16be, ldexp_f32, ldexp_f32le, ldexp_f32be, ldexp_f64, ldexp_f64le, ldexp_f64be, -}; +} log_f16 :: proc(x, base: f16) -> f16 { return ln(x) / ln(base); } @@ -208,7 +208,7 @@ log :: proc{ log_f16, log_f16le, log_f16be, log_f32, log_f32le, log_f32be, log_f64, log_f64le, log_f64be, -}; +} log2_f16 :: proc(x: f16) -> f16 { return ln(x)/LN2; } log2_f16le :: proc(x: f16le) -> f16le { return f16le(log2_f16(f16(x))); } @@ -225,7 +225,7 @@ log2 :: proc{ log2_f16, log2_f16le, log2_f16be, log2_f32, log2_f32le, log2_f32be, log2_f64, log2_f64le, log2_f64be, -}; +} log10_f16 :: proc(x: f16) -> f16 { return ln(x)/LN10; } log10_f16le :: proc(x: f16le) -> f16le { return f16le(log10_f16(f16(x))); } @@ -242,7 +242,7 @@ log10 :: proc{ log10_f16, log10_f16le, log10_f16be, log10_f32, log10_f32le, log10_f32be, log10_f64, log10_f64le, log10_f64be, -}; +} tan_f16 :: proc(θ: f16) -> f16 { return sin(θ)/cos(θ); } tan_f16le :: proc(θ: f16le) -> f16le { return f16le(tan_f16(f16(θ))); } @@ -259,55 +259,55 @@ tan :: proc{ tan_f16, tan_f16le, tan_f16be, tan_f32, tan_f32le, tan_f32be, tan_f64, tan_f64le, tan_f64be, -}; +} lerp :: proc(a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t; } -saturate :: proc(a: $T) -> (x: T) { return clamp(a, 0, 1); }; +saturate :: proc(a: $T) -> (x: T) { return clamp(a, 0, 1); } unlerp :: proc(a, b, x: $T) -> (t: T) where intrinsics.type_is_float(T), !intrinsics.type_is_array(T) { - return (x-a)/(b-a); + return (x-a)/(b-a) } remap :: proc(old_value, old_min, old_max, new_min, new_max: $T) -> (x: T) where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - old_range := old_max - old_min; - new_range := new_max - new_min; + old_range := old_max - old_min + new_range := new_max - new_min if old_range == 0 { - return new_range / 2; + return new_range / 2 } - return ((old_value - old_min) / old_range) * new_range + new_min; + return ((old_value - old_min) / old_range) * new_range + new_min } wrap :: proc(x, y: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - tmp := mod(x, y); - return y + tmp if tmp < 0 else tmp; + tmp := mod(x, y) + return y + tmp if tmp < 0 else tmp } angle_diff :: proc(a, b: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - dist := wrap(b - a, TAU); - return wrap(dist*2, TAU) - dist; + dist := wrap(b - a, TAU) + return wrap(dist*2, TAU) - dist } angle_lerp :: proc(a, b, t: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - return a + angle_diff(a, b) * t; + return a + angle_diff(a, b) * t } step :: proc(edge, x: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - return 0 if x < edge else 1; + return 0 if x < edge else 1 } smoothstep :: proc(edge0, edge1, x: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { - t := clamp((x - edge0) / (edge1 - edge0), 0, 1); - return t * t * (3 - 2*t); + t := clamp((x - edge0) / (edge1 - edge0), 0, 1) + return t * t * (3 - 2*t) } bias :: proc(t, b: $T) -> T where intrinsics.type_is_numeric(T) { - return t / (((1/b) - 2) * (1 - t) + 1); + return t / (((1/b) - 2) * (1 - t) + 1) } gain :: proc(t, g: $T) -> T where intrinsics.type_is_numeric(T) { if t < 0.5 { - return bias(t*2, g)*0.5; + return bias(t*2, g)*0.5 } - return bias(t*2 - 1, 1 - g)*0.5 + 0.5; + return bias(t*2 - 1, 1 - g)*0.5 + 0.5 } @@ -324,20 +324,20 @@ sign :: proc{ sign_f16, sign_f16le, sign_f16be, sign_f32, sign_f32le, sign_f32be, sign_f64, sign_f64le, sign_f64be, -}; +} sign_bit_f16 :: proc(x: f16) -> bool { - return (transmute(u16)x) & (1<<15) != 0; + return (transmute(u16)x) & (1<<15) != 0 } sign_bit_f16le :: proc(x: f16le) -> bool { return #force_inline sign_bit_f16(f16(x)); } sign_bit_f16be :: proc(x: f16be) -> bool { return #force_inline sign_bit_f16(f16(x)); } sign_bit_f32 :: proc(x: f32) -> bool { - return (transmute(u32)x) & (1<<31) != 0; + return (transmute(u32)x) & (1<<31) != 0 } sign_bit_f32le :: proc(x: f32le) -> bool { return #force_inline sign_bit_f32(f32(x)); } sign_bit_f32be :: proc(x: f32be) -> bool { return #force_inline sign_bit_f32(f32(x)); } sign_bit_f64 :: proc(x: f64) -> bool { - return (transmute(u64)x) & (1<<63) != 0; + return (transmute(u64)x) & (1<<63) != 0 } sign_bit_f64le :: proc(x: f64le) -> bool { return #force_inline sign_bit_f64(f64(x)); } sign_bit_f64be :: proc(x: f64be) -> bool { return #force_inline sign_bit_f64(f64(x)); } @@ -345,32 +345,32 @@ sign_bit :: proc{ sign_bit_f16, sign_bit_f16le, sign_bit_f16be, sign_bit_f32, sign_bit_f32le, sign_bit_f32be, sign_bit_f64, sign_bit_f64le, sign_bit_f64be, -}; +} copy_sign_f16 :: proc(x, y: f16) -> f16 { - ix := transmute(u16)x; - iy := transmute(u16)y; - ix &= 0x7fff; - ix |= iy & 0x8000; - return transmute(f16)ix; + ix := transmute(u16)x + iy := transmute(u16)y + ix &= 0x7fff + ix |= iy & 0x8000 + return transmute(f16)ix } copy_sign_f16le :: proc(x, y: f16le) -> f16le { return #force_inline f16le(copy_sign_f16(f16(x), f16(y))); } copy_sign_f16be :: proc(x, y: f16be) -> f16be { return #force_inline f16be(copy_sign_f16(f16(x), f16(y))); } copy_sign_f32 :: proc(x, y: f32) -> f32 { - ix := transmute(u32)x; - iy := transmute(u32)y; - ix &= 0x7fff_ffff; - ix |= iy & 0x8000_0000; - return transmute(f32)ix; + ix := transmute(u32)x + iy := transmute(u32)y + ix &= 0x7fff_ffff + ix |= iy & 0x8000_0000 + return transmute(f32)ix } copy_sign_f32le :: proc(x, y: f32le) -> f32le { return #force_inline f32le(copy_sign_f32(f32(x), f32(y))); } copy_sign_f32be :: proc(x, y: f32be) -> f32be { return #force_inline f32be(copy_sign_f32(f32(x), f32(y))); } copy_sign_f64 :: proc(x, y: f64) -> f64 { - ix := transmute(u64)x; - iy := transmute(u64)y; - ix &= 0x7fff_ffff_ffff_ffff; - ix |= iy & 0x8000_0000_0000_0000; - return transmute(f64)ix; + ix := transmute(u64)x + iy := transmute(u64)y + ix &= 0x7fff_ffff_ffff_ffff + ix |= iy & 0x8000_0000_0000_0000 + return transmute(f64)ix } copy_sign_f64le :: proc(x, y: f64le) -> f64le { return #force_inline f64le(copy_sign_f64(f64(x), f64(y))); } copy_sign_f64be :: proc(x, y: f64be) -> f64be { return #force_inline f64be(copy_sign_f64(f64(x), f64(y))); } @@ -378,7 +378,7 @@ copy_sign :: proc{ copy_sign_f16, copy_sign_f16le, copy_sign_f16be, copy_sign_f32, copy_sign_f32le, copy_sign_f32be, copy_sign_f64, copy_sign_f64le, copy_sign_f64be, -}; +} to_radians_f16 :: proc(degrees: f16) -> f16 { return degrees * RAD_PER_DEG; } to_radians_f16le :: proc(degrees: f16le) -> f16le { return degrees * RAD_PER_DEG; } @@ -402,105 +402,105 @@ to_radians :: proc{ to_radians_f16, to_radians_f16le, to_radians_f16be, to_radians_f32, to_radians_f32le, to_radians_f32be, to_radians_f64, to_radians_f64le, to_radians_f64be, -}; +} to_degrees :: proc{ to_degrees_f16, to_degrees_f16le, to_degrees_f16be, to_degrees_f32, to_degrees_f32le, to_degrees_f32be, to_degrees_f64, to_degrees_f64le, to_degrees_f64be, -}; +} trunc_f16 :: proc(x: f16) -> f16 { trunc_internal :: proc(f: f16) -> f16 { - mask :: 0x1f; - shift :: 16 - 6; - bias :: 0xf; + mask :: 0x1f + shift :: 16 - 6 + bias :: 0xf if f < 1 { switch { - case f < 0: return -trunc_internal(-f); - case f == 0: return f; - case: return 0; + case f < 0: return -trunc_internal(-f) + case f == 0: return f + case: return 0 } } - x := transmute(u16)f; - e := (x >> shift) & mask - bias; + x := transmute(u16)f + e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1; + x &= ~(1 << (shift-e)) - 1 } - return transmute(f16)x; + return transmute(f16)x } switch classify(x) { case .Zero, .Neg_Zero, .NaN, .Inf, .Neg_Inf: - return x; + return x case .Normal, .Subnormal: // carry on } - return trunc_internal(x); + return trunc_internal(x) } trunc_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(trunc_f16(f16(x))); } trunc_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(trunc_f16(f16(x))); } trunc_f32 :: proc(x: f32) -> f32 { trunc_internal :: proc(f: f32) -> f32 { - mask :: 0xff; - shift :: 32 - 9; - bias :: 0x7f; + mask :: 0xff + shift :: 32 - 9 + bias :: 0x7f if f < 1 { switch { - case f < 0: return -trunc_internal(-f); - case f == 0: return f; - case: return 0; + case f < 0: return -trunc_internal(-f) + case f == 0: return f + case: return 0 } } - x := transmute(u32)f; - e := (x >> shift) & mask - bias; + x := transmute(u32)f + e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1; + x &= ~(1 << (shift-e)) - 1 } - return transmute(f32)x; + return transmute(f32)x } switch classify(x) { case .Zero, .Neg_Zero, .NaN, .Inf, .Neg_Inf: - return x; + return x case .Normal, .Subnormal: // carry on } - return trunc_internal(x); + return trunc_internal(x) } trunc_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(trunc_f32(f32(x))); } trunc_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(trunc_f32(f32(x))); } trunc_f64 :: proc(x: f64) -> f64 { trunc_internal :: proc(f: f64) -> f64 { - mask :: 0x7ff; - shift :: 64 - 12; - bias :: 0x3ff; + mask :: 0x7ff + shift :: 64 - 12 + bias :: 0x3ff if f < 1 { switch { - case f < 0: return -trunc_internal(-f); - case f == 0: return f; - case: return 0; + case f < 0: return -trunc_internal(-f) + case f == 0: return f + case: return 0 } } - x := transmute(u64)f; - e := (x >> shift) & mask - bias; + x := transmute(u64)f + e := (x >> shift) & mask - bias if e < shift { - x &= ~(1 << (shift-e)) - 1; + x &= ~(1 << (shift-e)) - 1 } - return transmute(f64)x; + return transmute(f64)x } switch classify(x) { case .Zero, .Neg_Zero, .NaN, .Inf, .Neg_Inf: - return x; + return x case .Normal, .Subnormal: // carry on } - return trunc_internal(x); + return trunc_internal(x) } trunc_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(trunc_f64(f64(x))); } trunc_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(trunc_f64(f64(x))); } @@ -508,41 +508,41 @@ trunc :: proc{ trunc_f16, trunc_f16le, trunc_f16be, trunc_f32, trunc_f32le, trunc_f32be, trunc_f64, trunc_f64le, trunc_f64be, -}; +} round_f16 :: proc(x: f16) -> f16 { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f16le :: proc(x: f16le) -> f16le { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f16be :: proc(x: f16be) -> f16be { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f32 :: proc(x: f32) -> f32 { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f32le :: proc(x: f32le) -> f32le { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f32be :: proc(x: f32be) -> f32be { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f64 :: proc(x: f64) -> f64 { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f64le :: proc(x: f64le) -> f64le { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round_f64be :: proc(x: f64be) -> f64be { - return ceil(x - 0.5) if x < 0 else floor(x + 0.5); + return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round :: proc{ round_f16, round_f16le, round_f16be, round_f32, round_f32le, round_f32be, round_f64, round_f64le, round_f64be, -}; +} ceil_f16 :: proc(x: f16) -> f16 { return -floor(-x); } @@ -561,53 +561,53 @@ ceil :: proc{ ceil_f16, ceil_f16le, ceil_f16be, ceil_f32, ceil_f32le, ceil_f32be, ceil_f64, ceil_f64le, ceil_f64be, -}; +} floor_f16 :: proc(x: f16) -> f16 { if x == 0 || is_nan(x) || is_inf(x) { - return x; + return x } if x < 0 { - d, fract := modf(-x); + d, fract := modf(-x) if fract != 0.0 { - d = d + 1; + d = d + 1 } - return -d; + return -d } - d, _ := modf(x); - return d; + d, _ := modf(x) + return d } floor_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(floor_f16(f16(x))); } floor_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(floor_f16(f16(x))); } floor_f32 :: proc(x: f32) -> f32 { if x == 0 || is_nan(x) || is_inf(x) { - return x; + return x } if x < 0 { - d, fract := modf(-x); + d, fract := modf(-x) if fract != 0.0 { - d = d + 1; + d = d + 1 } - return -d; + return -d } - d, _ := modf(x); - return d; + d, _ := modf(x) + return d } floor_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(floor_f32(f32(x))); } floor_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(floor_f32(f32(x))); } floor_f64 :: proc(x: f64) -> f64 { if x == 0 || is_nan(x) || is_inf(x) { - return x; + return x } if x < 0 { - d, fract := modf(-x); + d, fract := modf(-x) if fract != 0.0 { - d = d + 1; + d = d + 1 } - return -d; + return -d } - d, _ := modf(x); - return d; + d, _ := modf(x) + return d } floor_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(floor_f64(f64(x))); } floor_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(floor_f64(f64(x))); } @@ -615,164 +615,164 @@ floor :: proc{ floor_f16, floor_f16le, floor_f16be, floor_f32, floor_f32le, floor_f32be, floor_f64, floor_f64le, floor_f64be, -}; +} floor_div :: proc(x, y: $T) -> T where intrinsics.type_is_integer(T) { - a := x / y; - r := x % y; + a := x / y + r := x % y if (r > 0 && y < 0) || (r < 0 && y > 0) { - a -= 1; + a -= 1 } - return a; + return a } floor_mod :: proc(x, y: $T) -> T where intrinsics.type_is_integer(T) { - r := x % y; + r := x % y if (r > 0 && y < 0) || (r < 0 && y > 0) { - r += y; + r += y } - return r; + return r } modf_f16 :: proc(x: f16) -> (int: f16, frac: f16) { - shift :: 16 - 5 - 1; - mask :: 0x1f; - bias :: 15; + shift :: 16 - 5 - 1 + mask :: 0x1f + bias :: 15 if x < 1 { switch { case x < 0: - int, frac = modf(-x); - return -int, -frac; + int, frac = modf(-x) + return -int, -frac case x == 0: - return x, x; + return x, x } - return 0, x; + return 0, x } - i := transmute(u16)x; - e := uint(i>>shift)&mask - bias; + i := transmute(u16)x + e := uint(i>>shift)&mask - bias if e < shift { - i &~= 1<<(shift-e) - 1; + i &~= 1<<(shift-e) - 1 } - int = transmute(f16)i; - frac = x - int; - return; + int = transmute(f16)i + frac = x - int + return } modf_f16le :: proc(x: f16le) -> (int: f16le, frac: f16le) { - i, f := #force_inline modf_f16(f16(x)); - return f16le(i), f16le(f); + i, f := #force_inline modf_f16(f16(x)) + return f16le(i), f16le(f) } modf_f16be :: proc(x: f16be) -> (int: f16be, frac: f16be) { - i, f := #force_inline modf_f16(f16(x)); - return f16be(i), f16be(f); + i, f := #force_inline modf_f16(f16(x)) + return f16be(i), f16be(f) } modf_f32 :: proc(x: f32) -> (int: f32, frac: f32) { - shift :: 32 - 8 - 1; - mask :: 0xff; - bias :: 127; + shift :: 32 - 8 - 1 + mask :: 0xff + bias :: 127 if x < 1 { switch { case x < 0: - int, frac = modf(-x); - return -int, -frac; + int, frac = modf(-x) + return -int, -frac case x == 0: - return x, x; + return x, x } - return 0, x; + return 0, x } - i := transmute(u32)x; - e := uint(i>>shift)&mask - bias; + i := transmute(u32)x + e := uint(i>>shift)&mask - bias if e < shift { - i &~= 1<<(shift-e) - 1; + i &~= 1<<(shift-e) - 1 } - int = transmute(f32)i; - frac = x - int; - return; + int = transmute(f32)i + frac = x - int + return } modf_f32le :: proc(x: f32le) -> (int: f32le, frac: f32le) { - i, f := #force_inline modf_f32(f32(x)); - return f32le(i), f32le(f); + i, f := #force_inline modf_f32(f32(x)) + return f32le(i), f32le(f) } modf_f32be :: proc(x: f32be) -> (int: f32be, frac: f32be) { - i, f := #force_inline modf_f32(f32(x)); - return f32be(i), f32be(f); + i, f := #force_inline modf_f32(f32(x)) + return f32be(i), f32be(f) } modf_f64 :: proc(x: f64) -> (int: f64, frac: f64) { - shift :: 64 - 11 - 1; - mask :: 0x7ff; - bias :: 1023; + shift :: 64 - 11 - 1 + mask :: 0x7ff + bias :: 1023 if x < 1 { switch { case x < 0: - int, frac = modf(-x); - return -int, -frac; + int, frac = modf(-x) + return -int, -frac case x == 0: - return x, x; + return x, x } - return 0, x; + return 0, x } - i := transmute(u64)x; - e := uint(i>>shift)&mask - bias; + i := transmute(u64)x + e := uint(i>>shift)&mask - bias if e < shift { - i &~= 1<<(shift-e) - 1; + i &~= 1<<(shift-e) - 1 } - int = transmute(f64)i; - frac = x - int; - return; + int = transmute(f64)i + frac = x - int + return } modf_f64le :: proc(x: f64le) -> (int: f64le, frac: f64le) { - i, f := #force_inline modf_f64(f64(x)); - return f64le(i), f64le(f); + i, f := #force_inline modf_f64(f64(x)) + return f64le(i), f64le(f) } modf_f64be :: proc(x: f64be) -> (int: f64be, frac: f64be) { - i, f := #force_inline modf_f64(f64(x)); - return f64be(i), f64be(f); + i, f := #force_inline modf_f64(f64(x)) + return f64be(i), f64be(f) } modf :: proc{ modf_f16, modf_f16le, modf_f16be, modf_f32, modf_f32le, modf_f32be, modf_f64, modf_f64le, modf_f64be, -}; -split_decimal :: modf; +} +split_decimal :: modf mod_f16 :: proc(x, y: f16) -> (n: f16) { - z := abs(y); - n = remainder(abs(x), z); + z := abs(y) + n = remainder(abs(x), z) if sign(n) < 0 { - n += z; + n += z } - return copy_sign(n, x); + return copy_sign(n, x) } mod_f16le :: proc(x, y: f16le) -> (n: f16le) { return #force_inline f16le(mod_f16(f16(x), f16(y))); } mod_f16be :: proc(x, y: f16be) -> (n: f16be) { return #force_inline f16be(mod_f16(f16(x), f16(y))); } mod_f32 :: proc(x, y: f32) -> (n: f32) { - z := abs(y); - n = remainder(abs(x), z); + z := abs(y) + n = remainder(abs(x), z) if sign(n) < 0 { - n += z; + n += z } - return copy_sign(n, x); + return copy_sign(n, x) } mod_f32le :: proc(x, y: f32le) -> (n: f32le) { return #force_inline f32le(mod_f32(f32(x), f32(y))); } mod_f32be :: proc(x, y: f32be) -> (n: f32be) { return #force_inline f32be(mod_f32(f32(x), f32(y))); } mod_f64 :: proc(x, y: f64) -> (n: f64) { - z := abs(y); - n = remainder(abs(x), z); + z := abs(y) + n = remainder(abs(x), z) if sign(n) < 0 { - n += z; + n += z } - return copy_sign(n, x); + return copy_sign(n, x) } mod_f64le :: proc(x, y: f64le) -> (n: f64le) { return #force_inline f64le(mod_f64(f64(x), f64(y))); } mod_f64be :: proc(x, y: f64be) -> (n: f64be) { return #force_inline f64be(mod_f64(f64(x), f64(y))); } @@ -780,7 +780,7 @@ mod :: proc{ mod_f16, mod_f16le, mod_f16be, mod_f32, mod_f32le, mod_f32be, mod_f64, mod_f64le, mod_f64be, -}; +} remainder_f16 :: proc(x, y: f16 ) -> f16 { return x - round(x/y) * y; } remainder_f16le :: proc(x, y: f16le) -> f16le { return x - round(x/y) * y; } @@ -795,95 +795,95 @@ remainder :: proc{ remainder_f16, remainder_f16le, remainder_f16be, remainder_f32, remainder_f32le, remainder_f32be, remainder_f64, remainder_f64le, remainder_f64be, -}; +} gcd :: proc(x, y: $T) -> T where intrinsics.type_is_ordered_numeric(T) { - x, y := x, y; + x, y := x, y for y != 0 { - x %= y; - x, y = y, x; + x %= y + x, y = y, x } - return abs(x); + return abs(x) } lcm :: proc(x, y: $T) -> T where intrinsics.type_is_ordered_numeric(T) { - return x / gcd(x, y) * y; + return x / gcd(x, y) * y } frexp_f16 :: proc(x: f16) -> (significand: f16, exponent: int) { - f, e := frexp_f64(f64(x)); - return f16(f), e; + f, e := frexp_f64(f64(x)) + return f16(f), e } frexp_f16le :: proc(x: f16le) -> (significand: f16le, exponent: int) { - f, e := frexp_f64(f64(x)); - return f16le(f), e; + f, e := frexp_f64(f64(x)) + return f16le(f), e } frexp_f16be :: proc(x: f16be) -> (significand: f16be, exponent: int) { - f, e := frexp_f64(f64(x)); - return f16be(f), e; + f, e := frexp_f64(f64(x)) + return f16be(f), e } frexp_f32 :: proc(x: f32) -> (significand: f32, exponent: int) { - f, e := frexp_f64(f64(x)); - return f32(f), e; + f, e := frexp_f64(f64(x)) + return f32(f), e } frexp_f32le :: proc(x: f32le) -> (significand: f32le, exponent: int) { - f, e := frexp_f64(f64(x)); - return f32le(f), e; + f, e := frexp_f64(f64(x)) + return f32le(f), e } frexp_f32be :: proc(x: f32be) -> (significand: f32be, exponent: int) { - f, e := frexp_f64(f64(x)); - return f32be(f), e; + f, e := frexp_f64(f64(x)) + return f32be(f), e } frexp_f64 :: proc(x: f64) -> (significand: f64, exponent: int) { switch { case x == 0: - return 0, 0; + return 0, 0 case x < 0: - significand, exponent = frexp(-x); - return -significand, exponent; + significand, exponent = frexp(-x) + return -significand, exponent } - ex := trunc(log2(x)); - exponent = int(ex); - significand = x / pow(2.0, ex); + ex := trunc(log2(x)) + exponent = int(ex) + significand = x / pow(2.0, ex) if abs(significand) >= 1 { - exponent += 1; - significand /= 2; + exponent += 1 + significand /= 2 } if exponent == 1024 && significand == 0 { - significand = 0.99999999999999988898; + significand = 0.99999999999999988898 } - return; + return } frexp_f64le :: proc(x: f64le) -> (significand: f64le, exponent: int) { - f, e := frexp_f64(f64(x)); - return f64le(f), e; + f, e := frexp_f64(f64(x)) + return f64le(f), e } frexp_f64be :: proc(x: f64be) -> (significand: f64be, exponent: int) { - f, e := frexp_f64(f64(x)); - return f64be(f), e; + f, e := frexp_f64(f64(x)) + return f64be(f), e } frexp :: proc{ frexp_f16, frexp_f16le, frexp_f16be, frexp_f32, frexp_f32le, frexp_f32be, frexp_f64, frexp_f64le, frexp_f64be, -}; +} binomial :: proc(n, k: int) -> int { switch { - case k <= 0: return 1; - case 2*k > n: return binomial(n, n-k); + case k <= 0: return 1 + case 2*k > n: return binomial(n, n-k) } - b := n; + b := n for i in 2..<k { - b = (b * (n+1-i))/i; + b = (b * (n+1-i))/i } - return b; + return b } factorial :: proc(n: int) -> int { @@ -910,7 +910,7 @@ factorial :: proc(n: int) -> int { 6_402_373_705_728_000, 121_645_100_408_832_000, 2_432_902_008_176_640_000, - }; + } } else { @static table := [13]int{ 1, @@ -926,88 +926,88 @@ factorial :: proc(n: int) -> int { 3_628_800, 39_916_800, 479_001_600, - }; + } } - assert(n >= 0, "parameter must not be negative"); - assert(n < len(table), "parameter is too large to lookup in the table"); - return table[n]; + assert(n >= 0, "parameter must not be negative") + assert(n < len(table), "parameter is too large to lookup in the table") + return table[n] } classify_f16 :: proc(x: f16) -> Float_Class { switch { case x == 0: - i := transmute(i16)x; + i := transmute(i16)x if i < 0 { - return .Neg_Zero; + return .Neg_Zero } - return .Zero; + return .Zero case x*0.5 == x: if x < 0 { - return .Neg_Inf; + return .Neg_Inf } - return .Inf; + return .Inf case !(x == x): - return .NaN; + return .NaN } - u := transmute(u16)x; - exp := int(u>>10) & (1<<5 - 1); + u := transmute(u16)x + exp := int(u>>10) & (1<<5 - 1) if exp == 0 { - return .Subnormal; + return .Subnormal } - return .Normal; + return .Normal } classify_f16le :: proc(x: f16le) -> Float_Class { return #force_inline classify_f16(f16(x)); } classify_f16be :: proc(x: f16be) -> Float_Class { return #force_inline classify_f16(f16(x)); } classify_f32 :: proc(x: f32) -> Float_Class { switch { case x == 0: - i := transmute(i32)x; + i := transmute(i32)x if i < 0 { - return .Neg_Zero; + return .Neg_Zero } - return .Zero; + return .Zero case x*0.5 == x: if x < 0 { - return .Neg_Inf; + return .Neg_Inf } - return .Inf; + return .Inf case !(x == x): - return .NaN; + return .NaN } - u := transmute(u32)x; - exp := int(u>>23) & (1<<8 - 1); + u := transmute(u32)x + exp := int(u>>23) & (1<<8 - 1) if exp == 0 { - return .Subnormal; + return .Subnormal } - return .Normal; + return .Normal } classify_f32le :: proc(x: f32le) -> Float_Class { return #force_inline classify_f32(f32(x)); } classify_f32be :: proc(x: f32be) -> Float_Class { return #force_inline classify_f32(f32(x)); } classify_f64 :: proc(x: f64) -> Float_Class { switch { case x == 0: - i := transmute(i64)x; + i := transmute(i64)x if i < 0 { - return .Neg_Zero; + return .Neg_Zero } - return .Zero; + return .Zero case x*0.5 == x: if x < 0 { - return .Neg_Inf; + return .Neg_Inf } - return .Inf; + return .Inf case !(x == x): - return .NaN; + return .NaN } - u := transmute(u64)x; - exp := int(u>>52) & (1<<11 - 1); + u := transmute(u64)x + exp := int(u>>52) & (1<<11 - 1) if exp == 0 { - return .Subnormal; + return .Subnormal } - return .Normal; + return .Normal } classify_f64le :: proc(x: f64le) -> Float_Class { return #force_inline classify_f64(f64(x)); } classify_f64be :: proc(x: f64be) -> Float_Class { return #force_inline classify_f64(f64(x)); } @@ -1015,7 +1015,7 @@ classify :: proc{ classify_f16, classify_f16le, classify_f16be, classify_f32, classify_f32le, classify_f32be, classify_f64, classify_f64le, classify_f64be, -}; +} is_nan_f16 :: proc(x: f16) -> bool { return classify(x) == .NaN; } is_nan_f16le :: proc(x: f16le) -> bool { return classify(x) == .NaN; } @@ -1030,209 +1030,209 @@ is_nan :: proc{ is_nan_f16, is_nan_f16le, is_nan_f16be, is_nan_f32, is_nan_f32le, is_nan_f32be, is_nan_f64, is_nan_f64le, is_nan_f64be, -}; +} // is_inf reports whether f is an infinity, according to sign. // If sign > 0, is_inf reports whether f is positive infinity. // If sign < 0, is_inf reports whether f is negative infinity. // If sign == 0, is_inf reports whether f is either infinity. is_inf_f16 :: proc(x: f16, sign: int = 0) -> bool { - class := classify(abs(x)); + class := classify(abs(x)) switch { case sign > 0: - return class == .Inf; + return class == .Inf case sign < 0: - return class == .Neg_Inf; + return class == .Neg_Inf } - return class == .Inf || class == .Neg_Inf; + return class == .Inf || class == .Neg_Inf } is_inf_f16le :: proc(x: f16le, sign: int = 0) -> bool { - return #force_inline is_inf_f16(f16(x), sign); + return #force_inline is_inf_f16(f16(x), sign) } is_inf_f16be :: proc(x: f16be, sign: int = 0) -> bool { - return #force_inline is_inf_f16(f16(x), sign); + return #force_inline is_inf_f16(f16(x), sign) } is_inf_f32 :: proc(x: f32, sign: int = 0) -> bool { - class := classify(abs(x)); + class := classify(abs(x)) switch { case sign > 0: - return class == .Inf; + return class == .Inf case sign < 0: - return class == .Neg_Inf; + return class == .Neg_Inf } - return class == .Inf || class == .Neg_Inf; + return class == .Inf || class == .Neg_Inf } is_inf_f32le :: proc(x: f32le, sign: int = 0) -> bool { - return #force_inline is_inf_f32(f32(x), sign); + return #force_inline is_inf_f32(f32(x), sign) } is_inf_f32be :: proc(x: f32be, sign: int = 0) -> bool { - return #force_inline is_inf_f32(f32(x), sign); + return #force_inline is_inf_f32(f32(x), sign) } is_inf_f64 :: proc(x: f64, sign: int = 0) -> bool { - class := classify(abs(x)); + class := classify(abs(x)) switch { case sign > 0: - return class == .Inf; + return class == .Inf case sign < 0: - return class == .Neg_Inf; + return class == .Neg_Inf } - return class == .Inf || class == .Neg_Inf; + return class == .Inf || class == .Neg_Inf } is_inf_f64le :: proc(x: f64le, sign: int = 0) -> bool { - return #force_inline is_inf_f64(f64(x), sign); + return #force_inline is_inf_f64(f64(x), sign) } is_inf_f64be :: proc(x: f64be, sign: int = 0) -> bool { - return #force_inline is_inf_f64(f64(x), sign); + return #force_inline is_inf_f64(f64(x), sign) } is_inf :: proc{ is_inf_f16, is_inf_f16le, is_inf_f16be, is_inf_f32, is_inf_f32le, is_inf_f32be, is_inf_f64, is_inf_f64le, is_inf_f64be, -}; +} inf_f16 :: proc(sign: int) -> f16 { - return f16(inf_f64(sign)); + return f16(inf_f64(sign)) } inf_f16le :: proc(sign: int) -> f16le { - return f16le(inf_f64(sign)); + return f16le(inf_f64(sign)) } inf_f16be :: proc(sign: int) -> f16be { - return f16be(inf_f64(sign)); + return f16be(inf_f64(sign)) } inf_f32 :: proc(sign: int) -> f32 { - return f32(inf_f64(sign)); + return f32(inf_f64(sign)) } inf_f32le :: proc(sign: int) -> f32le { - return f32le(inf_f64(sign)); + return f32le(inf_f64(sign)) } inf_f32be :: proc(sign: int) -> f32be { - return f32be(inf_f64(sign)); + return f32be(inf_f64(sign)) } inf_f64 :: proc(sign: int) -> f64 { - v: u64; + v: u64 if sign >= 0 { - v = 0x7ff00000_00000000; + v = 0x7ff00000_00000000 } else { - v = 0xfff00000_00000000; + v = 0xfff00000_00000000 } - return transmute(f64)v; + return transmute(f64)v } inf_f64le :: proc(sign: int) -> f64le { - return f64le(inf_f64(sign)); + return f64le(inf_f64(sign)) } inf_f64be :: proc(sign: int) -> f64be { - return f64be(inf_f64(sign)); + return f64be(inf_f64(sign)) } nan_f16 :: proc() -> f16 { - return f16(nan_f64()); + return f16(nan_f64()) } nan_f16le :: proc() -> f16le { - return f16le(nan_f64()); + return f16le(nan_f64()) } nan_f16be :: proc() -> f16be { - return f16be(nan_f64()); + return f16be(nan_f64()) } nan_f32 :: proc() -> f32 { - return f32(nan_f64()); + return f32(nan_f64()) } nan_f32le :: proc() -> f32le { - return f32le(nan_f64()); + return f32le(nan_f64()) } nan_f32be :: proc() -> f32be { - return f32be(nan_f64()); + return f32be(nan_f64()) } nan_f64 :: proc() -> f64 { - v: u64 = 0x7ff80000_00000001; - return transmute(f64)v; + v: u64 = 0x7ff80000_00000001 + return transmute(f64)v } nan_f64le :: proc() -> f64le { - return f64le(nan_f64()); + return f64le(nan_f64()) } nan_f64be :: proc() -> f64be { - return f64be(nan_f64()); + return f64be(nan_f64()) } is_power_of_two :: proc(x: int) -> bool { - return x > 0 && (x & (x-1)) == 0; + return x > 0 && (x & (x-1)) == 0 } next_power_of_two :: proc(x: int) -> int { - k := x -1; + k := x -1 when size_of(int) == 8 { - k = k | (k >> 32); + k = k | (k >> 32) } - k = k | (k >> 16); - k = k | (k >> 8); - k = k | (k >> 4); - k = k | (k >> 2); - k = k | (k >> 1); - k += 1 + int(x <= 0); - return k; + k = k | (k >> 16) + k = k | (k >> 8) + k = k | (k >> 4) + k = k | (k >> 2) + k = k | (k >> 1) + k += 1 + int(x <= 0) + return k } sum :: proc(x: $T/[]$E) -> (res: E) where intrinsics.type_is_numeric(E) { for i in x { - res += i; + res += i } - return; + return } prod :: proc(x: $T/[]$E) -> (res: E) where intrinsics.type_is_numeric(E) { for i in x { - res *= i; + res *= i } - return; + return } cumsum_inplace :: proc(x: $T/[]$E) -> T where intrinsics.type_is_numeric(E) { for i in 1..<len(x) { - x[i] = x[i-1] + x[i]; + x[i] = x[i-1] + x[i] } } cumsum :: proc(dst, src: $T/[]$E) -> T where intrinsics.type_is_numeric(E) { - N := min(len(dst), len(src)); + N := min(len(dst), len(src)) if N > 0 { - dst[0] = src[0]; + dst[0] = src[0] for i in 1..<N { - dst[i] = dst[i-1] + src[i]; + dst[i] = dst[i-1] + src[i] } } - return dst[:N]; + return dst[:N] } atan2_f16 :: proc(y, x: f16) -> f16 { // TODO(bill): Better atan2_f16 - return f16(atan2_f64(f64(y), f64(x))); + return f16(atan2_f64(f64(y), f64(x))) } atan2_f16le :: proc(y, x: f16le) -> f16le { // TODO(bill): Better atan2_f16 - return f16le(atan2_f64(f64(y), f64(x))); + return f16le(atan2_f64(f64(y), f64(x))) } atan2_f16be :: proc(y, x: f16be) -> f16be { // TODO(bill): Better atan2_f16 - return f16be(atan2_f64(f64(y), f64(x))); + return f16be(atan2_f64(f64(y), f64(x))) } atan2_f32 :: proc(y, x: f32) -> f32 { // TODO(bill): Better atan2_f32 - return f32(atan2_f64(f64(y), f64(x))); + return f32(atan2_f64(f64(y), f64(x))) } atan2_f32le :: proc(y, x: f32le) -> f32le { // TODO(bill): Better atan2_f32 - return f32le(atan2_f64(f64(y), f64(x))); + return f32le(atan2_f64(f64(y), f64(x))) } atan2_f32be :: proc(y, x: f32be) -> f32be { // TODO(bill): Better atan2_f32 - return f32be(atan2_f64(f64(y), f64(x))); + return f32be(atan2_f64(f64(y), f64(x))) } atan2_f64 :: proc(y, x: f64) -> f64 { @@ -1242,161 +1242,161 @@ atan2_f64 :: proc(y, x: f64) -> f64 { // Stephen L. Moshier // moshier@na-net.ornl.gov - NAN :: 0h7fff_ffff_ffff_ffff; - INF :: 0h7FF0_0000_0000_0000; - PI :: 0h4009_21fb_5444_2d18; + NAN :: 0h7fff_ffff_ffff_ffff + INF :: 0h7FF0_0000_0000_0000 + PI :: 0h4009_21fb_5444_2d18 atan :: proc(x: f64) -> f64 { if x == 0 { - return x; + return x } if x > 0 { - return s_atan(x); + return s_atan(x) } - return -s_atan(-x); + return -s_atan(-x) } // s_atan reduces its argument (known to be positive) to the range [0, 0.66] and calls x_atan. s_atan :: proc(x: f64) -> f64 { - MORE_BITS :: 6.123233995736765886130e-17; // pi/2 = PIO2 + MORE_BITS - TAN3PI08 :: 2.41421356237309504880; // tan(3*pi/8) + MORE_BITS :: 6.123233995736765886130e-17 // pi/2 = PIO2 + MORE_BITS + TAN3PI08 :: 2.41421356237309504880 // tan(3*pi/8) if x <= 0.66 { - return x_atan(x); + return x_atan(x) } if x > TAN3PI08 { - return PI/2 - x_atan(1/x) + MORE_BITS; + return PI/2 - x_atan(1/x) + MORE_BITS } - return PI/4 + x_atan((x-1)/(x+1)) + 0.5*MORE_BITS; + return PI/4 + x_atan((x-1)/(x+1)) + 0.5*MORE_BITS } // x_atan evaluates a series valid in the range [0, 0.66]. x_atan :: proc(x: f64) -> f64 { - P0 :: -8.750608600031904122785e-01; - P1 :: -1.615753718733365076637e+01; - P2 :: -7.500855792314704667340e+01; - P3 :: -1.228866684490136173410e+02; - P4 :: -6.485021904942025371773e+01; - Q0 :: +2.485846490142306297962e+01; - Q1 :: +1.650270098316988542046e+02; - Q2 :: +4.328810604912902668951e+02; - Q3 :: +4.853903996359136964868e+02; - Q4 :: +1.945506571482613964425e+02; - - z := x * x; - z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4); - z = x*z + x; - return z; + P0 :: -8.750608600031904122785e-01 + P1 :: -1.615753718733365076637e+01 + P2 :: -7.500855792314704667340e+01 + P3 :: -1.228866684490136173410e+02 + P4 :: -6.485021904942025371773e+01 + Q0 :: +2.485846490142306297962e+01 + Q1 :: +1.650270098316988542046e+02 + Q2 :: +4.328810604912902668951e+02 + Q3 :: +4.853903996359136964868e+02 + Q4 :: +1.945506571482613964425e+02 + + z := x * x + z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4) + z = x*z + x + return z } switch { case is_nan(y) || is_nan(x): - return NAN; + return NAN case y == 0: if x >= 0 && !sign_bit(x) { - return copy_sign(0.0, y); + return copy_sign(0.0, y) } - return copy_sign(PI, y); + return copy_sign(PI, y) case x == 0: - return copy_sign(PI*0.5, y); + return copy_sign(PI*0.5, y) case is_inf(x, 0): if is_inf(x, 1) { if is_inf(y, 0) { - return copy_sign(PI*0.25, y); + return copy_sign(PI*0.25, y) } - return copy_sign(0, y); + return copy_sign(0, y) } if is_inf(y, 0) { - return copy_sign(PI*0.75, y); + return copy_sign(PI*0.75, y) } - return copy_sign(PI, y); + return copy_sign(PI, y) case is_inf(y, 0): - return copy_sign(PI*0.5, y); + return copy_sign(PI*0.5, y) } - q := atan(y / x); + q := atan(y / x) if x < 0 { if q <= 0 { - return q + PI; + return q + PI } - return q - PI; + return q - PI } - return q; + return q } atan2_f64le :: proc(y, x: f64le) -> f64le { // TODO(bill): Better atan2_f32 - return f64le(atan2_f64(f64(y), f64(x))); + return f64le(atan2_f64(f64(y), f64(x))) } atan2_f64be :: proc(y, x: f64be) -> f64be { // TODO(bill): Better atan2_f32 - return f64be(atan2_f64(f64(y), f64(x))); + return f64be(atan2_f64(f64(y), f64(x))) } atan2 :: proc{ atan2_f16, atan2_f16le, atan2_f16be, atan2_f32, atan2_f32le, atan2_f32be, atan2_f64, atan2_f64le, atan2_f64be, -}; +} atan :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return atan2(x, 1); + return atan2(x, 1) } asin :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return atan2(x, 1 + sqrt(1 - x*x)); + return atan2(x, 1 + sqrt(1 - x*x)) } acos :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return 2 * atan2(sqrt(1 - x), sqrt(1 + x)); + return 2 * atan2(sqrt(1 - x), sqrt(1 + x)) } sinh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return (exp(x) - exp(-x))*0.5; + return (exp(x) - exp(-x))*0.5 } cosh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - return (exp(x) + exp(-x))*0.5; + return (exp(x) + exp(-x))*0.5 } tanh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { - t := exp(2*x); - return (t - 1) / (t + 1); -} - -F16_DIG :: 3; -F16_EPSILON :: 0.00097656; -F16_GUARD :: 0; -F16_MANT_DIG :: 11; -F16_MAX :: 65504.0; -F16_MAX_10_EXP :: 4; -F16_MAX_EXP :: 15; -F16_MIN :: 6.10351562e-5; -F16_MIN_10_EXP :: -4; -F16_MIN_EXP :: -14; -F16_NORMALIZE :: 0; -F16_RADIX :: 2; -F16_ROUNDS :: 1; - - -F32_DIG :: 6; -F32_EPSILON :: 1.192092896e-07; -F32_GUARD :: 0; -F32_MANT_DIG :: 24; -F32_MAX :: 3.402823466e+38; -F32_MAX_10_EXP :: 38; -F32_MAX_EXP :: 128; -F32_MIN :: 1.175494351e-38; -F32_MIN_10_EXP :: -37; -F32_MIN_EXP :: -125; -F32_NORMALIZE :: 0; -F32_RADIX :: 2; -F32_ROUNDS :: 1; - -F64_DIG :: 15; // # of decimal digits of precision -F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0 -F64_MANT_DIG :: 53; // # of bits in mantissa -F64_MAX :: 1.7976931348623158e+308; // max value -F64_MAX_10_EXP :: 308; // max decimal exponent -F64_MAX_EXP :: 1024; // max binary exponent -F64_MIN :: 2.2250738585072014e-308; // min positive value -F64_MIN_10_EXP :: -307; // min decimal exponent -F64_MIN_EXP :: -1021; // min binary exponent -F64_RADIX :: 2; // exponent radix -F64_ROUNDS :: 1; // addition rounding: near + t := exp(2*x) + return (t - 1) / (t + 1) +} + +F16_DIG :: 3 +F16_EPSILON :: 0.00097656 +F16_GUARD :: 0 +F16_MANT_DIG :: 11 +F16_MAX :: 65504.0 +F16_MAX_10_EXP :: 4 +F16_MAX_EXP :: 15 +F16_MIN :: 6.10351562e-5 +F16_MIN_10_EXP :: -4 +F16_MIN_EXP :: -14 +F16_NORMALIZE :: 0 +F16_RADIX :: 2 +F16_ROUNDS :: 1 + + +F32_DIG :: 6 +F32_EPSILON :: 1.192092896e-07 +F32_GUARD :: 0 +F32_MANT_DIG :: 24 +F32_MAX :: 3.402823466e+38 +F32_MAX_10_EXP :: 38 +F32_MAX_EXP :: 128 +F32_MIN :: 1.175494351e-38 +F32_MIN_10_EXP :: -37 +F32_MIN_EXP :: -125 +F32_NORMALIZE :: 0 +F32_RADIX :: 2 +F32_ROUNDS :: 1 + +F64_DIG :: 15 // # of decimal digits of precision +F64_EPSILON :: 2.2204460492503131e-016 // smallest such that 1.0+F64_EPSILON != 1.0 +F64_MANT_DIG :: 53 // # of bits in mantissa +F64_MAX :: 1.7976931348623158e+308 // max value +F64_MAX_10_EXP :: 308 // max decimal exponent +F64_MAX_EXP :: 1024 // max binary exponent +F64_MIN :: 2.2250738585072014e-308 // min positive value +F64_MIN_10_EXP :: -307 // min decimal exponent +F64_MIN_EXP :: -1021 // min binary exponent +F64_RADIX :: 2 // exponent radix +F64_ROUNDS :: 1 // addition rounding: near diff --git a/core/math/rand/normal.odin b/core/math/rand/normal.odin index 653ca6c3b..4a77543ba 100644 --- a/core/math/rand/normal.odin +++ b/core/math/rand/normal.odin @@ -18,7 +18,7 @@ import "core:math" // sample = norm_float64() * std_dev + mean // norm_float64 :: proc(r: ^Rand = nil) -> f64 { - rn :: 3.442619855899; + rn :: 3.442619855899 @(static) kn := [128]u32{ @@ -48,7 +48,7 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 { 0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72, 0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a, 0x7ba90bdc, 0x7a722176, 0x77d664e5, - }; + } @(static) wn := [128]f32{ @@ -84,7 +84,7 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 { 1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09, 1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09, 1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09, - }; + } @(static) fn := [128]f32{ @@ -114,39 +114,39 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 { 0.044660863, 0.040742867, 0.03688439, 0.033087887, 0.029356318, 0.025693292, 0.022103304, 0.018592102, 0.015167298, 0.011839478, 0.008624485, 0.005548995, 0.0026696292, - }; + } - r := r; + r := r if r == nil { // NOTE(bill, 2020-09-07): Do this so that people can // enforce the global random state if necessary with `nil` - r = &global_rand; + r = &global_rand } for { - j := i32(uint32(r)); - i := j & 0x7f; - x := f64(j) * f64(wn[i]); + j := i32(uint32(r)) + i := j & 0x7f + x := f64(j) * f64(wn[i]) if u32(abs(j)) < kn[i] { // 99% of the time this will be hit - return x; + return x } if i == 0 { for { - x = -math.ln(float64(r)) * (1.0/ rn); - y := -math.ln(float64(r)); + x = -math.ln(float64(r)) * (1.0/ rn) + y := -math.ln(float64(r)) if y+y >= x*x { - break; + break } } - return j > 0 ? rn + x : -rn - x; + return j > 0 ? rn + x : -rn - x } if fn[i]+f32(float64(r))*(fn[i-1]-fn[i]) < f32(math.exp(-0.5*x*x)) { - return x; + return x } } - return 0; // NOTE(bill): Will never be hit but this is here for sanity's sake + return 0 // NOTE(bill): Will never be hit but this is here for sanity's sake } diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 812cdc53d..1a833d3ca 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -7,56 +7,56 @@ Rand :: struct { @(private) -_GLOBAL_SEED_DATA := 1234567890; +_GLOBAL_SEED_DATA := 1234567890 @(private) -global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA))); +global_rand := create(u64(uintptr(&_GLOBAL_SEED_DATA))) set_global_seed :: proc(seed: u64) { - init(&global_rand, seed); + init(&global_rand, seed) } create :: proc(seed: u64) -> Rand { - r: Rand; - init(&r, seed); - return r; + r: Rand + init(&r, seed) + return r } init :: proc(r: ^Rand, seed: u64) { - r.state = 0; - r.inc = (seed << 1) | 1; - _random(r); - r.state += seed; - _random(r); + r.state = 0 + r.inc = (seed << 1) | 1 + _random(r) + r.state += seed + _random(r) } _random :: proc(r: ^Rand) -> u32 { - r := r; + r := r if r == nil { // NOTE(bill, 2020-09-07): Do this so that people can // enforce the global random state if necessary with `nil` - r = &global_rand; + r = &global_rand } - old_state := r.state; - r.state = old_state * 6364136223846793005 + (r.inc|1); - xor_shifted := u32(((old_state>>18) ~ old_state) >> 27); - rot := u32(old_state >> 59); - return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31)); + old_state := r.state + r.state = old_state * 6364136223846793005 + (r.inc|1) + xor_shifted := u32(((old_state>>18) ~ old_state) >> 27) + rot := u32(old_state >> 59) + return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31)) } uint32 :: proc(r: ^Rand = nil) -> u32 { return _random(r); } uint64 :: proc(r: ^Rand = nil) -> u64 { - a := u64(_random(r)); - b := u64(_random(r)); - return (a<<32) | b; + a := u64(_random(r)) + b := u64(_random(r)) + return (a<<32) | b } uint128 :: proc(r: ^Rand = nil) -> u128 { - a := u128(_random(r)); - b := u128(_random(r)); - c := u128(_random(r)); - d := u128(_random(r)); - return (a<<96) | (b<<64) | (c<<32) | d; + a := u128(_random(r)) + b := u128(_random(r)) + c := u128(_random(r)) + d := u128(_random(r)) + return (a<<96) | (b<<64) | (c<<32) | d } int31 :: proc(r: ^Rand = nil) -> i32 { return i32(uint32(r) << 1 >> 1); } @@ -65,57 +65,57 @@ int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1); } int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 { if n <= 0 { - panic("Invalid argument to int31_max"); + panic("Invalid argument to int31_max") } if n&(n-1) == 0 { - return int31(r) & (n-1); + return int31(r) & (n-1) } - max := i32((1<<31) - 1 - (1<<31)&u32(n)); - v := int31(r); + max := i32((1<<31) - 1 - (1<<31)&u32(n)) + v := int31(r) for v > max { - v = int31(r); + v = int31(r) } - return v % n; + return v % n } int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 { if n <= 0 { - panic("Invalid argument to int63_max"); + panic("Invalid argument to int63_max") } if n&(n-1) == 0 { - return int63(r) & (n-1); + return int63(r) & (n-1) } - max := i64((1<<63) - 1 - (1<<63)&u64(n)); - v := int63(r); + max := i64((1<<63) - 1 - (1<<63)&u64(n)) + v := int63(r) for v > max { - v = int63(r); + v = int63(r) } - return v % n; + return v % n } int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 { if n <= 0 { - panic("Invalid argument to int127_max"); + panic("Invalid argument to int127_max") } if n&(n-1) == 0 { - return int127(r) & (n-1); + return int127(r) & (n-1) } - max := i128((1<<63) - 1 - (1<<63)&u128(n)); - v := int127(r); + max := i128((1<<63) - 1 - (1<<63)&u128(n)) + v := int127(r) for v > max { - v = int127(r); + v = int127(r) } - return v % n; + return v % n } int_max :: proc(n: int, r: ^Rand = nil) -> int { if n <= 0 { - panic("Invalid argument to int_max"); + panic("Invalid argument to int_max") } when size_of(int) == 4 { - return int(int31_max(i32(n), r)); + return int(int31_max(i32(n), r)) } else { - return int(int63_max(i64(n), r)); + return int(int63_max(i64(n), r)) } } @@ -127,40 +127,40 @@ float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) { - pos := i8(0); - val := i64(0); + pos := i8(0) + val := i64(0) for n = 0; n < len(p); n += 1 { if pos == 0 { - val = int63(r); - pos = 7; + val = int63(r) + pos = 7 } - p[n] = byte(val); - val >>= 8; - pos -= 1; + p[n] = byte(val) + val >>= 8 + pos -= 1 } - return; + return } // perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n) perm :: proc(n: int, r: ^Rand = nil) -> []int { - m := make([]int, n); + m := make([]int, n) for i := 0; i < n; i += 1 { - j := int_max(i+1, r); - m[i] = m[j]; - m[j] = i; + j := int_max(i+1, r) + m[i] = m[j] + m[j] = i } - return m; + return m } shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) { - n := i64(len(array)); + n := i64(len(array)) if n < 2 { - return; + return } for i := i64(0); i < n; i += 1 { - j := int63_max(n, r); - array[i], array[j] = array[j], array[i]; + j := int63_max(n, r) + array[i], array[j] = array[j], array[i] } } |