From b2a2aa15c25a93f22c3c22810ade7bfb5651b6da Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 12:49:39 +0000 Subject: [PATCH 01/13] Add `ODIN_BUILD_MODE` --- core/runtime/internal.odin | 35 ++++++++++++++++++----------------- src/build_settings.cpp | 19 +++++++++++++++++++ src/checker.cpp | 2 ++ src/main.cpp | 2 +- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 2b8dcd36a..e0cbc8360 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -3,7 +3,8 @@ package runtime import "core:intrinsics" @(private) -RUNTIME_LINKAGE :: "strong" when ODIN_USE_SEPARATE_MODULES else "internal" +RUNTIME_LINKAGE :: "strong" when (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic_library") else "internal" +RUNTIME_EXPORT :: ODIN_BUILD_MODE == "dynamic" @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check { @@ -649,7 +650,7 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { return quaternion(t0, t1, t2, t3) } -@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require) +@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) truncsfhf2 :: proc "c" (value: f32) -> u16 { v: struct #raw_union { i: u32, f: f32 } i, s, e, m: i32 @@ -707,12 +708,12 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 { } -@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require) +@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) truncdfhf2 :: proc "c" (value: f64) -> u16 { return truncsfhf2(f32(value)) } -@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require) +@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { fp32 :: struct #raw_union { u: u32, f: f32 } @@ -731,19 +732,19 @@ gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { } -@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require) +@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) gnu_f2h_ieee :: proc "c" (value: f32) -> u16 { return truncsfhf2(value) } -@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require) +@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) extendhfsf2 :: proc "c" (value: u16) -> f32 { return gnu_h2f_ieee(value) } -@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require) +@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) floattidf :: proc "c" (a: i128) -> f64 { DBL_MANT_DIG :: 53 if a == 0 { @@ -786,7 +787,7 @@ floattidf :: proc "c" (a: i128) -> f64 { } -@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require) +@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) floattidf_unsigned :: proc "c" (a: u128) -> f64 { DBL_MANT_DIG :: 53 if a == 0 { @@ -828,14 +829,14 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 { -@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require) +@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 { // TODO(bill): implement `fixunsdfti` correctly x := u64(a) return u128(x) } -@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require) +@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { // TODO(bill): implement `fixunsdfdi` correctly x := i64(a) @@ -845,7 +846,7 @@ fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { -@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) umodti3 :: proc "c" (a, b: u128) -> u128 { r: u128 = --- _ = udivmod128(a, b, &r) @@ -853,18 +854,18 @@ umodti3 :: proc "c" (a, b: u128) -> u128 { } -@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require) +@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { return udivmod128(a, b, rem) } -@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) udivti3 :: proc "c" (a, b: u128) -> u128 { return udivmodti4(a, b, nil) } -@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) modti3 :: proc "c" (a, b: i128) -> i128 { s_a := a >> (128 - 1) s_b := b >> (128 - 1) @@ -877,20 +878,20 @@ modti3 :: proc "c" (a, b: i128) -> i128 { } -@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require) +@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 { u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem) return transmute(i128)u } -@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require) +@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) divti3 :: proc "c" (a, b: i128) -> i128 { u := udivmodti4(transmute(u128)a, transmute(u128)b, nil) return transmute(i128)u } -@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require) +@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) fixdfti :: proc(a: u64) -> i128 { significandBits :: 52 typeWidth :: (size_of(u64)*8) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 63752ce68..fa8922f61 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -166,6 +166,7 @@ struct BuildContext { String ODIN_VENDOR; // compiler vendor String ODIN_VERSION; // compiler version String ODIN_ROOT; // Odin ROOT + String ODIN_BUILD_MODE; bool ODIN_DEBUG; // Odin in debug mode bool ODIN_DISABLE_ASSERT; // Whether the default 'assert' et al is disabled in code or not bool ODIN_DEFAULT_TO_NIL_ALLOCATOR; // Whether the default allocator is a "nil" allocator or not (i.e. it does nothing) @@ -815,6 +816,24 @@ void init_build_context(TargetMetrics *cross_target) { bc->ODIN_VENDOR = str_lit("odin"); bc->ODIN_VERSION = ODIN_VERSION; bc->ODIN_ROOT = odin_root_dir(); + switch (bc->build_mode) { + default: + case BuildMode_Executable: + bc->ODIN_BUILD_MODE = str_lit("executable"); + break; + case BuildMode_DynamicLibrary: + bc->ODIN_BUILD_MODE = str_lit("dynamic"); + break; + case BuildMode_Object: + bc->ODIN_BUILD_MODE = str_lit("object"); + break; + case BuildMode_Assembly: + bc->ODIN_BUILD_MODE = str_lit("assembly"); + break; + case BuildMode_LLVM_IR: + bc->ODIN_BUILD_MODE = str_lit("llvm-ir"); + break; + } bc->copy_file_contents = true; diff --git a/src/checker.cpp b/src/checker.cpp index 591377726..1a92b1c06 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -778,6 +778,8 @@ void init_universal(void) { add_global_string_constant("ODIN_VENDOR", bc->ODIN_VENDOR); add_global_string_constant("ODIN_VERSION", bc->ODIN_VERSION); add_global_string_constant("ODIN_ROOT", bc->ODIN_ROOT); + + add_global_string_constant("ODIN_BUILD_MODE", bc->ODIN_BUILD_MODE); add_global_bool_constant("ODIN_DEBUG", bc->ODIN_DEBUG); add_global_bool_constant("ODIN_DISABLE_ASSERT", bc->ODIN_DISABLE_ASSERT); add_global_bool_constant("ODIN_DEFAULT_TO_NIL_ALLOCATOR", bc->ODIN_DEFAULT_TO_NIL_ALLOCATOR); diff --git a/src/main.cpp b/src/main.cpp index 55439337d..e79e7203d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1185,7 +1185,7 @@ bool parse_build_flags(Array args) { break; } - if (str == "dll" || str == "shared") { + if (str == "dll" || str == "shared" || str == "dynamic") { build_context.build_mode = BuildMode_DynamicLibrary; } else if (str == "obj" || str == "object") { build_context.build_mode = BuildMode_Object; From 7ef3c87dbb1455c5058878f69db93cdcdb16bcfd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 13:52:53 +0000 Subject: [PATCH 02/13] Change `RUNTIME_LINKAGE` requirements --- core/runtime/internal.odin | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index e0cbc8360..5ab91e627 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -3,8 +3,7 @@ package runtime import "core:intrinsics" @(private) -RUNTIME_LINKAGE :: "strong" when (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic_library") else "internal" -RUNTIME_EXPORT :: ODIN_BUILD_MODE == "dynamic" +RUNTIME_LINKAGE :: "strong" when (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic") else "internal" @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check { @@ -650,7 +649,7 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 { return quaternion(t0, t1, t2, t3) } -@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require) truncsfhf2 :: proc "c" (value: f32) -> u16 { v: struct #raw_union { i: u32, f: f32 } i, s, e, m: i32 @@ -708,12 +707,12 @@ truncsfhf2 :: proc "c" (value: f32) -> u16 { } -@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require) truncdfhf2 :: proc "c" (value: f64) -> u16 { return truncsfhf2(f32(value)) } -@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require) gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { fp32 :: struct #raw_union { u: u32, f: f32 } @@ -732,19 +731,19 @@ gnu_h2f_ieee :: proc "c" (value: u16) -> f32 { } -@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require) gnu_f2h_ieee :: proc "c" (value: f32) -> u16 { return truncsfhf2(value) } -@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require) extendhfsf2 :: proc "c" (value: u16) -> f32 { return gnu_h2f_ieee(value) } -@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__floattidf", linkage=RUNTIME_LINKAGE, require) floattidf :: proc "c" (a: i128) -> f64 { DBL_MANT_DIG :: 53 if a == 0 { @@ -787,7 +786,7 @@ floattidf :: proc "c" (a: i128) -> f64 { } -@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__floattidf_unsigned", linkage=RUNTIME_LINKAGE, require) floattidf_unsigned :: proc "c" (a: u128) -> f64 { DBL_MANT_DIG :: 53 if a == 0 { @@ -829,14 +828,14 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 { -@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__fixunsdfti", linkage=RUNTIME_LINKAGE, require) fixunsdfti :: #force_no_inline proc "c" (a: f64) -> u128 { // TODO(bill): implement `fixunsdfti` correctly x := u64(a) return u128(x) } -@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__fixunsdfdi", linkage=RUNTIME_LINKAGE, require) fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { // TODO(bill): implement `fixunsdfdi` correctly x := i64(a) @@ -846,7 +845,7 @@ fixunsdfdi :: #force_no_inline proc "c" (a: f64) -> i128 { -@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__umodti3", linkage=RUNTIME_LINKAGE, require) umodti3 :: proc "c" (a, b: u128) -> u128 { r: u128 = --- _ = udivmod128(a, b, &r) @@ -854,18 +853,18 @@ umodti3 :: proc "c" (a, b: u128) -> u128 { } -@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__udivmodti4", linkage=RUNTIME_LINKAGE, require) udivmodti4 :: proc "c" (a, b: u128, rem: ^u128) -> u128 { return udivmod128(a, b, rem) } -@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__udivti3", linkage=RUNTIME_LINKAGE, require) udivti3 :: proc "c" (a, b: u128) -> u128 { return udivmodti4(a, b, nil) } -@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__modti3", linkage=RUNTIME_LINKAGE, require) modti3 :: proc "c" (a, b: i128) -> i128 { s_a := a >> (128 - 1) s_b := b >> (128 - 1) @@ -878,20 +877,20 @@ modti3 :: proc "c" (a, b: i128) -> i128 { } -@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__divmodti4", linkage=RUNTIME_LINKAGE, require) divmodti4 :: proc "c" (a, b: i128, rem: ^i128) -> i128 { u := udivmod128(transmute(u128)a, transmute(u128)b, cast(^u128)rem) return transmute(i128)u } -@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__divti3", linkage=RUNTIME_LINKAGE, require) divti3 :: proc "c" (a, b: i128) -> i128 { u := udivmodti4(transmute(u128)a, transmute(u128)b, nil) return transmute(i128)u } -@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require, export=RUNTIME_EXPORT) +@(link_name="__fixdfti", linkage=RUNTIME_LINKAGE, require) fixdfti :: proc(a: u64) -> i128 { significandBits :: 52 typeWidth :: (size_of(u64)*8) From 14351c5bf2adb58597a3ba003c4bb2abb1073da3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 13:56:38 +0000 Subject: [PATCH 03/13] Simplify logic for procs.odin --- core/runtime/procs.odin | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index d3233c31b..c69e5b00a 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -1,7 +1,7 @@ package runtime -when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" { - @(link_name="memset", require) +when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || ODIN_NO_CRT { + @(link_name="memset", linkage="strong", require) memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { if ptr != nil && len != 0 { b := byte(val) @@ -13,7 +13,7 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" { return ptr } - @(link_name="memmove", require) + @(link_name="memmove", linkage="strong", require) memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { if dst != src { d, s := ([^]byte)(dst), ([^]byte)(src) @@ -25,32 +25,7 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" { return dst } -} else when ODIN_NO_CRT { - @(link_name="memset", linkage=RUNTIME_LINKAGE, require) - memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { - if ptr != nil && len != 0 { - b := byte(val) - p := ([^]byte)(ptr) - for i in 0.. rawptr { - if dst != src { - d, s := ([^]byte)(dst), ([^]byte)(src) - d_end, s_end := d[len:], s[len:] - for i := len-1; i >= 0; i -= 1 { - d[i] = s[i] - } - } - return dst - - } - @(link_name="memcpy", linkage=RUNTIME_LINKAGE, require) + @(link_name="memcpy", linkage="strong", require) memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { if dst != src { d, s := ([^]byte)(dst), ([^]byte)(src) From 7bb7a741c6dda281f9c96bf3efa09cfbd58cc467 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:07:05 +0000 Subject: [PATCH 04/13] Make `math` procedure `contextless`; Add `asinh`, `acosh`, `atanh` --- core/math/math.odin | 595 ++++++++++++++++++++++---------------------- 1 file changed, 302 insertions(+), 293 deletions(-) diff --git a/core/math/math.odin b/core/math/math.odin index 3b26a972f..445bf0c64 100644 --- a/core/math/math.odin +++ b/core/math/math.odin @@ -96,96 +96,96 @@ foreign _ { ldexp_f64 :: proc(val: f64, exp: i32) -> f64 --- } -sqrt_f16le :: proc(x: f16le) -> f16le { return #force_inline f16le(sqrt_f16(f16(x))) } -sqrt_f16be :: proc(x: f16be) -> f16be { return #force_inline f16be(sqrt_f16(f16(x))) } -sqrt_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(sqrt_f32(f32(x))) } -sqrt_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(sqrt_f32(f32(x))) } -sqrt_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(sqrt_f64(f64(x))) } -sqrt_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(sqrt_f64(f64(x))) } +sqrt_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(sqrt_f16(f16(x))) } +sqrt_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(sqrt_f16(f16(x))) } +sqrt_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(sqrt_f32(f32(x))) } +sqrt_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(sqrt_f32(f32(x))) } +sqrt_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(sqrt_f64(f64(x))) } +sqrt_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(sqrt_f64(f64(x))) } 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(θ))) } -sin_f32le :: proc(θ: f32le) -> f32le { return #force_inline f32le(sin_f32(f32(θ))) } -sin_f32be :: proc(θ: f32be) -> f32be { return #force_inline f32be(sin_f32(f32(θ))) } -sin_f64le :: proc(θ: f64le) -> f64le { return #force_inline f64le(sin_f64(f64(θ))) } -sin_f64be :: proc(θ: f64be) -> f64be { return #force_inline f64be(sin_f64(f64(θ))) } +sin_f16le :: proc "contextless" (θ: f16le) -> f16le { return #force_inline f16le(sin_f16(f16(θ))) } +sin_f16be :: proc "contextless" (θ: f16be) -> f16be { return #force_inline f16be(sin_f16(f16(θ))) } +sin_f32le :: proc "contextless" (θ: f32le) -> f32le { return #force_inline f32le(sin_f32(f32(θ))) } +sin_f32be :: proc "contextless" (θ: f32be) -> f32be { return #force_inline f32be(sin_f32(f32(θ))) } +sin_f64le :: proc "contextless" (θ: f64le) -> f64le { return #force_inline f64le(sin_f64(f64(θ))) } +sin_f64be :: proc "contextless" (θ: f64be) -> f64be { return #force_inline f64be(sin_f64(f64(θ))) } 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(θ))) } -cos_f32le :: proc(θ: f32le) -> f32le { return #force_inline f32le(cos_f32(f32(θ))) } -cos_f32be :: proc(θ: f32be) -> f32be { return #force_inline f32be(cos_f32(f32(θ))) } -cos_f64le :: proc(θ: f64le) -> f64le { return #force_inline f64le(cos_f64(f64(θ))) } -cos_f64be :: proc(θ: f64be) -> f64be { return #force_inline f64be(cos_f64(f64(θ))) } +cos_f16le :: proc "contextless" (θ: f16le) -> f16le { return #force_inline f16le(cos_f16(f16(θ))) } +cos_f16be :: proc "contextless" (θ: f16be) -> f16be { return #force_inline f16be(cos_f16(f16(θ))) } +cos_f32le :: proc "contextless" (θ: f32le) -> f32le { return #force_inline f32le(cos_f32(f32(θ))) } +cos_f32be :: proc "contextless" (θ: f32be) -> f32be { return #force_inline f32be(cos_f32(f32(θ))) } +cos_f64le :: proc "contextless" (θ: f64le) -> f64le { return #force_inline f64le(cos_f64(f64(θ))) } +cos_f64be :: proc "contextless" (θ: f64be) -> f64be { return #force_inline f64be(cos_f64(f64(θ))) } 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))) } -pow_f32le :: proc(x, power: f32le) -> f32le { return #force_inline f32le(pow_f32(f32(x), f32(power))) } -pow_f32be :: proc(x, power: f32be) -> f32be { return #force_inline f32be(pow_f32(f32(x), f32(power))) } -pow_f64le :: proc(x, power: f64le) -> f64le { return #force_inline f64le(pow_f64(f64(x), f64(power))) } -pow_f64be :: proc(x, power: f64be) -> f64be { return #force_inline f64be(pow_f64(f64(x), f64(power))) } +pow_f16le :: proc "contextless" (x, power: f16le) -> f16le { return #force_inline f16le(pow_f16(f16(x), f16(power))) } +pow_f16be :: proc "contextless" (x, power: f16be) -> f16be { return #force_inline f16be(pow_f16(f16(x), f16(power))) } +pow_f32le :: proc "contextless" (x, power: f32le) -> f32le { return #force_inline f32le(pow_f32(f32(x), f32(power))) } +pow_f32be :: proc "contextless" (x, power: f32be) -> f32be { return #force_inline f32be(pow_f32(f32(x), f32(power))) } +pow_f64le :: proc "contextless" (x, power: f64le) -> f64le { return #force_inline f64le(pow_f64(f64(x), f64(power))) } +pow_f64be :: proc "contextless" (x, power: f64be) -> f64be { return #force_inline f64be(pow_f64(f64(x), f64(power))) } 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))) } -fmuladd_f32le :: proc(a, b, c: f32le) -> f32le { return #force_inline f32le(fmuladd_f32(f32(a), f32(b), f32(c))) } -fmuladd_f32be :: proc(a, b, c: f32be) -> f32be { return #force_inline f32be(fmuladd_f32(f32(a), f32(b), f32(c))) } -fmuladd_f64le :: proc(a, b, c: f64le) -> f64le { return #force_inline f64le(fmuladd_f64(f64(a), f64(b), f64(c))) } -fmuladd_f64be :: proc(a, b, c: f64be) -> f64be { return #force_inline f64be(fmuladd_f64(f64(a), f64(b), f64(c))) } +fmuladd_f16le :: proc "contextless" (a, b, c: f16le) -> f16le { return #force_inline f16le(fmuladd_f16(f16(a), f16(b), f16(c))) } +fmuladd_f16be :: proc "contextless" (a, b, c: f16be) -> f16be { return #force_inline f16be(fmuladd_f16(f16(a), f16(b), f16(c))) } +fmuladd_f32le :: proc "contextless" (a, b, c: f32le) -> f32le { return #force_inline f32le(fmuladd_f32(f32(a), f32(b), f32(c))) } +fmuladd_f32be :: proc "contextless" (a, b, c: f32be) -> f32be { return #force_inline f32be(fmuladd_f32(f32(a), f32(b), f32(c))) } +fmuladd_f64le :: proc "contextless" (a, b, c: f64le) -> f64le { return #force_inline f64le(fmuladd_f64(f64(a), f64(b), f64(c))) } +fmuladd_f64be :: proc "contextless" (a, b, c: f64be) -> f64be { return #force_inline f64be(fmuladd_f64(f64(a), f64(b), f64(c))) } 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))) } -ln_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(ln_f32(f32(x))) } -ln_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(ln_f32(f32(x))) } -ln_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) } -ln_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) } +ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f16(f16(x))) } +ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f16(f16(x))) } +ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f32(f32(x))) } +ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f32(f32(x))) } +ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) } +ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) } 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))) } -exp_f32le :: proc(x: f32le) -> f32le { return #force_inline f32le(exp_f32(f32(x))) } -exp_f32be :: proc(x: f32be) -> f32be { return #force_inline f32be(exp_f32(f32(x))) } -exp_f64le :: proc(x: f64le) -> f64le { return #force_inline f64le(exp_f64(f64(x))) } -exp_f64be :: proc(x: f64be) -> f64be { return #force_inline f64be(exp_f64(f64(x))) } +exp_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(exp_f16(f16(x))) } +exp_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(exp_f16(f16(x))) } +exp_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(exp_f32(f32(x))) } +exp_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(exp_f32(f32(x))) } +exp_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(exp_f64(f64(x))) } +exp_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(exp_f64(f64(x))) } 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)) } -ldexp_f32le :: proc(val: f32le, exp: i32) -> f32le { return #force_inline f32le(ldexp_f32(f32(val), exp)) } -ldexp_f32be :: proc(val: f32be, exp: i32) -> f32be { return #force_inline f32be(ldexp_f32(f32(val), exp)) } -ldexp_f64le :: proc(val: f64le, exp: i32) -> f64le { return #force_inline f64le(ldexp_f64(f64(val), exp)) } -ldexp_f64be :: proc(val: f64be, exp: i32) -> f64be { return #force_inline f64be(ldexp_f64(f64(val), exp)) } +ldexp_f16le :: proc "contextless" (val: f16le, exp: i32) -> f16le { return #force_inline f16le(ldexp_f16(f16(val), exp)) } +ldexp_f16be :: proc "contextless" (val: f16be, exp: i32) -> f16be { return #force_inline f16be(ldexp_f16(f16(val), exp)) } +ldexp_f32le :: proc "contextless" (val: f32le, exp: i32) -> f32le { return #force_inline f32le(ldexp_f32(f32(val), exp)) } +ldexp_f32be :: proc "contextless" (val: f32be, exp: i32) -> f32be { return #force_inline f32be(ldexp_f32(f32(val), exp)) } +ldexp_f64le :: proc "contextless" (val: f64le, exp: i32) -> f64le { return #force_inline f64le(ldexp_f64(f64(val), exp)) } +ldexp_f64be :: proc "contextless" (val: f64be, exp: i32) -> f64be { return #force_inline f64be(ldexp_f64(f64(val), exp)) } ldexp :: proc{ ldexp_f16, ldexp_f16le, ldexp_f16be, ldexp_f32, ldexp_f32le, ldexp_f32be, @@ -193,82 +193,82 @@ ldexp :: proc{ } -log_f16 :: proc(x, base: f16) -> f16 { return ln(x) / ln(base) } -log_f16le :: proc(x, base: f16le) -> f16le { return f16le(log_f16(f16(x), f16(base))) } -log_f16be :: proc(x, base: f16be) -> f16be { return f16be(log_f16(f16(x), f16(base))) } +log_f16 :: proc "contextless" (x, base: f16) -> f16 { return ln(x) / ln(base) } +log_f16le :: proc "contextless" (x, base: f16le) -> f16le { return f16le(log_f16(f16(x), f16(base))) } +log_f16be :: proc "contextless" (x, base: f16be) -> f16be { return f16be(log_f16(f16(x), f16(base))) } -log_f32 :: proc(x, base: f32) -> f32 { return ln(x) / ln(base) } -log_f32le :: proc(x, base: f32le) -> f32le { return f32le(log_f32(f32(x), f32(base))) } -log_f32be :: proc(x, base: f32be) -> f32be { return f32be(log_f32(f32(x), f32(base))) } +log_f32 :: proc "contextless" (x, base: f32) -> f32 { return ln(x) / ln(base) } +log_f32le :: proc "contextless" (x, base: f32le) -> f32le { return f32le(log_f32(f32(x), f32(base))) } +log_f32be :: proc "contextless" (x, base: f32be) -> f32be { return f32be(log_f32(f32(x), f32(base))) } -log_f64 :: proc(x, base: f64) -> f64 { return ln(x) / ln(base) } -log_f64le :: proc(x, base: f64le) -> f64le { return f64le(log_f64(f64(x), f64(base))) } -log_f64be :: proc(x, base: f64be) -> f64be { return f64be(log_f64(f64(x), f64(base))) } +log_f64 :: proc "contextless" (x, base: f64) -> f64 { return ln(x) / ln(base) } +log_f64le :: proc "contextless" (x, base: f64le) -> f64le { return f64le(log_f64(f64(x), f64(base))) } +log_f64be :: proc "contextless" (x, base: f64be) -> f64be { return f64be(log_f64(f64(x), f64(base))) } 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))) } -log2_f16be :: proc(x: f16be) -> f16be { return f16be(log2_f16(f16(x))) } +log2_f16 :: proc "contextless" (x: f16) -> f16 { return ln(x)/LN2 } +log2_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(log2_f16(f16(x))) } +log2_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(log2_f16(f16(x))) } -log2_f32 :: proc(x: f32) -> f32 { return ln(x)/LN2 } -log2_f32le :: proc(x: f32le) -> f32le { return f32le(log2_f32(f32(x))) } -log2_f32be :: proc(x: f32be) -> f32be { return f32be(log2_f32(f32(x))) } +log2_f32 :: proc "contextless" (x: f32) -> f32 { return ln(x)/LN2 } +log2_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(log2_f32(f32(x))) } +log2_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(log2_f32(f32(x))) } -log2_f64 :: proc(x: f64) -> f64 { return ln(x)/LN2 } -log2_f64le :: proc(x: f64le) -> f64le { return f64le(log2_f64(f64(x))) } -log2_f64be :: proc(x: f64be) -> f64be { return f64be(log2_f64(f64(x))) } +log2_f64 :: proc "contextless" (x: f64) -> f64 { return ln(x)/LN2 } +log2_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(log2_f64(f64(x))) } +log2_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(log2_f64(f64(x))) } 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))) } -log10_f16be :: proc(x: f16be) -> f16be { return f16be(log10_f16(f16(x))) } +log10_f16 :: proc "contextless" (x: f16) -> f16 { return ln(x)/LN10 } +log10_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(log10_f16(f16(x))) } +log10_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(log10_f16(f16(x))) } -log10_f32 :: proc(x: f32) -> f32 { return ln(x)/LN10 } -log10_f32le :: proc(x: f32le) -> f32le { return f32le(log10_f32(f32(x))) } -log10_f32be :: proc(x: f32be) -> f32be { return f32be(log10_f32(f32(x))) } +log10_f32 :: proc "contextless" (x: f32) -> f32 { return ln(x)/LN10 } +log10_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(log10_f32(f32(x))) } +log10_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(log10_f32(f32(x))) } -log10_f64 :: proc(x: f64) -> f64 { return ln(x)/LN10 } -log10_f64le :: proc(x: f64le) -> f64le { return f64le(log10_f64(f64(x))) } -log10_f64be :: proc(x: f64be) -> f64be { return f64be(log10_f64(f64(x))) } +log10_f64 :: proc "contextless" (x: f64) -> f64 { return ln(x)/LN10 } +log10_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(log10_f64(f64(x))) } +log10_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(log10_f64(f64(x))) } 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(θ))) } -tan_f16be :: proc(θ: f16be) -> f16be { return f16be(tan_f16(f16(θ))) } +tan_f16 :: proc "contextless" (θ: f16) -> f16 { return sin(θ)/cos(θ) } +tan_f16le :: proc "contextless" (θ: f16le) -> f16le { return f16le(tan_f16(f16(θ))) } +tan_f16be :: proc "contextless" (θ: f16be) -> f16be { return f16be(tan_f16(f16(θ))) } -tan_f32 :: proc(θ: f32) -> f32 { return sin(θ)/cos(θ) } -tan_f32le :: proc(θ: f32le) -> f32le { return f32le(tan_f32(f32(θ))) } -tan_f32be :: proc(θ: f32be) -> f32be { return f32be(tan_f32(f32(θ))) } +tan_f32 :: proc "contextless" (θ: f32) -> f32 { return sin(θ)/cos(θ) } +tan_f32le :: proc "contextless" (θ: f32le) -> f32le { return f32le(tan_f32(f32(θ))) } +tan_f32be :: proc "contextless" (θ: f32be) -> f32be { return f32be(tan_f32(f32(θ))) } -tan_f64 :: proc(θ: f64) -> f64 { return sin(θ)/cos(θ) } -tan_f64le :: proc(θ: f64le) -> f64le { return f64le(tan_f64(f64(θ))) } -tan_f64be :: proc(θ: f64be) -> f64be { return f64be(tan_f64(f64(θ))) } +tan_f64 :: proc "contextless" (θ: f64) -> f64 { return sin(θ)/cos(θ) } +tan_f64le :: proc "contextless" (θ: f64le) -> f64le { return f64le(tan_f64(f64(θ))) } +tan_f64be :: proc "contextless" (θ: f64be) -> f64be { return f64be(tan_f64(f64(θ))) } 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) } +lerp :: proc "contextless" (a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t } +saturate :: proc "contextless" (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) { +unlerp :: proc "contextless" (a, b, x: $T) -> (t: T) where intrinsics.type_is_float(T), !intrinsics.type_is_array(T) { 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) { +remap :: proc "contextless" (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 if old_range == 0 { @@ -277,33 +277,33 @@ remap :: proc(old_value, old_min, old_max, new_min, new_max: $T) -> (x: T) where 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) { +wrap :: proc "contextless" (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 } -angle_diff :: proc(a, b: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { +angle_diff :: proc "contextless" (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 } -angle_lerp :: proc(a, b, t: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { +angle_lerp :: proc "contextless" (a, b, t: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(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) { +step :: proc "contextless" (edge, x: $T) -> T where intrinsics.type_is_numeric(T), !intrinsics.type_is_array(T) { 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) { +smoothstep :: proc "contextless" (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) } -bias :: proc(t, b: $T) -> T where intrinsics.type_is_numeric(T) { +bias :: proc "contextless" (t, b: $T) -> T where intrinsics.type_is_numeric(T) { return t / (((1/b) - 2) * (1 - t) + 1) } -gain :: proc(t, g: $T) -> T where intrinsics.type_is_numeric(T) { +gain :: proc "contextless" (t, g: $T) -> T where intrinsics.type_is_numeric(T) { if t < 0.5 { return bias(t*2, g)*0.5 } @@ -311,93 +311,93 @@ gain :: proc(t, g: $T) -> T where intrinsics.type_is_numeric(T) { } -sign_f16 :: proc(x: f16) -> f16 { return f16(int(0 < x) - int(x < 0)) } -sign_f16le :: proc(x: f16le) -> f16le { return f16le(int(0 < x) - int(x < 0)) } -sign_f16be :: proc(x: f16be) -> f16be { return f16be(int(0 < x) - int(x < 0)) } -sign_f32 :: proc(x: f32) -> f32 { return f32(int(0 < x) - int(x < 0)) } -sign_f32le :: proc(x: f32le) -> f32le { return f32le(int(0 < x) - int(x < 0)) } -sign_f32be :: proc(x: f32be) -> f32be { return f32be(int(0 < x) - int(x < 0)) } -sign_f64 :: proc(x: f64) -> f64 { return f64(int(0 < x) - int(x < 0)) } -sign_f64le :: proc(x: f64le) -> f64le { return f64le(int(0 < x) - int(x < 0)) } -sign_f64be :: proc(x: f64be) -> f64be { return f64be(int(0 < x) - int(x < 0)) } +sign_f16 :: proc "contextless" (x: f16) -> f16 { return f16(int(0 < x) - int(x < 0)) } +sign_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(int(0 < x) - int(x < 0)) } +sign_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(int(0 < x) - int(x < 0)) } +sign_f32 :: proc "contextless" (x: f32) -> f32 { return f32(int(0 < x) - int(x < 0)) } +sign_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(int(0 < x) - int(x < 0)) } +sign_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(int(0 < x) - int(x < 0)) } +sign_f64 :: proc "contextless" (x: f64) -> f64 { return f64(int(0 < x) - int(x < 0)) } +sign_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(int(0 < x) - int(x < 0)) } +sign_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(int(0 < x) - int(x < 0)) } 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 { +sign_bit_f16 :: proc "contextless" (x: f16) -> bool { 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 { +sign_bit_f16le :: proc "contextless" (x: f16le) -> bool { return #force_inline sign_bit_f16(f16(x)) } +sign_bit_f16be :: proc "contextless" (x: f16be) -> bool { return #force_inline sign_bit_f16(f16(x)) } +sign_bit_f32 :: proc "contextless" (x: f32) -> bool { 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 { +sign_bit_f32le :: proc "contextless" (x: f32le) -> bool { return #force_inline sign_bit_f32(f32(x)) } +sign_bit_f32be :: proc "contextless" (x: f32be) -> bool { return #force_inline sign_bit_f32(f32(x)) } +sign_bit_f64 :: proc "contextless" (x: f64) -> bool { 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)) } +sign_bit_f64le :: proc "contextless" (x: f64le) -> bool { return #force_inline sign_bit_f64(f64(x)) } +sign_bit_f64be :: proc "contextless" (x: f64be) -> bool { return #force_inline sign_bit_f64(f64(x)) } 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 { +copy_sign_f16 :: proc "contextless" (x, y: f16) -> f16 { 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 { +copy_sign_f16le :: proc "contextless" (x, y: f16le) -> f16le { return #force_inline f16le(copy_sign_f16(f16(x), f16(y))) } +copy_sign_f16be :: proc "contextless" (x, y: f16be) -> f16be { return #force_inline f16be(copy_sign_f16(f16(x), f16(y))) } +copy_sign_f32 :: proc "contextless" (x, y: f32) -> f32 { 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 { +copy_sign_f32le :: proc "contextless" (x, y: f32le) -> f32le { return #force_inline f32le(copy_sign_f32(f32(x), f32(y))) } +copy_sign_f32be :: proc "contextless" (x, y: f32be) -> f32be { return #force_inline f32be(copy_sign_f32(f32(x), f32(y))) } +copy_sign_f64 :: proc "contextless" (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 } -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))) } +copy_sign_f64le :: proc "contextless" (x, y: f64le) -> f64le { return #force_inline f64le(copy_sign_f64(f64(x), f64(y))) } +copy_sign_f64be :: proc "contextless" (x, y: f64be) -> f64be { return #force_inline f64be(copy_sign_f64(f64(x), f64(y))) } 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 } -to_radians_f16be :: proc(degrees: f16be) -> f16be { return degrees * RAD_PER_DEG } -to_radians_f32 :: proc(degrees: f32) -> f32 { return degrees * RAD_PER_DEG } -to_radians_f32le :: proc(degrees: f32le) -> f32le { return degrees * RAD_PER_DEG } -to_radians_f32be :: proc(degrees: f32be) -> f32be { return degrees * RAD_PER_DEG } -to_radians_f64 :: proc(degrees: f64) -> f64 { return degrees * RAD_PER_DEG } -to_radians_f64le :: proc(degrees: f64le) -> f64le { return degrees * RAD_PER_DEG } -to_radians_f64be :: proc(degrees: f64be) -> f64be { return degrees * RAD_PER_DEG } -to_degrees_f16 :: proc(radians: f16) -> f16 { return radians * DEG_PER_RAD } -to_degrees_f16le :: proc(radians: f16le) -> f16le { return radians * DEG_PER_RAD } -to_degrees_f16be :: proc(radians: f16be) -> f16be { return radians * DEG_PER_RAD } -to_degrees_f32 :: proc(radians: f32) -> f32 { return radians * DEG_PER_RAD } -to_degrees_f32le :: proc(radians: f32le) -> f32le { return radians * DEG_PER_RAD } -to_degrees_f32be :: proc(radians: f32be) -> f32be { return radians * DEG_PER_RAD } -to_degrees_f64 :: proc(radians: f64) -> f64 { return radians * DEG_PER_RAD } -to_degrees_f64le :: proc(radians: f64le) -> f64le { return radians * DEG_PER_RAD } -to_degrees_f64be :: proc(radians: f64be) -> f64be { return radians * DEG_PER_RAD } +to_radians_f16 :: proc "contextless" (degrees: f16) -> f16 { return degrees * RAD_PER_DEG } +to_radians_f16le :: proc "contextless" (degrees: f16le) -> f16le { return degrees * RAD_PER_DEG } +to_radians_f16be :: proc "contextless" (degrees: f16be) -> f16be { return degrees * RAD_PER_DEG } +to_radians_f32 :: proc "contextless" (degrees: f32) -> f32 { return degrees * RAD_PER_DEG } +to_radians_f32le :: proc "contextless" (degrees: f32le) -> f32le { return degrees * RAD_PER_DEG } +to_radians_f32be :: proc "contextless" (degrees: f32be) -> f32be { return degrees * RAD_PER_DEG } +to_radians_f64 :: proc "contextless" (degrees: f64) -> f64 { return degrees * RAD_PER_DEG } +to_radians_f64le :: proc "contextless" (degrees: f64le) -> f64le { return degrees * RAD_PER_DEG } +to_radians_f64be :: proc "contextless" (degrees: f64be) -> f64be { return degrees * RAD_PER_DEG } +to_degrees_f16 :: proc "contextless" (radians: f16) -> f16 { return radians * DEG_PER_RAD } +to_degrees_f16le :: proc "contextless" (radians: f16le) -> f16le { return radians * DEG_PER_RAD } +to_degrees_f16be :: proc "contextless" (radians: f16be) -> f16be { return radians * DEG_PER_RAD } +to_degrees_f32 :: proc "contextless" (radians: f32) -> f32 { return radians * DEG_PER_RAD } +to_degrees_f32le :: proc "contextless" (radians: f32le) -> f32le { return radians * DEG_PER_RAD } +to_degrees_f32be :: proc "contextless" (radians: f32be) -> f32be { return radians * DEG_PER_RAD } +to_degrees_f64 :: proc "contextless" (radians: f64) -> f64 { return radians * DEG_PER_RAD } +to_degrees_f64le :: proc "contextless" (radians: f64le) -> f64le { return radians * DEG_PER_RAD } +to_degrees_f64be :: proc "contextless" (radians: f64be) -> f64be { return radians * DEG_PER_RAD } to_radians :: proc{ to_radians_f16, to_radians_f16le, to_radians_f16be, to_radians_f32, to_radians_f32le, to_radians_f32be, @@ -409,8 +409,8 @@ to_degrees :: proc{ to_degrees_f64, to_degrees_f64le, to_degrees_f64be, } -trunc_f16 :: proc(x: f16) -> f16 { - trunc_internal :: proc(f: f16) -> f16 { +trunc_f16 :: proc "contextless" (x: f16) -> f16 { + trunc_internal :: proc "contextless" (f: f16) -> f16 { mask :: 0x1f shift :: 16 - 6 bias :: 0xf @@ -438,11 +438,11 @@ trunc_f16 :: proc(x: f16) -> f16 { } 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_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(trunc_f16(f16(x))) } +trunc_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(trunc_f16(f16(x))) } -trunc_f32 :: proc(x: f32) -> f32 { - trunc_internal :: proc(f: f32) -> f32 { +trunc_f32 :: proc "contextless" (x: f32) -> f32 { + trunc_internal :: proc "contextless" (f: f32) -> f32 { mask :: 0xff shift :: 32 - 9 bias :: 0x7f @@ -470,11 +470,11 @@ trunc_f32 :: proc(x: f32) -> f32 { } 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_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(trunc_f32(f32(x))) } +trunc_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(trunc_f32(f32(x))) } -trunc_f64 :: proc(x: f64) -> f64 { - trunc_internal :: proc(f: f64) -> f64 { +trunc_f64 :: proc "contextless" (x: f64) -> f64 { + trunc_internal :: proc "contextless" (f: f64) -> f64 { mask :: 0x7ff shift :: 64 - 12 bias :: 0x3ff @@ -502,40 +502,40 @@ trunc_f64 :: proc(x: f64) -> f64 { } 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))) } +trunc_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(trunc_f64(f64(x))) } +trunc_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(trunc_f64(f64(x))) } 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 { +round_f16 :: proc "contextless" (x: f16) -> f16 { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f16le :: proc(x: f16le) -> f16le { +round_f16le :: proc "contextless" (x: f16le) -> f16le { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f16be :: proc(x: f16be) -> f16be { +round_f16be :: proc "contextless" (x: f16be) -> f16be { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f32 :: proc(x: f32) -> f32 { +round_f32 :: proc "contextless" (x: f32) -> f32 { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f32le :: proc(x: f32le) -> f32le { +round_f32le :: proc "contextless" (x: f32le) -> f32le { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f32be :: proc(x: f32be) -> f32be { +round_f32be :: proc "contextless" (x: f32be) -> f32be { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f64 :: proc(x: f64) -> f64 { +round_f64 :: proc "contextless" (x: f64) -> f64 { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f64le :: proc(x: f64le) -> f64le { +round_f64le :: proc "contextless" (x: f64le) -> f64le { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } -round_f64be :: proc(x: f64be) -> f64be { +round_f64be :: proc "contextless" (x: f64be) -> f64be { return ceil(x - 0.5) if x < 0 else floor(x + 0.5) } round :: proc{ @@ -545,17 +545,17 @@ round :: proc{ } -ceil_f16 :: proc(x: f16) -> f16 { return -floor(-x) } -ceil_f16le :: proc(x: f16le) -> f16le { return -floor(-x) } -ceil_f16be :: proc(x: f16be) -> f16be { return -floor(-x) } +ceil_f16 :: proc "contextless" (x: f16) -> f16 { return -floor(-x) } +ceil_f16le :: proc "contextless" (x: f16le) -> f16le { return -floor(-x) } +ceil_f16be :: proc "contextless" (x: f16be) -> f16be { return -floor(-x) } -ceil_f32 :: proc(x: f32) -> f32 { return -floor(-x) } -ceil_f32le :: proc(x: f32le) -> f32le { return -floor(-x) } -ceil_f32be :: proc(x: f32be) -> f32be { return -floor(-x) } +ceil_f32 :: proc "contextless" (x: f32) -> f32 { return -floor(-x) } +ceil_f32le :: proc "contextless" (x: f32le) -> f32le { return -floor(-x) } +ceil_f32be :: proc "contextless" (x: f32be) -> f32be { return -floor(-x) } -ceil_f64 :: proc(x: f64) -> f64 { return -floor(-x) } -ceil_f64le :: proc(x: f64le) -> f64le { return -floor(-x) } -ceil_f64be :: proc(x: f64be) -> f64be { return -floor(-x) } +ceil_f64 :: proc "contextless" (x: f64) -> f64 { return -floor(-x) } +ceil_f64le :: proc "contextless" (x: f64le) -> f64le { return -floor(-x) } +ceil_f64be :: proc "contextless" (x: f64be) -> f64be { return -floor(-x) } ceil :: proc{ ceil_f16, ceil_f16le, ceil_f16be, @@ -563,7 +563,7 @@ ceil :: proc{ ceil_f64, ceil_f64le, ceil_f64be, } -floor_f16 :: proc(x: f16) -> f16 { +floor_f16 :: proc "contextless" (x: f16) -> f16 { if x == 0 || is_nan(x) || is_inf(x) { return x } @@ -577,9 +577,9 @@ floor_f16 :: proc(x: f16) -> f16 { 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 { +floor_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(floor_f16(f16(x))) } +floor_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(floor_f16(f16(x))) } +floor_f32 :: proc "contextless" (x: f32) -> f32 { if x == 0 || is_nan(x) || is_inf(x) { return x } @@ -593,9 +593,9 @@ floor_f32 :: proc(x: f32) -> f32 { 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 { +floor_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(floor_f32(f32(x))) } +floor_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(floor_f32(f32(x))) } +floor_f64 :: proc "contextless" (x: f64) -> f64 { if x == 0 || is_nan(x) || is_inf(x) { return x } @@ -609,8 +609,8 @@ floor_f64 :: proc(x: f64) -> f64 { 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))) } +floor_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(floor_f64(f64(x))) } +floor_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(floor_f64(f64(x))) } floor :: proc{ floor_f16, floor_f16le, floor_f16be, floor_f32, floor_f32le, floor_f32be, @@ -618,7 +618,7 @@ floor :: proc{ } -floor_div :: proc(x, y: $T) -> T +floor_div :: proc "contextless" (x, y: $T) -> T where intrinsics.type_is_integer(T) { a := x / y r := x % y @@ -628,7 +628,7 @@ floor_div :: proc(x, y: $T) -> T return a } -floor_mod :: proc(x, y: $T) -> T +floor_mod :: proc "contextless" (x, y: $T) -> T where intrinsics.type_is_integer(T) { r := x % y if (r > 0 && y < 0) || (r < 0 && y > 0) { @@ -637,7 +637,7 @@ floor_mod :: proc(x, y: $T) -> T return r } -modf_f16 :: proc(x: f16) -> (int: f16, frac: f16) { +modf_f16 :: proc "contextless" (x: f16) -> (int: f16, frac: f16) { shift :: 16 - 5 - 1 mask :: 0x1f bias :: 15 @@ -663,15 +663,15 @@ modf_f16 :: proc(x: f16) -> (int: f16, frac: f16) { frac = x - int return } -modf_f16le :: proc(x: f16le) -> (int: f16le, frac: f16le) { +modf_f16le :: proc "contextless" (x: f16le) -> (int: f16le, frac: f16le) { i, f := #force_inline modf_f16(f16(x)) return f16le(i), f16le(f) } -modf_f16be :: proc(x: f16be) -> (int: f16be, frac: f16be) { +modf_f16be :: proc "contextless" (x: f16be) -> (int: f16be, frac: f16be) { i, f := #force_inline modf_f16(f16(x)) return f16be(i), f16be(f) } -modf_f32 :: proc(x: f32) -> (int: f32, frac: f32) { +modf_f32 :: proc "contextless" (x: f32) -> (int: f32, frac: f32) { shift :: 32 - 8 - 1 mask :: 0xff bias :: 127 @@ -697,15 +697,15 @@ modf_f32 :: proc(x: f32) -> (int: f32, frac: f32) { frac = x - int return } -modf_f32le :: proc(x: f32le) -> (int: f32le, frac: f32le) { +modf_f32le :: proc "contextless" (x: f32le) -> (int: f32le, frac: f32le) { i, f := #force_inline modf_f32(f32(x)) return f32le(i), f32le(f) } -modf_f32be :: proc(x: f32be) -> (int: f32be, frac: f32be) { +modf_f32be :: proc "contextless" (x: f32be) -> (int: f32be, frac: f32be) { i, f := #force_inline modf_f32(f32(x)) return f32be(i), f32be(f) } -modf_f64 :: proc(x: f64) -> (int: f64, frac: f64) { +modf_f64 :: proc "contextless" (x: f64) -> (int: f64, frac: f64) { shift :: 64 - 11 - 1 mask :: 0x7ff bias :: 1023 @@ -731,11 +731,11 @@ modf_f64 :: proc(x: f64) -> (int: f64, frac: f64) { frac = x - int return } -modf_f64le :: proc(x: f64le) -> (int: f64le, frac: f64le) { +modf_f64le :: proc "contextless" (x: f64le) -> (int: f64le, frac: f64le) { i, f := #force_inline modf_f64(f64(x)) return f64le(i), f64le(f) } -modf_f64be :: proc(x: f64be) -> (int: f64be, frac: f64be) { +modf_f64be :: proc "contextless" (x: f64be) -> (int: f64be, frac: f64be) { i, f := #force_inline modf_f64(f64(x)) return f64be(i), f64be(f) } @@ -746,7 +746,7 @@ modf :: proc{ } split_decimal :: modf -mod_f16 :: proc(x, y: f16) -> (n: f16) { +mod_f16 :: proc "contextless" (x, y: f16) -> (n: f16) { z := abs(y) n = remainder(abs(x), z) if sign(n) < 0 { @@ -754,9 +754,9 @@ mod_f16 :: proc(x, y: f16) -> (n: f16) { } 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) { +mod_f16le :: proc "contextless" (x, y: f16le) -> (n: f16le) { return #force_inline f16le(mod_f16(f16(x), f16(y))) } +mod_f16be :: proc "contextless" (x, y: f16be) -> (n: f16be) { return #force_inline f16be(mod_f16(f16(x), f16(y))) } +mod_f32 :: proc "contextless" (x, y: f32) -> (n: f32) { z := abs(y) n = remainder(abs(x), z) if sign(n) < 0 { @@ -764,9 +764,9 @@ mod_f32 :: proc(x, y: f32) -> (n: f32) { } 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) { +mod_f32le :: proc "contextless" (x, y: f32le) -> (n: f32le) { return #force_inline f32le(mod_f32(f32(x), f32(y))) } +mod_f32be :: proc "contextless" (x, y: f32be) -> (n: f32be) { return #force_inline f32be(mod_f32(f32(x), f32(y))) } +mod_f64 :: proc "contextless" (x, y: f64) -> (n: f64) { z := abs(y) n = remainder(abs(x), z) if sign(n) < 0 { @@ -774,30 +774,30 @@ mod_f64 :: proc(x, y: f64) -> (n: f64) { } 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))) } +mod_f64le :: proc "contextless" (x, y: f64le) -> (n: f64le) { return #force_inline f64le(mod_f64(f64(x), f64(y))) } +mod_f64be :: proc "contextless" (x, y: f64be) -> (n: f64be) { return #force_inline f64be(mod_f64(f64(x), f64(y))) } 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 } -remainder_f16be :: proc(x, y: f16be) -> f16be { return x - round(x/y) * y } -remainder_f32 :: proc(x, y: f32 ) -> f32 { return x - round(x/y) * y } -remainder_f32le :: proc(x, y: f32le) -> f32le { return x - round(x/y) * y } -remainder_f32be :: proc(x, y: f32be) -> f32be { return x - round(x/y) * y } -remainder_f64 :: proc(x, y: f64 ) -> f64 { return x - round(x/y) * y } -remainder_f64le :: proc(x, y: f64le) -> f64le { return x - round(x/y) * y } -remainder_f64be :: proc(x, y: f64be) -> f64be { return x - round(x/y) * y } +remainder_f16 :: proc "contextless" (x, y: f16 ) -> f16 { return x - round(x/y) * y } +remainder_f16le :: proc "contextless" (x, y: f16le) -> f16le { return x - round(x/y) * y } +remainder_f16be :: proc "contextless" (x, y: f16be) -> f16be { return x - round(x/y) * y } +remainder_f32 :: proc "contextless" (x, y: f32 ) -> f32 { return x - round(x/y) * y } +remainder_f32le :: proc "contextless" (x, y: f32le) -> f32le { return x - round(x/y) * y } +remainder_f32be :: proc "contextless" (x, y: f32be) -> f32be { return x - round(x/y) * y } +remainder_f64 :: proc "contextless" (x, y: f64 ) -> f64 { return x - round(x/y) * y } +remainder_f64le :: proc "contextless" (x, y: f64le) -> f64le { return x - round(x/y) * y } +remainder_f64be :: proc "contextless" (x, y: f64be) -> f64be { return x - round(x/y) * y } 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 +gcd :: proc "contextless" (x, y: $T) -> T where intrinsics.type_is_ordered_numeric(T) { x, y := x, y for y != 0 { @@ -807,36 +807,36 @@ gcd :: proc(x, y: $T) -> T return abs(x) } -lcm :: proc(x, y: $T) -> T +lcm :: proc "contextless" (x, y: $T) -> T where intrinsics.type_is_ordered_numeric(T) { return x / gcd(x, y) * y } -frexp_f16 :: proc(x: f16) -> (significand: f16, exponent: int) { +frexp_f16 :: proc "contextless" (x: f16) -> (significand: f16, exponent: int) { f, e := frexp_f64(f64(x)) return f16(f), e } -frexp_f16le :: proc(x: f16le) -> (significand: f16le, exponent: int) { +frexp_f16le :: proc "contextless" (x: f16le) -> (significand: f16le, exponent: int) { f, e := frexp_f64(f64(x)) return f16le(f), e } -frexp_f16be :: proc(x: f16be) -> (significand: f16be, exponent: int) { +frexp_f16be :: proc "contextless" (x: f16be) -> (significand: f16be, exponent: int) { f, e := frexp_f64(f64(x)) return f16be(f), e } -frexp_f32 :: proc(x: f32) -> (significand: f32, exponent: int) { +frexp_f32 :: proc "contextless" (x: f32) -> (significand: f32, exponent: int) { f, e := frexp_f64(f64(x)) return f32(f), e } -frexp_f32le :: proc(x: f32le) -> (significand: f32le, exponent: int) { +frexp_f32le :: proc "contextless" (x: f32le) -> (significand: f32le, exponent: int) { f, e := frexp_f64(f64(x)) return f32le(f), e } -frexp_f32be :: proc(x: f32be) -> (significand: f32be, exponent: int) { +frexp_f32be :: proc "contextless" (x: f32be) -> (significand: f32be, exponent: int) { f, e := frexp_f64(f64(x)) return f32be(f), e } -frexp_f64 :: proc(x: f64) -> (significand: f64, exponent: int) { +frexp_f64 :: proc "contextless" (x: f64) -> (significand: f64, exponent: int) { switch { case x == 0: return 0, 0 @@ -856,11 +856,11 @@ frexp_f64 :: proc(x: f64) -> (significand: f64, exponent: int) { } return } -frexp_f64le :: proc(x: f64le) -> (significand: f64le, exponent: int) { +frexp_f64le :: proc "contextless" (x: f64le) -> (significand: f64le, exponent: int) { f, e := frexp_f64(f64(x)) return f64le(f), e } -frexp_f64be :: proc(x: f64be) -> (significand: f64be, exponent: int) { +frexp_f64be :: proc "contextless" (x: f64be) -> (significand: f64be, exponent: int) { f, e := frexp_f64(f64(x)) return f64be(f), e } @@ -873,7 +873,7 @@ frexp :: proc{ -binomial :: proc(n, k: int) -> int { +binomial :: proc "contextless" (n, k: int) -> int { switch { case k <= 0: return 1 case 2*k > n: return binomial(n, n-k) @@ -886,7 +886,7 @@ binomial :: proc(n, k: int) -> int { return b } -factorial :: proc(n: int) -> int { +factorial :: proc "contextless" (n: int) -> int { when size_of(int) == size_of(i64) { @static table := [21]int{ 1, @@ -928,13 +928,10 @@ factorial :: proc(n: int) -> int { 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] } -classify_f16 :: proc(x: f16) -> Float_Class { +classify_f16 :: proc "contextless" (x: f16) -> Float_Class { switch { case x == 0: i := transmute(i16)x @@ -958,9 +955,9 @@ classify_f16 :: proc(x: f16) -> Float_Class { } 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 { +classify_f16le :: proc "contextless" (x: f16le) -> Float_Class { return #force_inline classify_f16(f16(x)) } +classify_f16be :: proc "contextless" (x: f16be) -> Float_Class { return #force_inline classify_f16(f16(x)) } +classify_f32 :: proc "contextless" (x: f32) -> Float_Class { switch { case x == 0: i := transmute(i32)x @@ -984,9 +981,9 @@ classify_f32 :: proc(x: f32) -> Float_Class { } 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 { +classify_f32le :: proc "contextless" (x: f32le) -> Float_Class { return #force_inline classify_f32(f32(x)) } +classify_f32be :: proc "contextless" (x: f32be) -> Float_Class { return #force_inline classify_f32(f32(x)) } +classify_f64 :: proc "contextless" (x: f64) -> Float_Class { switch { case x == 0: i := transmute(i64)x @@ -1009,23 +1006,23 @@ classify_f64 :: proc(x: f64) -> Float_Class { } 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)) } +classify_f64le :: proc "contextless" (x: f64le) -> Float_Class { return #force_inline classify_f64(f64(x)) } +classify_f64be :: proc "contextless" (x: f64be) -> Float_Class { return #force_inline classify_f64(f64(x)) } 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 } -is_nan_f16be :: proc(x: f16be) -> bool { return classify(x) == .NaN } -is_nan_f32 :: proc(x: f32) -> bool { return classify(x) == .NaN } -is_nan_f32le :: proc(x: f32le) -> bool { return classify(x) == .NaN } -is_nan_f32be :: proc(x: f32be) -> bool { return classify(x) == .NaN } -is_nan_f64 :: proc(x: f64) -> bool { return classify(x) == .NaN } -is_nan_f64le :: proc(x: f64le) -> bool { return classify(x) == .NaN } -is_nan_f64be :: proc(x: f64be) -> bool { return classify(x) == .NaN } +is_nan_f16 :: proc "contextless" (x: f16) -> bool { return classify(x) == .NaN } +is_nan_f16le :: proc "contextless" (x: f16le) -> bool { return classify(x) == .NaN } +is_nan_f16be :: proc "contextless" (x: f16be) -> bool { return classify(x) == .NaN } +is_nan_f32 :: proc "contextless" (x: f32) -> bool { return classify(x) == .NaN } +is_nan_f32le :: proc "contextless" (x: f32le) -> bool { return classify(x) == .NaN } +is_nan_f32be :: proc "contextless" (x: f32be) -> bool { return classify(x) == .NaN } +is_nan_f64 :: proc "contextless" (x: f64) -> bool { return classify(x) == .NaN } +is_nan_f64le :: proc "contextless" (x: f64le) -> bool { return classify(x) == .NaN } +is_nan_f64be :: proc "contextless" (x: f64be) -> bool { return classify(x) == .NaN } is_nan :: proc{ is_nan_f16, is_nan_f16le, is_nan_f16be, is_nan_f32, is_nan_f32le, is_nan_f32be, @@ -1036,7 +1033,7 @@ is_nan :: proc{ // 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 { +is_inf_f16 :: proc "contextless" (x: f16, sign: int = 0) -> bool { class := classify(abs(x)) switch { case sign > 0: @@ -1046,14 +1043,14 @@ is_inf_f16 :: proc(x: f16, sign: int = 0) -> bool { } return class == .Inf || class == .Neg_Inf } -is_inf_f16le :: proc(x: f16le, sign: int = 0) -> bool { +is_inf_f16le :: proc "contextless" (x: f16le, sign: int = 0) -> bool { return #force_inline is_inf_f16(f16(x), sign) } -is_inf_f16be :: proc(x: f16be, sign: int = 0) -> bool { +is_inf_f16be :: proc "contextless" (x: f16be, sign: int = 0) -> bool { return #force_inline is_inf_f16(f16(x), sign) } -is_inf_f32 :: proc(x: f32, sign: int = 0) -> bool { +is_inf_f32 :: proc "contextless" (x: f32, sign: int = 0) -> bool { class := classify(abs(x)) switch { case sign > 0: @@ -1063,14 +1060,14 @@ is_inf_f32 :: proc(x: f32, sign: int = 0) -> bool { } return class == .Inf || class == .Neg_Inf } -is_inf_f32le :: proc(x: f32le, sign: int = 0) -> bool { +is_inf_f32le :: proc "contextless" (x: f32le, sign: int = 0) -> bool { return #force_inline is_inf_f32(f32(x), sign) } -is_inf_f32be :: proc(x: f32be, sign: int = 0) -> bool { +is_inf_f32be :: proc "contextless" (x: f32be, sign: int = 0) -> bool { return #force_inline is_inf_f32(f32(x), sign) } -is_inf_f64 :: proc(x: f64, sign: int = 0) -> bool { +is_inf_f64 :: proc "contextless" (x: f64, sign: int = 0) -> bool { class := classify(abs(x)) switch { case sign > 0: @@ -1080,10 +1077,10 @@ is_inf_f64 :: proc(x: f64, sign: int = 0) -> bool { } return class == .Inf || class == .Neg_Inf } -is_inf_f64le :: proc(x: f64le, sign: int = 0) -> bool { +is_inf_f64le :: proc "contextless" (x: f64le, sign: int = 0) -> bool { return #force_inline is_inf_f64(f64(x), sign) } -is_inf_f64be :: proc(x: f64be, sign: int = 0) -> bool { +is_inf_f64be :: proc "contextless" (x: f64be, sign: int = 0) -> bool { return #force_inline is_inf_f64(f64(x), sign) } is_inf :: proc{ @@ -1092,25 +1089,25 @@ is_inf :: proc{ is_inf_f64, is_inf_f64le, is_inf_f64be, } -inf_f16 :: proc(sign: int) -> f16 { +inf_f16 :: proc "contextless" (sign: int) -> f16 { return f16(inf_f64(sign)) } -inf_f16le :: proc(sign: int) -> f16le { +inf_f16le :: proc "contextless" (sign: int) -> f16le { return f16le(inf_f64(sign)) } -inf_f16be :: proc(sign: int) -> f16be { +inf_f16be :: proc "contextless" (sign: int) -> f16be { return f16be(inf_f64(sign)) } -inf_f32 :: proc(sign: int) -> f32 { +inf_f32 :: proc "contextless" (sign: int) -> f32 { return f32(inf_f64(sign)) } -inf_f32le :: proc(sign: int) -> f32le { +inf_f32le :: proc "contextless" (sign: int) -> f32le { return f32le(inf_f64(sign)) } -inf_f32be :: proc(sign: int) -> f32be { +inf_f32be :: proc "contextless" (sign: int) -> f32be { return f32be(inf_f64(sign)) } -inf_f64 :: proc(sign: int) -> f64 { +inf_f64 :: proc "contextless" (sign: int) -> f64 { v: u64 if sign >= 0 { v = 0x7ff00000_00000000 @@ -1119,47 +1116,47 @@ inf_f64 :: proc(sign: int) -> f64 { } return transmute(f64)v } -inf_f64le :: proc(sign: int) -> f64le { +inf_f64le :: proc "contextless" (sign: int) -> f64le { return f64le(inf_f64(sign)) } -inf_f64be :: proc(sign: int) -> f64be { +inf_f64be :: proc "contextless" (sign: int) -> f64be { return f64be(inf_f64(sign)) } -nan_f16 :: proc() -> f16 { +nan_f16 :: proc "contextless" () -> f16 { return f16(nan_f64()) } -nan_f16le :: proc() -> f16le { +nan_f16le :: proc "contextless" () -> f16le { return f16le(nan_f64()) } -nan_f16be :: proc() -> f16be { +nan_f16be :: proc "contextless" () -> f16be { return f16be(nan_f64()) } -nan_f32 :: proc() -> f32 { +nan_f32 :: proc "contextless" () -> f32 { return f32(nan_f64()) } -nan_f32le :: proc() -> f32le { +nan_f32le :: proc "contextless" () -> f32le { return f32le(nan_f64()) } -nan_f32be :: proc() -> f32be { +nan_f32be :: proc "contextless" () -> f32be { return f32be(nan_f64()) } -nan_f64 :: proc() -> f64 { +nan_f64 :: proc "contextless" () -> f64 { v: u64 = 0x7ff80000_00000001 return transmute(f64)v } -nan_f64le :: proc() -> f64le { +nan_f64le :: proc "contextless" () -> f64le { return f64le(nan_f64()) } -nan_f64be :: proc() -> f64be { +nan_f64be :: proc "contextless" () -> f64be { return f64be(nan_f64()) } -is_power_of_two :: proc(x: int) -> bool { +is_power_of_two :: proc "contextless" (x: int) -> bool { return x > 0 && (x & (x-1)) == 0 } -next_power_of_two :: proc(x: int) -> int { +next_power_of_two :: proc "contextless" (x: int) -> int { k := x -1 when size_of(int) == 8 { k = k | (k >> 32) @@ -1173,7 +1170,7 @@ next_power_of_two :: proc(x: int) -> int { return k } -sum :: proc(x: $T/[]$E) -> (res: E) +sum :: proc "contextless" (x: $T/[]$E) -> (res: E) where intrinsics.type_is_numeric(E) { for i in x { res += i @@ -1181,7 +1178,7 @@ sum :: proc(x: $T/[]$E) -> (res: E) return } -prod :: proc(x: $T/[]$E) -> (res: E) +prod :: proc "contextless" (x: $T/[]$E) -> (res: E) where intrinsics.type_is_numeric(E) { for i in x { res *= i @@ -1189,7 +1186,7 @@ prod :: proc(x: $T/[]$E) -> (res: E) return } -cumsum_inplace :: proc(x: $T/[]$E) -> T +cumsum_inplace :: proc "contextless" (x: $T/[]$E) -> T where intrinsics.type_is_numeric(E) { for i in 1.. T } -cumsum :: proc(dst, src: $T/[]$E) -> T +cumsum :: proc "contextless" (dst, src: $T/[]$E) -> T where intrinsics.type_is_numeric(E) { N := min(len(dst), len(src)) if N > 0 { @@ -1210,32 +1207,32 @@ cumsum :: proc(dst, src: $T/[]$E) -> T } -atan2_f16 :: proc(y, x: f16) -> f16 { +atan2_f16 :: proc "contextless" (y, x: f16) -> f16 { // TODO(bill): Better atan2_f16 return f16(atan2_f64(f64(y), f64(x))) } -atan2_f16le :: proc(y, x: f16le) -> f16le { +atan2_f16le :: proc "contextless" (y, x: f16le) -> f16le { // TODO(bill): Better atan2_f16 return f16le(atan2_f64(f64(y), f64(x))) } -atan2_f16be :: proc(y, x: f16be) -> f16be { +atan2_f16be :: proc "contextless" (y, x: f16be) -> f16be { // TODO(bill): Better atan2_f16 return f16be(atan2_f64(f64(y), f64(x))) } -atan2_f32 :: proc(y, x: f32) -> f32 { +atan2_f32 :: proc "contextless" (y, x: f32) -> f32 { // TODO(bill): Better atan2_f32 return f32(atan2_f64(f64(y), f64(x))) } -atan2_f32le :: proc(y, x: f32le) -> f32le { +atan2_f32le :: proc "contextless" (y, x: f32le) -> f32le { // TODO(bill): Better atan2_f32 return f32le(atan2_f64(f64(y), f64(x))) } -atan2_f32be :: proc(y, x: f32be) -> f32be { +atan2_f32be :: proc "contextless" (y, x: f32be) -> f32be { // TODO(bill): Better atan2_f32 return f32be(atan2_f64(f64(y), f64(x))) } -atan2_f64 :: proc(y, x: f64) -> f64 { +atan2_f64 :: proc "contextless" (y, x: f64) -> f64 { // TODO(bill): Faster atan2_f64 if possible // The original C code: @@ -1246,7 +1243,7 @@ atan2_f64 :: proc(y, x: f64) -> f64 { INF :: 0h7FF0_0000_0000_0000 PI :: 0h4009_21fb_5444_2d18 - atan :: proc(x: f64) -> f64 { + atan :: proc "contextless" (x: f64) -> f64 { if x == 0 { return x } @@ -1256,7 +1253,7 @@ atan2_f64 :: proc(y, x: f64) -> f64 { 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 { + s_atan :: proc "contextless" (x: f64) -> f64 { MORE_BITS :: 6.123233995736765886130e-17 // pi/2 = PIO2 + MORE_BITS TAN3PI08 :: 2.41421356237309504880 // tan(3*pi/8) if x <= 0.66 { @@ -1268,7 +1265,7 @@ atan2_f64 :: proc(y, x: f64) -> f64 { 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 { + x_atan :: proc "contextless" (x: f64) -> f64 { P0 :: -8.750608600031904122785e-01 P1 :: -1.615753718733365076637e+01 P2 :: -7.500855792314704667340e+01 @@ -1320,11 +1317,11 @@ atan2_f64 :: proc(y, x: f64) -> f64 { } return q } -atan2_f64le :: proc(y, x: f64le) -> f64le { +atan2_f64le :: proc "contextless" (y, x: f64le) -> f64le { // TODO(bill): Better atan2_f32 return f64le(atan2_f64(f64(y), f64(x))) } -atan2_f64be :: proc(y, x: f64be) -> f64be { +atan2_f64be :: proc "contextless" (y, x: f64be) -> f64be { // TODO(bill): Better atan2_f32 return f64be(atan2_f64(f64(y), f64(x))) } @@ -1335,31 +1332,43 @@ atan2 :: proc{ atan2_f64, atan2_f64le, atan2_f64be, } -atan :: proc(x: $T) -> T where intrinsics.type_is_float(T) { +atan :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { return atan2(x, 1) } -asin :: proc(x: $T) -> T where intrinsics.type_is_float(T) { +asin :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { return atan2(x, 1 + sqrt(1 - x*x)) } -acos :: proc(x: $T) -> T where intrinsics.type_is_float(T) { +acos :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { return 2 * atan2(sqrt(1 - x), sqrt(1 + x)) } -sinh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { +sinh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { return (exp(x) - exp(-x))*0.5 } -cosh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { +cosh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { return (exp(x) + exp(-x))*0.5 } -tanh :: proc(x: $T) -> T where intrinsics.type_is_float(T) { +tanh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { t := exp(2*x) return (t - 1) / (t + 1) } +asinh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { + return ln(x + sqrt(x*x + 1)) +} + +acosh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { + return ln(x + sqrt(x*x - 1)) +} + +atanh :: proc "contextless" (x: $T) -> T where intrinsics.type_is_float(T) { + return 0.5*ln((1+x)/(1-x)) +} + F16_DIG :: 3 F16_EPSILON :: 0.00097656 F16_GUARD :: 0 From 017fe10762eaf5c68f5536cea8144b8f5aa40f95 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:09:12 +0000 Subject: [PATCH 05/13] `core:math/linalg/glsl` - GLSL-like mathematics types and operations --- core/math/linalg/glsl/linalg_glsl.odin | 1152 +++++++++++++++++++ core/math/linalg/glsl/linalg_glsl_math.odin | 34 + 2 files changed, 1186 insertions(+) create mode 100644 core/math/linalg/glsl/linalg_glsl.odin create mode 100644 core/math/linalg/glsl/linalg_glsl_math.odin diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin new file mode 100644 index 000000000..759c313a1 --- /dev/null +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -0,0 +1,1152 @@ +package math_linalg_glsl + +import "core:builtin" + +foreign import math "webgl_math" + +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 +E :: 2.71828182845904523536 +τ :: TAU +π :: PI +e :: E + +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 + +LN2 :: 0.693147180559945309417232121458176568 +LN10 :: 2.30258509299404568401799145468436421 + +F32_EPSILON :: 1e-7 + +mat2 :: distinct matrix[2, 2]f32 +mat3 :: distinct matrix[3, 3]f32 +mat4 :: distinct matrix[4, 4]f32 +mat2x2 :: mat2 +mat3x3 :: mat3 +mat4x4 :: mat4 + +// Should this be renamed the other way around? +mat3x2 :: distinct matrix[2, 3]f32 +mat4x2 :: distinct matrix[2, 4]f32 +mat2x3 :: distinct matrix[3, 2]f32 +mat4x3 :: distinct matrix[3, 4]f32 +mat2x4 :: distinct matrix[4, 2]f32 +mat3x4 :: distinct matrix[4, 3]f32 + +vec2 :: distinct [2]f32 +vec3 :: distinct [3]f32 +vec4 :: distinct [4]f32 + +ivec2 :: distinct [2]i32 +ivec3 :: distinct [3]i32 +ivec4 :: distinct [4]i32 + +uvec2 :: distinct [2]u32 +uvec3 :: distinct [3]u32 +uvec4 :: distinct [4]u32 + +bvec2 :: distinct [2]bool +bvec3 :: distinct [3]bool +bvec4 :: distinct [4]bool + +quat :: distinct quaternion128 + +cos :: proc{ + cos_f32, + cos_vec2, + cos_vec3, + cos_vec4, +} +cos_vec2 :: proc "c" (x: vec2) -> vec2 { return {cos(x.x), cos(x.y)} } +cos_vec3 :: proc "c" (x: vec3) -> vec3 { return {cos(x.x), cos(x.y), cos(x.z)} } +cos_vec4 :: proc "c" (x: vec4) -> vec4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } + + +sin :: proc{ + sin_f32, + sin_vec2, + sin_vec3, + sin_vec4, +} +sin_vec2 :: proc "c" (x: vec2) -> vec2 { return {sin(x.x), sin(x.y)} } +sin_vec3 :: proc "c" (x: vec3) -> vec3 { return {sin(x.x), sin(x.y), sin(x.z)} } +sin_vec4 :: proc "c" (x: vec4) -> vec4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } + + +tan :: proc{ + tan_f32, + tan_vec2, + tan_vec3, + tan_vec4, +} +tan_vec2 :: proc "c" (x: vec2) -> vec2 { return {tan(x.x), tan(x.y)} } +tan_vec3 :: proc "c" (x: vec3) -> vec3 { return {tan(x.x), tan(x.y), tan(x.z)} } +tan_vec4 :: proc "c" (x: vec4) -> vec4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } + + +acos :: proc{ + acos_f32, + acos_vec2, + acos_vec3, + acos_vec4, +} +acos_vec2 :: proc "c" (x: vec2) -> vec2 { return {acos(x.x), acos(x.y)} } +acos_vec3 :: proc "c" (x: vec3) -> vec3 { return {acos(x.x), acos(x.y), acos(x.z)} } +acos_vec4 :: proc "c" (x: vec4) -> vec4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } + + +asin :: proc{ + asin_f32, + asin_vec2, + asin_vec3, + asin_vec4, +} +asin_vec2 :: proc "c" (x: vec2) -> vec2 { return {asin(x.x), asin(x.y)} } +asin_vec3 :: proc "c" (x: vec3) -> vec3 { return {asin(x.x), asin(x.y), asin(x.z)} } +asin_vec4 :: proc "c" (x: vec4) -> vec4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } + + +atan :: proc{ + atan_f32, + atan_vec2, + atan_vec3, + atan_vec4, + atan2_f32, + atan2_vec2, + atan2_vec3, + atan2_vec4, +} +atan_vec2 :: proc "c" (x: vec2) -> vec2 { return {atan(x.x), atan(x.y)} } +atan_vec3 :: proc "c" (x: vec3) -> vec3 { return {atan(x.x), atan(x.y), atan(x.z)} } +atan_vec4 :: proc "c" (x: vec4) -> vec4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } + + +atan2 :: proc{ + atan2_f32, + atan2_vec2, + atan2_vec3, + atan2_vec4, +} +atan2_vec2 :: proc "c" (y, x: vec2) -> vec2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } +atan2_vec3 :: proc "c" (y, x: vec3) -> vec3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } +atan2_vec4 :: proc "c" (y, x: vec4) -> vec4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } + + + +cosh :: proc{ + cosh_f32, + cosh_vec2, + cosh_vec3, + cosh_vec4, +} +cosh_vec2 :: proc "c" (x: vec2) -> vec2 { return {cosh(x.x), cosh(x.y)} } +cosh_vec3 :: proc "c" (x: vec3) -> vec3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } +cosh_vec4 :: proc "c" (x: vec4) -> vec4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } + + +sinh :: proc{ + sinh_f32, + sinh_vec2, + sinh_vec3, + sinh_vec4, +} +sinh_vec2 :: proc "c" (x: vec2) -> vec2 { return {sinh(x.x), sinh(x.y)} } +sinh_vec3 :: proc "c" (x: vec3) -> vec3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } +sinh_vec4 :: proc "c" (x: vec4) -> vec4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } + + +tanh :: proc{ + tanh_f32, + tanh_vec2, + tanh_vec3, + tanh_vec4, +} +tanh_vec2 :: proc "c" (x: vec2) -> vec2 { return {tanh(x.x), tanh(x.y)} } +tanh_vec3 :: proc "c" (x: vec3) -> vec3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } +tanh_vec4 :: proc "c" (x: vec4) -> vec4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } + + +acosh :: proc{ + acosh_f32, + acosh_vec2, + acosh_vec3, + acosh_vec4, +} +acosh_vec2 :: proc "c" (x: vec2) -> vec2 { return {acosh(x.x), acosh(x.y)} } +acosh_vec3 :: proc "c" (x: vec3) -> vec3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } +acosh_vec4 :: proc "c" (x: vec4) -> vec4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } + + +asinh :: proc{ + asinh_f32, + asinh_vec2, + asinh_vec3, + asinh_vec4, +} +asinh_vec2 :: proc "c" (x: vec2) -> vec2 { return {asinh(x.x), asinh(x.y)} } +asinh_vec3 :: proc "c" (x: vec3) -> vec3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } +asinh_vec4 :: proc "c" (x: vec4) -> vec4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } + + +atanh :: proc{ + atanh_f32, + atanh_vec2, + atanh_vec3, + atanh_vec4, +} +atanh_vec2 :: proc "c" (x: vec2) -> vec2 { return {atanh(x.x), atanh(x.y)} } +atanh_vec3 :: proc "c" (x: vec3) -> vec3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } +atanh_vec4 :: proc "c" (x: vec4) -> vec4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } + + +sqrt :: proc{ + sqrt_f32, + sqrt_vec2, + sqrt_vec3, + sqrt_vec4, +} +sqrt_vec2 :: proc "c" (x: vec2) -> vec2 { return {sqrt(x.x), sqrt(x.y)} } +sqrt_vec3 :: proc "c" (x: vec3) -> vec3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } +sqrt_vec4 :: proc "c" (x: vec4) -> vec4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } + + +rsqrt :: inversesqrt +inversesqrt :: proc{ + inversesqrt_f32, + inversesqrt_vec2, + inversesqrt_vec3, + inversesqrt_vec4, +} +inversesqrt_vec2 :: proc "c" (x: vec2) -> vec2 { return {inversesqrt(x.x), inversesqrt(x.y)} } +inversesqrt_vec3 :: proc "c" (x: vec3) -> vec3 { return {inversesqrt(x.x), inversesqrt(x.y), inversesqrt(x.z)} } +inversesqrt_vec4 :: proc "c" (x: vec4) -> vec4 { return {inversesqrt(x.x), inversesqrt(x.y), inversesqrt(x.z), inversesqrt(x.w)} } + + + +pow :: proc{ + pow_f32, + pow_vec2, + pow_vec3, + pow_vec4, +} +pow_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {pow(x.x, y.x), pow(x.y, y.y)} } +pow_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } +pow_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } + + +exp :: proc{ + exp_f32, + exp_vec2, + exp_vec3, + exp_vec4, +} +exp_vec2 :: proc "c" (x: vec2) -> vec2 { return {exp(x.x), exp(x.y)} } +exp_vec3 :: proc "c" (x: vec3) -> vec3 { return {exp(x.x), exp(x.y), exp(x.z)} } +exp_vec4 :: proc "c" (x: vec4) -> vec4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } + + +log :: proc{ + log_f32, + log_vec2, + log_vec3, + log_vec4, +} +log_vec2 :: proc "c" (x: vec2) -> vec2 { return {log(x.x), log(x.y)} } +log_vec3 :: proc "c" (x: vec3) -> vec3 { return {log(x.x), log(x.y), log(x.z)} } +log_vec4 :: proc "c" (x: vec4) -> vec4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } + + +exp2 :: proc{ + exp2_f32, + exp2_vec2, + exp2_vec3, + exp2_vec4, +} +exp2_vec2 :: proc "c" (x: vec2) -> vec2 { return {exp2(x.x), exp2(x.y)} } +exp2_vec3 :: proc "c" (x: vec3) -> vec3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } +exp2_vec4 :: proc "c" (x: vec4) -> vec4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } + + +sign :: proc{ + sign_i32, + sign_u32, + sign_f32, + sign_vec2, + sign_vec3, + sign_vec4, + sign_ivec2, + sign_ivec3, + sign_ivec4, + sign_uvec2, + sign_uvec3, + sign_uvec4, +} +sign_i32 :: proc "c" (x: i32) -> i32 { return -1 if x < 0 else +1 if x > 0 else 0 } +sign_u32 :: proc "c" (x: u32) -> u32 { return +1 if x > 0 else 0 } +sign_vec2 :: proc "c" (x: vec2) -> vec2 { return {sign(x.x), sign(x.y)} } +sign_vec3 :: proc "c" (x: vec3) -> vec3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_vec4 :: proc "c" (x: vec4) -> vec4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } +sign_ivec2 :: proc "c" (x: ivec2) -> ivec2 { return {sign(x.x), sign(x.y)} } +sign_ivec3 :: proc "c" (x: ivec3) -> ivec3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_ivec4 :: proc "c" (x: ivec4) -> ivec4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } +sign_uvec2 :: proc "c" (x: uvec2) -> uvec2 { return {sign(x.x), sign(x.y)} } +sign_uvec3 :: proc "c" (x: uvec3) -> uvec3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_uvec4 :: proc "c" (x: uvec4) -> uvec4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } + +floor :: proc{ + floor_f32, + floor_vec2, + floor_vec3, + floor_vec4, +} +floor_vec2 :: proc "c" (x: vec2) -> vec2 { return {floor(x.x), floor(x.y)} } +floor_vec3 :: proc "c" (x: vec3) -> vec3 { return {floor(x.x), floor(x.y), floor(x.z)} } +floor_vec4 :: proc "c" (x: vec4) -> vec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } + + +ceil :: proc{ + ceil_f32, + ceil_vec2, + ceil_vec3, + ceil_vec4, +} +ceil_vec2 :: proc "c" (x: vec2) -> vec2 { return {ceil(x.x), ceil(x.y)} } +ceil_vec3 :: proc "c" (x: vec3) -> vec3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } +ceil_vec4 :: proc "c" (x: vec4) -> vec4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } + + +mod :: proc{ + mod_f32, + mod_vec2, + mod_vec3, + mod_vec4, +} +mod_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {mod(x.x, y.x), mod(x.y, y.y)} } +mod_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {mod(x.x, y.x), mod(x.y, y.y), mod(x.z, y.z)} } +mod_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {mod(x.x, y.x), mod(x.y, y.y), mod(x.z, y.z), mod(x.w, y.w)} } + + +fract :: proc{ + fract_f32, + fract_vec2, + fract_vec3, + fract_vec4, +} +fract_vec2 :: proc "c" (x: vec2) -> vec2 { return {fract(x.x), fract(x.y)} } +fract_vec3 :: proc "c" (x: vec3) -> vec3 { return {fract(x.x), fract(x.y), fract(x.z)} } +fract_vec4 :: proc "c" (x: vec4) -> vec4 { return {fract(x.x), fract(x.y), fract(x.z), fract(x.w)} } + + + +radians :: proc{ + radians_f32, + radians_vec2, + radians_vec3, + radians_vec4, +} +radians_f32 :: proc "c" (degrees: f32) -> f32 { return degrees * TAU / 360.0 } +radians_vec2 :: proc "c" (degrees: vec2) -> vec2 { return degrees * TAU / 360.0 } +radians_vec3 :: proc "c" (degrees: vec3) -> vec3 { return degrees * TAU / 360.0 } +radians_vec4 :: proc "c" (degrees: vec4) -> vec4 { return degrees * TAU / 360.0 } + + +degrees :: proc{ + degrees_f32, + degrees_vec2, + degrees_vec3, + degrees_vec4, +} +degrees_f32 :: proc "c" (radians: f32) -> f32 { return radians * 360.0 / TAU } +degrees_vec2 :: proc "c" (radians: vec2) -> vec2 { return radians * 360.0 / TAU } +degrees_vec3 :: proc "c" (radians: vec3) -> vec3 { return radians * 360.0 / TAU } +degrees_vec4 :: proc "c" (radians: vec4) -> vec4 { return radians * 360.0 / TAU } + + +min :: proc{ + min_i32, + min_u32, + min_f32, + min_vec2, + min_vec3, + min_vec4, + min_ivec2, + min_ivec3, + min_ivec4, + min_uvec2, + min_uvec3, + min_uvec4, +} +min_i32 :: proc "c" (x, y: i32) -> i32 { return builtin.min(x, y) } +min_u32 :: proc "c" (x, y: u32) -> u32 { return builtin.min(x, y) } +min_f32 :: proc "c" (x, y: f32) -> f32 { return builtin.min(x, y) } +min_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } +min_ivec2 :: proc "c" (x, y: ivec2) -> ivec2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_ivec3 :: proc "c" (x, y: ivec3) -> ivec3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_ivec4 :: proc "c" (x, y: ivec4) -> ivec4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } +min_uvec2 :: proc "c" (x, y: uvec2) -> uvec2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_uvec3 :: proc "c" (x, y: uvec3) -> uvec3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_uvec4 :: proc "c" (x, y: uvec4) -> uvec4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } + + +max :: proc{ + max_i32, + max_u32, + max_f32, + max_vec2, + max_vec3, + max_vec4, + max_ivec2, + max_ivec3, + max_ivec4, + max_uvec2, + max_uvec3, + max_uvec4, +} +max_i32 :: proc "c" (x, y: i32) -> i32 { return builtin.max(x, y) } +max_u32 :: proc "c" (x, y: u32) -> u32 { return builtin.max(x, y) } +max_f32 :: proc "c" (x, y: f32) -> f32 { return builtin.max(x, y) } +max_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } +max_ivec2 :: proc "c" (x, y: ivec2) -> ivec2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_ivec3 :: proc "c" (x, y: ivec3) -> ivec3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_ivec4 :: proc "c" (x, y: ivec4) -> ivec4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } +max_uvec2 :: proc "c" (x, y: uvec2) -> uvec2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_uvec3 :: proc "c" (x, y: uvec3) -> uvec3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_uvec4 :: proc "c" (x, y: uvec4) -> uvec4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } + + + +clamp :: proc{ + clamp_i32, + clamp_u32, + clamp_f32, + clamp_vec2, + clamp_vec3, + clamp_vec4, + clamp_ivec2, + clamp_ivec3, + clamp_ivec4, + clamp_uvec2, + clamp_uvec3, + clamp_uvec4, +} +clamp_i32 :: proc "c" (x, y, z: i32) -> i32 { return builtin.clamp(x, y, z) } +clamp_u32 :: proc "c" (x, y, z: u32) -> u32 { return builtin.clamp(x, y, z) } +clamp_f32 :: proc "c" (x, y, z: f32) -> f32 { return builtin.clamp(x, y, z) } +clamp_vec2 :: proc "c" (x, y, z: vec2) -> vec2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_vec3 :: proc "c" (x, y, z: vec3) -> vec3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_vec4 :: proc "c" (x, y, z: vec4) -> vec4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } +clamp_ivec2 :: proc "c" (x, y, z: ivec2) -> ivec2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_ivec3 :: proc "c" (x, y, z: ivec3) -> ivec3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_ivec4 :: proc "c" (x, y, z: ivec4) -> ivec4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } +clamp_uvec2 :: proc "c" (x, y, z: uvec2) -> uvec2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_uvec3 :: proc "c" (x, y, z: uvec3) -> uvec3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_uvec4 :: proc "c" (x, y, z: uvec4) -> uvec4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } + +saturate :: proc{ + saturate_i32, + saturate_u32, + saturate_f32, + saturate_vec2, + saturate_vec3, + saturate_vec4, + saturate_ivec2, + saturate_ivec3, + saturate_ivec4, + saturate_uvec2, + saturate_uvec3, + saturate_uvec4, +} +saturate_i32 :: proc "c" (x, y, z: i32) -> i32 { return builtin.clamp(x, 0, 1) } +saturate_u32 :: proc "c" (x, y, z: u32) -> u32 { return builtin.clamp(x, 0, 1) } +saturate_f32 :: proc "c" (x, y, z: f32) -> f32 { return builtin.clamp(x, 0, 1) } +saturate_vec2 :: proc "c" (x, y, z: vec2) -> vec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} } +saturate_vec3 :: proc "c" (x, y, z: vec3) -> vec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} } +saturate_vec4 :: proc "c" (x, y, z: vec4) -> vec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} } +saturate_ivec2 :: proc "c" (x, y, z: ivec2) -> ivec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} } +saturate_ivec3 :: proc "c" (x, y, z: ivec3) -> ivec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} } +saturate_ivec4 :: proc "c" (x, y, z: ivec4) -> ivec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} } +saturate_uvec2 :: proc "c" (x, y, z: uvec2) -> uvec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} } +saturate_uvec3 :: proc "c" (x, y, z: uvec3) -> uvec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} } +saturate_uvec4 :: proc "c" (x, y, z: uvec4) -> uvec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} } + + +mix :: proc{ + mix_f32, + mix_vec2, + mix_vec3, + mix_vec4, +} +mix_f32 :: proc "c" (x, y, t: f32) -> f32 { return x*(1-t) + y*t } +mix_vec2 :: proc "c" (x, y, t: vec2) -> vec2 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, t.y)} } +mix_vec3 :: proc "c" (x, y, t: vec3) -> vec3 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, t.y), mix(x.z, y.z, t.z)} } +mix_vec4 :: proc "c" (x, y, t: vec4) -> vec4 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, y.y), mix(x.z, y.z, t.z), mix(x.w, y.w, t.w)} } + +lerp :: proc{ + lerp_f32, + lerp_vec2, + lerp_vec3, + lerp_vec4, +} +lerp_f32 :: proc "c" (x, y, t: f32) -> f32 { return x*(1-t) + y*t } +lerp_vec2 :: proc "c" (x, y, t: vec2) -> vec2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } +lerp_vec3 :: proc "c" (x, y, t: vec3) -> vec3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } +lerp_vec4 :: proc "c" (x, y, t: vec4) -> vec4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } + + +step :: proc{ + step_f32, + step_vec2, + step_vec3, + step_vec4, +} +step_f32 :: proc "c" (edge, x: f32) -> f32 { return 0 if x < edge else 1 } +step_vec2 :: proc "c" (edge, x: vec2) -> vec2 { return {step(edge.x, x.x), step(edge.y, x.y)} } +step_vec3 :: proc "c" (edge, x: vec3) -> vec3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } +step_vec4 :: proc "c" (edge, x: vec4) -> vec4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } + + +abs :: proc{ + abs_i32, + abs_u32, + abs_f32, + abs_vec2, + abs_vec3, + abs_vec4, + abs_ivec2, + abs_ivec3, + abs_ivec4, + abs_uvec2, + abs_uvec3, + abs_uvec4, +} +abs_i32 :: proc "c" (x: i32) -> i32 { return builtin.abs(x) } +abs_u32 :: proc "c" (x: u32) -> u32 { return x } +abs_f32 :: proc "c" (x: f32) -> f32 { return builtin.abs(x) } +abs_vec2 :: proc "c" (x: vec2) -> vec2 { return {abs(x.x), abs(x.y)} } +abs_vec3 :: proc "c" (x: vec3) -> vec3 { return {abs(x.x), abs(x.y), abs(x.z)} } +abs_vec4 :: proc "c" (x: vec4) -> vec4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } +abs_ivec2 :: proc "c" (x: ivec2) -> ivec2 { return {abs(x.x), abs(x.y)} } +abs_ivec3 :: proc "c" (x: ivec3) -> ivec3 { return {abs(x.x), abs(x.y), abs(x.z)} } +abs_ivec4 :: proc "c" (x: ivec4) -> ivec4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } +abs_uvec2 :: proc "c" (x: uvec2) -> uvec2 { return x } +abs_uvec3 :: proc "c" (x: uvec3) -> uvec3 { return x } +abs_uvec4 :: proc "c" (x: uvec4) -> uvec4 { return x } + +dot :: proc{ + dot_i32, + dot_u32, + dot_f32, + dot_vec2, + dot_vec3, + dot_vec4, + dot_ivec2, + dot_ivec3, + dot_ivec4, + dot_uvec2, + dot_uvec3, + dot_uvec4, + dot_quat, +} +dot_i32 :: proc "c" (a, b: i32) -> i32 { return a*b } +dot_u32 :: proc "c" (a, b: u32) -> u32 { return a*b } +dot_f32 :: proc "c" (a, b: f32) -> f32 { return a*b } +dot_vec2 :: proc "c" (a, b: vec2) -> f32 { return a.x*b.x + a.y*b.y } +dot_vec3 :: proc "c" (a, b: vec3) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_vec4 :: proc "c" (a, b: vec4) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_ivec2 :: proc "c" (a, b: ivec2) -> i32 { return a.x*b.x + a.y*b.y } +dot_ivec3 :: proc "c" (a, b: ivec3) -> i32 { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_ivec4 :: proc "c" (a, b: ivec4) -> i32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_uvec2 :: proc "c" (a, b: uvec2) -> u32 { return a.x*b.x + a.y*b.y } +dot_uvec3 :: proc "c" (a, b: uvec3) -> u32 { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_uvec4 :: proc "c" (a, b: uvec4) -> u32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_quat :: proc "c" (a, b: quat) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } + +length :: proc{ + length_f32, + length_vec2, + length_vec3, + length_vec4, + length_quat, +} +length_f32 :: proc "c" (x: f32) -> f32 { return builtin.abs(x) } +length_vec2 :: proc "c" (x: vec2) -> f32 { return sqrt(x.x*x.x + x.y*x.y) } +length_vec3 :: proc "c" (x: vec3) -> f32 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } +length_vec4 :: proc "c" (x: vec4) -> f32 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } +length_quat :: proc "c" (x: quat) -> f32 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } + + +distance :: proc{ + distance_f32, + distance_vec2, + distance_vec3, + distance_vec4, +} +distance_f32 :: proc "c" (x, y: f32) -> f32 { return length(y-x) } +distance_vec2 :: proc "c" (x, y: vec2) -> f32 { return length(y-x) } +distance_vec3 :: proc "c" (x, y: vec3) -> f32 { return length(y-x) } +distance_vec4 :: proc "c" (x, y: vec4) -> f32 { return length(y-x) } + + +cross :: proc{ + cross_vec3, + cross_ivec3, +} + +cross_vec3 :: proc "c" (a, b: vec3) -> (c: vec3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} +cross_ivec3 :: proc "c" (a, b: ivec3) -> (c: ivec3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} + +normalize :: proc{ + normalize_f32, + normalize_vec2, + normalize_vec3, + normalize_vec4, + normalize_quat, +} +normalize_f32 :: proc "c" (x: f32) -> f32 { return 1.0 } +normalize_vec2 :: proc "c" (x: vec2) -> vec2 { return x / length(x) } +normalize_vec3 :: proc "c" (x: vec3) -> vec3 { return x / length(x) } +normalize_vec4 :: proc "c" (x: vec4) -> vec4 { return x / length(x) } +normalize_quat :: proc "c" (x: quat) -> quat { return x / quat(length(x)) } + + +faceForward :: proc{ + faceForward_f32, + faceForward_vec2, + faceForward_vec3, + faceForward_vec4, +} +faceForward_f32 :: proc "c" (N, I, Nref: f32) -> f32 { return N if dot(I, Nref) < 0 else -N } +faceForward_vec2 :: proc "c" (N, I, Nref: vec2) -> vec2 { return N if dot(I, Nref) < 0 else -N } +faceForward_vec3 :: proc "c" (N, I, Nref: vec3) -> vec3 { return N if dot(I, Nref) < 0 else -N } +faceForward_vec4 :: proc "c" (N, I, Nref: vec4) -> vec4 { return N if dot(I, Nref) < 0 else -N } + + +reflect :: proc{ + reflect_f32, + reflect_vec2, + reflect_vec3, + reflect_vec4, +} +reflect_f32 :: proc "c" (I, N: f32) -> f32 { return I - 2*N*dot(N, I) } +reflect_vec2 :: proc "c" (I, N: vec2) -> vec2 { return I - 2*N*dot(N, I) } +reflect_vec3 :: proc "c" (I, N: vec3) -> vec3 { return I - 2*N*dot(N, I) } +reflect_vec4 :: proc "c" (I, N: vec4) -> vec4 { return I - 2*N*dot(N, I) } + + + +refract :: proc{ + refract_f32, + refract_vec2, + refract_vec3, + refract_vec4, +} +refract_f32 :: proc "c" (i, n, eta: f32) -> f32 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * f32(i32(cost2 > 0)) +} +refract_vec2 :: proc "c" (i, n, eta: vec2) -> vec2 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * vec2{f32(i32(cost2.x > 0)), f32(i32(cost2.y > 0))} +} +refract_vec3 :: proc "c" (i, n, eta: vec3) -> vec3 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * vec3{f32(i32(cost2.x > 0)), f32(i32(cost2.y > 0)), f32(i32(cost2.z > 0))} +} +refract_vec4 :: proc "c" (i, n, eta: vec4) -> vec4 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * vec4{f32(i32(cost2.x > 0)), f32(i32(cost2.y > 0)), f32(i32(cost2.z > 0)), f32(i32(cost2.w > 0))} +} + +scalarTripleProduct :: proc "c" (a, b, c: vec3) -> f32 { return dot(a, cross(b, c)) } +vectorTripleProduct :: proc "c" (a, b, c: vec3) -> vec3 { return cross(a, cross(b, c)) } + + +// Vector Relational Procedures + +lessThan :: proc{ + lessThan_f32, + lessThan_i32, + lessThan_u32, + lessThan_vec2, + lessThan_ivec2, + lessThan_uvec2, + lessThan_vec3, + lessThan_ivec3, + lessThan_uvec3, + lessThan_vec4, + lessThan_ivec4, + lessThan_uvec4, +} +lessThan_f32 :: proc "c" (a, b: f32) -> bool { return a < b } +lessThan_i32 :: proc "c" (a, b: i32) -> bool { return a < b } +lessThan_u32 :: proc "c" (a, b: u32) -> bool { return a < b } +lessThan_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } +lessThan_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } +lessThan_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } +lessThan_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } +lessThan_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } +lessThan_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } + + +lessThanEqual :: proc{ + lessThanEqual_f32, + lessThanEqual_i32, + lessThanEqual_u32, + lessThanEqual_vec2, + lessThanEqual_ivec2, + lessThanEqual_uvec2, + lessThanEqual_vec3, + lessThanEqual_ivec3, + lessThanEqual_uvec3, + lessThanEqual_vec4, + lessThanEqual_ivec4, + lessThanEqual_uvec4, +} +lessThanEqual_f32 :: proc "c" (a, b: f32) -> bool { return a <= b } +lessThanEqual_i32 :: proc "c" (a, b: i32) -> bool { return a <= b } +lessThanEqual_u32 :: proc "c" (a, b: u32) -> bool { return a <= b } +lessThanEqual_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } +lessThanEqual_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } +lessThanEqual_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } + + +greaterThan :: proc{ + greaterThan_f32, + greaterThan_i32, + greaterThan_u32, + greaterThan_vec2, + greaterThan_ivec2, + greaterThan_uvec2, + greaterThan_vec3, + greaterThan_ivec3, + greaterThan_uvec3, + greaterThan_vec4, + greaterThan_ivec4, + greaterThan_uvec4, +} +greaterThan_f32 :: proc "c" (a, b: f32) -> bool { return a > b } +greaterThan_i32 :: proc "c" (a, b: i32) -> bool { return a > b } +greaterThan_u32 :: proc "c" (a, b: u32) -> bool { return a > b } +greaterThan_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } +greaterThan_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } +greaterThan_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } +greaterThan_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } +greaterThan_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } +greaterThan_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } + + +greaterThanEqual :: proc{ + greaterThanEqual_f32, + greaterThanEqual_i32, + greaterThanEqual_u32, + greaterThanEqual_vec2, + greaterThanEqual_ivec2, + greaterThanEqual_uvec2, + greaterThanEqual_vec3, + greaterThanEqual_ivec3, + greaterThanEqual_uvec3, + greaterThanEqual_vec4, + greaterThanEqual_ivec4, + greaterThanEqual_uvec4, +} +greaterThanEqual_f32 :: proc "c" (a, b: f32) -> bool { return a >= b } +greaterThanEqual_i32 :: proc "c" (a, b: i32) -> bool { return a >= b } +greaterThanEqual_u32 :: proc "c" (a, b: u32) -> bool { return a >= b } +greaterThanEqual_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } +greaterThanEqual_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } +greaterThanEqual_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } + + +equal :: proc{ + equal_f32, + equal_i32, + equal_u32, + equal_vec2, + equal_ivec2, + equal_uvec2, + equal_vec3, + equal_ivec3, + equal_uvec3, + equal_vec4, + equal_ivec4, + equal_uvec4, +} +equal_f32 :: proc "c" (a, b: f32) -> bool { return a == b } +equal_i32 :: proc "c" (a, b: i32) -> bool { return a == b } +equal_u32 :: proc "c" (a, b: u32) -> bool { return a == b } +equal_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } +equal_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } +equal_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } +equal_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } +equal_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } +equal_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } + +notEqual :: proc{ + notEqual_f32, + notEqual_i32, + notEqual_u32, + notEqual_vec2, + notEqual_ivec2, + notEqual_uvec2, + notEqual_vec3, + notEqual_ivec3, + notEqual_uvec3, + notEqual_vec4, + notEqual_ivec4, + notEqual_uvec4, +} +notEqual_f32 :: proc "c" (a, b: f32) -> bool { return a != b } +notEqual_i32 :: proc "c" (a, b: i32) -> bool { return a != b } +notEqual_u32 :: proc "c" (a, b: u32) -> bool { return a != b } +notEqual_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } +notEqual_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } +notEqual_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } +notEqual_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } +notEqual_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } +notEqual_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } + + +any :: proc{ + any_bool, + any_bvec2, + any_bvec3, + any_bvec4, +} +any_bool :: proc "c" (v: bool) -> bool { return v } +any_bvec2 :: proc "c" (v: bvec2) -> bool { return v.x || v.y } +any_bvec3 :: proc "c" (v: bvec3) -> bool { return v.x || v.y || v.z } +any_bvec4 :: proc "c" (v: bvec4) -> bool { return v.x || v.y || v.z || v.w } + +all :: proc{ + all_bool, + all_bvec2, + all_bvec3, + all_bvec4, +} +all_bool :: proc "c" (v: bool) -> bool { return v } +all_bvec2 :: proc "c" (v: bvec2) -> bool { return v.x && v.y } +all_bvec3 :: proc "c" (v: bvec3) -> bool { return v.x && v.y && v.z } +all_bvec4 :: proc "c" (v: bvec4) -> bool { return v.x && v.y && v.z && v.w } + +not :: proc{ + not_bool, + not_bvec2, + not_bvec3, + not_bvec4, +} +not_bool :: proc "c" (v: bool) -> bool { return !v } +not_bvec2 :: proc "c" (v: bvec2) -> bvec2 { return {!v.x, !v.y} } +not_bvec3 :: proc "c" (v: bvec3) -> bvec3 { return {!v.x, !v.y, !v.z} } +not_bvec4 :: proc "c" (v: bvec4) -> bvec4 { return {!v.x, !v.y, !v.z, !v.w} } + + + +/// Matrix Utilities + +identity :: proc "c" ($M: typeid/matrix[$N, N]f32) -> M { return 1 } + +mat4Perspective :: proc "c" (fovy, aspect, near, far: f32) -> (m: mat4) { + tan_half_fovy := 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[3, 2] = -1 + m[2, 3] = -2*far*near / (far - near) + return +} +mat4PerspectiveInfinite :: proc "c" (fovy, aspect, near: f32) -> (m: mat4) { + tan_half_fovy := tan(0.5 * fovy) + m[0, 0] = 1 / (aspect*tan_half_fovy) + m[1, 1] = 1 / (tan_half_fovy) + m[2, 2] = -1 + m[3, 2] = -1 + m[2, 3] = -2*near + return +} +mat4Ortho3d :: proc "c" (left, right, bottom, top, near, far: f32) -> (m: mat4) { + m[0, 0] = +2 / (right - left) + m[1, 1] = +2 / (top - bottom) + m[2, 2] = -2 / (far - near) + m[0, 3] = -(right + left) / (right - left) + m[1, 3] = -(top + bottom) / (top - bottom) + m[2, 3] = -(far + near) / (far- near) + m[3, 3] = 1 + return m +} + + +mat4LookAt :: proc "c" (eye, centre, up: vec3) -> (m: mat4) { + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) + + fe := dot(f, eye) + + m[0] = {+s.x, +u.x, -f.x, 0} + m[1] = {+s.y, +u.y, -f.y, 0} + m[2] = {+s.z, +u.z, -f.z, 0} + m[3] = {-dot(s, eye), -dot(u, eye), +fe, 1} + return + // return mat4{ + // +s.x, +s.y, +s.z, -dot(s, eye), + // +u.x, +u.y, +u.z, -dot(u, eye), + // -f.x, -f.y, -f.z, +fe, + // 0, 0, 0, 1, + // } +} + +mat4Rotate :: proc "c" (v: vec3, radians: f32) -> (rot: mat4) { + c := cos(radians) + s := sin(radians) + + a := normalize(v) + t := a * (1-c) + + rot = 1 + + rot[0, 0] = c + t[0]*a[0] + rot[1, 0] = 0 + t[0]*a[1] + s*a[2] + rot[2, 0] = 0 + t[0]*a[2] - s*a[1] + rot[3, 0] = 0 + + rot[0, 1] = 0 + t[1]*a[0] - s*a[2] + rot[1, 1] = c + t[1]*a[1] + rot[2, 1] = 0 + t[1]*a[2] + s*a[0] + rot[3, 1] = 0 + + rot[0, 2] = 0 + t[2]*a[0] + s*a[1] + rot[1, 2] = 0 + t[2]*a[1] - s*a[0] + rot[2, 2] = c + t[2]*a[2] + rot[3, 2] = 0 + + return rot +} + +mat4Translate :: proc "c" (v: vec3) -> (m: mat4) { + m = 1 + m[3].xyz = v.xyz + return +} +mat4Scale :: proc "c" (v: vec3) -> (m: mat4) { + m[0, 0] = v[0] + m[1, 1] = v[1] + m[2, 2] = v[2] + m[3, 3] = 1 + return +} + +mat4Orientation :: proc "c" (normal, up: vec3) -> mat4 { + if normal == up { + return 1 + } + + rotation_axis := cross(up, normal) + angle := acos(dot(normal, up)) + + return mat4Rotate(rotation_axis, angle) +} + +mat4FromQuat :: proc "c" (q: quat) -> (m: mat4) { + 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[1, 0] = 2 * (qxy + qwz) + m[2, 0] = 2 * (qxz - qwy) + + m[0, 1] = 2 * (qxy - qwz) + m[1, 1] = 1 - 2 * (qxx + qzz) + m[2, 1] = 2 * (qyz + qwx) + + m[0, 2] = 2 * (qxz + qwy) + m[1, 2] = 2 * (qyz - qwx) + m[2, 2] = 1 - 2 * (qxx + qyy) + + m[3, 3] = 1 + + return +} + +quatAxisAngle :: proc "c" (axis: vec3, radians: f32) -> (q: quat) { + t := radians*0.5 + v := normalize(axis) * sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = cos(t) + return +} + +quatDot :: proc "c" (a, b: quat) -> f32 { + return dot(transmute(vec4)a, transmute(vec4)b) +} + +quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) { + 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 c/builtin.abs(c) +} + +quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) { + a, b := x, y + cos_angle := quatDot(a, b) + if cos_angle < 0 { + 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 + } + + angle := acos(cos_angle) + sin_angle := sin(angle) + factor_a := sin((1-t) * angle) / sin_angle + factor_b := 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 +} + +quatFromMat3 :: proc "c" (m: mat3) -> (q: quat) { + 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 + if four_x_squared_minus_1 > four_biggest_squared_minus_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 + } + if four_z_squared_minus_1 > four_biggest_squared_minus_1 { + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 + } + + biggest_val := sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val + + q = 1 + switch biggest_index { + case 0: + q.w = biggest_val + q.x = (m[2, 1] - m[1, 2]) * mult + q.y = (m[0, 2] - m[2, 0]) * mult + q.z = (m[1, 0] - m[0, 1]) * mult + case 1: + q.w = (m[2, 1] - m[1, 2]) * mult + q.x = biggest_val + q.y = (m[1, 0] + m[0, 1]) * mult + q.z = (m[0, 2] + m[2, 0]) * mult + case 2: + q.w = (m[0, 2] - m[2, 0]) * mult + q.x = (m[1, 0] + m[0, 1]) * mult + q.y = biggest_val + q.z = (m[2, 1] + m[1, 2]) * mult + case 3: + q.w = (m[1, 0] - m[0, 1]) * mult + q.x = (m[0, 2] + m[2, 0]) * mult + q.y = (m[2, 1] + m[1, 2]) * mult + q.z = biggest_val + } + return +} + +quatFromMat4 :: proc "c" (m: mat4) -> (q: quat) { + return quatFromMat3(mat3(m)) +} + +quatMulVec3 :: proc "c" (q: quat, v: vec3) -> vec3 { + xyz := vec3{q.x, q.y, q.z} + t := cross(xyz, v) + return v + q.w*t + cross(xyz, t) +} + +inverse_mat2 :: proc "c" (m: mat2) -> mat2 { return builtin.inverse(m) } +inverse_mat3 :: proc "c" (m: mat3) -> mat3 { return builtin.inverse(m) } +inverse_mat4 :: proc "c" (m: mat4) -> mat4 { return builtin.inverse(m) } +inverse_quat :: proc "c" (q: quat) -> quat { return 1/q } + +inverse :: proc{ + inverse_mat2, + inverse_mat3, + inverse_mat4, + inverse_quat, +} + +transpose :: builtin.transpose +inverse_transpose :: builtin.inverse_transpose +adjugate :: builtin.adjugate +hermitian_adjoint :: builtin.hermitian_adjoint +minor :: builtin.matrix_minor +determinant :: builtin.determinant +trace :: builtin.matrix_trace \ No newline at end of file diff --git a/core/math/linalg/glsl/linalg_glsl_math.odin b/core/math/linalg/glsl/linalg_glsl_math.odin new file mode 100644 index 000000000..b01557b17 --- /dev/null +++ b/core/math/linalg/glsl/linalg_glsl_math.odin @@ -0,0 +1,34 @@ +//+build !freestanding !wasm32 +package math_linalg_glsl + +import "core:math" + +cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos_f32(x) } +sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin_f32(x) } +tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan_f32(x) } +acos_f32 :: proc "c" (x: f32) -> f32 { return math.acos(x) } +asin_f32 :: proc "c" (x: f32) -> f32 { return math.asin(x) } +atan_f32 :: proc "c" (x: f32) -> f32 { return math.atan(x) } +atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2_f32(y, x) } +cosh_f32 :: proc "c" (x: f32) -> f32 { return math.cosh(x) } +sinh_f32 :: proc "c" (x: f32) -> f32 { return math.sinh(x) } +tanh_f32 :: proc "c" (x: f32) -> f32 { return math.tanh(x) } +acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) } +asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) } +atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) } +sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) } +inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/sqrt_f32(x) } +pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) } +exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) } +log_f32 :: proc "c" (x: f32) -> f32 { return math.ln_f32(x) } +exp2_f32 :: proc "c" (x: f32) -> f32 { return pow(2, x) } +sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) } +floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) } +ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) } +mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) } +fract_f32 :: proc "c" (x: f32) -> f32 { + if x >= 0 { + return x - math.trunc_f32(x) + } + return math.trunc_f32(-x) + x +} From e3cfdf698202b4dd95d5ebe3fe42fec45b28fca1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:11:04 +0000 Subject: [PATCH 06/13] Remove build tag --- core/math/linalg/glsl/linalg_glsl_math.odin | 1 - 1 file changed, 1 deletion(-) diff --git a/core/math/linalg/glsl/linalg_glsl_math.odin b/core/math/linalg/glsl/linalg_glsl_math.odin index b01557b17..c09e13919 100644 --- a/core/math/linalg/glsl/linalg_glsl_math.odin +++ b/core/math/linalg/glsl/linalg_glsl_math.odin @@ -1,4 +1,3 @@ -//+build !freestanding !wasm32 package math_linalg_glsl import "core:math" From 57d15ac6e7d8e11b31965749a262c084d5689a6e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:11:34 +0000 Subject: [PATCH 07/13] Remove unneeded suffixes --- core/math/linalg/glsl/linalg_glsl_math.odin | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/math/linalg/glsl/linalg_glsl_math.odin b/core/math/linalg/glsl/linalg_glsl_math.odin index c09e13919..5d06c02a1 100644 --- a/core/math/linalg/glsl/linalg_glsl_math.odin +++ b/core/math/linalg/glsl/linalg_glsl_math.odin @@ -2,13 +2,13 @@ package math_linalg_glsl import "core:math" -cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos_f32(x) } -sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin_f32(x) } -tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan_f32(x) } +cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos(x) } +sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin(x) } +tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan(x) } acos_f32 :: proc "c" (x: f32) -> f32 { return math.acos(x) } asin_f32 :: proc "c" (x: f32) -> f32 { return math.asin(x) } atan_f32 :: proc "c" (x: f32) -> f32 { return math.atan(x) } -atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2_f32(y, x) } +atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2(y, x) } cosh_f32 :: proc "c" (x: f32) -> f32 { return math.cosh(x) } sinh_f32 :: proc "c" (x: f32) -> f32 { return math.sinh(x) } tanh_f32 :: proc "c" (x: f32) -> f32 { return math.tanh(x) } @@ -16,10 +16,10 @@ acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) } asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) } atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) } sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) } -inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/sqrt_f32(x) } +inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/sqrt(x) } pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) } exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) } -log_f32 :: proc "c" (x: f32) -> f32 { return math.ln_f32(x) } +log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) } exp2_f32 :: proc "c" (x: f32) -> f32 { return pow(2, x) } sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) } floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) } @@ -27,7 +27,7 @@ ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) } mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) } fract_f32 :: proc "c" (x: f32) -> f32 { if x >= 0 { - return x - math.trunc_f32(x) + return x - math.trunc(x) } - return math.trunc_f32(-x) + x + return math.trunc(-x) + x } From a882118c56f18eb35b4827cf5365d76900e675ff Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:20:47 +0000 Subject: [PATCH 08/13] Add comments --- core/math/linalg/glsl/linalg_glsl.odin | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index 759c313a1..8bf8c1914 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -1,9 +1,8 @@ +// core:math/linalg/glsl implements a GLSL-like mathematics library plus numerous other utility procedures package math_linalg_glsl import "core:builtin" -foreign import math "webgl_math" - TAU :: 6.28318530717958647692528676655900576 PI :: 3.14159265358979323846264338327950288 E :: 2.71828182845904523536 From eb058791485307b338897c7a2963715c5f09e628 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:25:34 +0000 Subject: [PATCH 09/13] Add more comments --- core/math/linalg/glsl/linalg_glsl.odin | 28 +++++++++++++++----------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index 8bf8c1914..8b487c906 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -3,22 +3,23 @@ package math_linalg_glsl import "core:builtin" -TAU :: 6.28318530717958647692528676655900576 -PI :: 3.14159265358979323846264338327950288 -E :: 2.71828182845904523536 -τ :: TAU -π :: PI -e :: E +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 +E :: 2.71828182845904523536 +τ :: 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 F32_EPSILON :: 1e-7 +// Odin matrices are stored internally as Column-Major, which matches OpenGL/GLSL by default mat2 :: distinct matrix[2, 2]f32 mat3 :: distinct matrix[3, 3]f32 mat4 :: distinct matrix[4, 4]f32 @@ -26,7 +27,10 @@ mat2x2 :: mat2 mat3x3 :: mat3 mat4x4 :: mat4 -// Should this be renamed the other way around? +// IMPORTANT NOTE: These data types are "backwards" in normal mathematical terms +// but they match how GLSL and OpenGL defines them in name +// Odin: matrix[R, C]f32 +// GLSL: matCxR mat3x2 :: distinct matrix[2, 3]f32 mat4x2 :: distinct matrix[2, 4]f32 mat2x3 :: distinct matrix[3, 2]f32 From 3accf4048e997c89d095006dfdd282a9b1dff612 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:52:03 +0000 Subject: [PATCH 10/13] Add `f64` variants of all types and procedures --- core/math/linalg/glsl/linalg_glsl.odin | 698 +++++++++++++++++++- core/math/linalg/glsl/linalg_glsl_math.odin | 34 +- 2 files changed, 695 insertions(+), 37 deletions(-) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index 8b487c906..a77a91505 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -18,6 +18,7 @@ LN2 :: 0.693147180559945309417232121458176568 LN10 :: 2.30258509299404568401799145468436421 F32_EPSILON :: 1e-7 +F64_EPSILON :: 1e-15 // Odin matrices are stored internally as Column-Major, which matches OpenGL/GLSL by default mat2 :: distinct matrix[2, 2]f32 @@ -56,229 +57,382 @@ bvec4 :: distinct [4]bool quat :: distinct quaternion128 +// Double Precision (f64) Floating Point Types + +dmat2 :: distinct matrix[2, 2]f64 +dmat3 :: distinct matrix[3, 3]f64 +dmat4 :: distinct matrix[4, 4]f64 +dmat2x2 :: dmat2 +dmat3x3 :: dmat3 +dmat4x4 :: dmat4 + +dmat3x2 :: distinct matrix[2, 3]f64 +dmat4x2 :: distinct matrix[2, 4]f64 +dmat2x3 :: distinct matrix[3, 2]f64 +dmat4x3 :: distinct matrix[3, 4]f64 +dmat2x4 :: distinct matrix[4, 2]f64 +dmat3x4 :: distinct matrix[4, 3]f64 + +dvec2 :: distinct [2]f64 +dvec3 :: distinct [3]f64 +dvec4 :: distinct [4]f64 + +dquat :: distinct quaternion256 + cos :: proc{ cos_f32, + cos_f64, cos_vec2, cos_vec3, cos_vec4, + cos_dvec2, + cos_dvec3, + cos_dvec4, } cos_vec2 :: proc "c" (x: vec2) -> vec2 { return {cos(x.x), cos(x.y)} } cos_vec3 :: proc "c" (x: vec3) -> vec3 { return {cos(x.x), cos(x.y), cos(x.z)} } cos_vec4 :: proc "c" (x: vec4) -> vec4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } - +cos_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {cos(x.x), cos(x.y)} } +cos_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {cos(x.x), cos(x.y), cos(x.z)} } +cos_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } sin :: proc{ sin_f32, + sin_f64, sin_vec2, sin_vec3, sin_vec4, + sin_dvec2, + sin_dvec3, + sin_dvec4, } sin_vec2 :: proc "c" (x: vec2) -> vec2 { return {sin(x.x), sin(x.y)} } sin_vec3 :: proc "c" (x: vec3) -> vec3 { return {sin(x.x), sin(x.y), sin(x.z)} } sin_vec4 :: proc "c" (x: vec4) -> vec4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } - +sin_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {sin(x.x), sin(x.y)} } +sin_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {sin(x.x), sin(x.y), sin(x.z)} } +sin_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } tan :: proc{ tan_f32, + tan_f64, tan_vec2, tan_vec3, tan_vec4, + tan_dvec2, + tan_dvec3, + tan_dvec4, } tan_vec2 :: proc "c" (x: vec2) -> vec2 { return {tan(x.x), tan(x.y)} } tan_vec3 :: proc "c" (x: vec3) -> vec3 { return {tan(x.x), tan(x.y), tan(x.z)} } tan_vec4 :: proc "c" (x: vec4) -> vec4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } - +tan_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {tan(x.x), tan(x.y)} } +tan_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {tan(x.x), tan(x.y), tan(x.z)} } +tan_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } acos :: proc{ acos_f32, + acos_f64, acos_vec2, acos_vec3, acos_vec4, + acos_dvec2, + acos_dvec3, + acos_dvec4, } acos_vec2 :: proc "c" (x: vec2) -> vec2 { return {acos(x.x), acos(x.y)} } acos_vec3 :: proc "c" (x: vec3) -> vec3 { return {acos(x.x), acos(x.y), acos(x.z)} } acos_vec4 :: proc "c" (x: vec4) -> vec4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } - +acos_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {acos(x.x), acos(x.y)} } +acos_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {acos(x.x), acos(x.y), acos(x.z)} } +acos_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } asin :: proc{ asin_f32, + asin_f64, asin_vec2, asin_vec3, asin_vec4, + asin_dvec2, + asin_dvec3, + asin_dvec4, } asin_vec2 :: proc "c" (x: vec2) -> vec2 { return {asin(x.x), asin(x.y)} } asin_vec3 :: proc "c" (x: vec3) -> vec3 { return {asin(x.x), asin(x.y), asin(x.z)} } asin_vec4 :: proc "c" (x: vec4) -> vec4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } - +asin_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {asin(x.x), asin(x.y)} } +asin_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {asin(x.x), asin(x.y), asin(x.z)} } +asin_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } atan :: proc{ atan_f32, + atan_f64, atan_vec2, atan_vec3, atan_vec4, + atan_dvec2, + atan_dvec3, + atan_dvec4, atan2_f32, + atan2_f64, atan2_vec2, atan2_vec3, atan2_vec4, + atan2_dvec2, + atan2_dvec3, + atan2_dvec4, } atan_vec2 :: proc "c" (x: vec2) -> vec2 { return {atan(x.x), atan(x.y)} } atan_vec3 :: proc "c" (x: vec3) -> vec3 { return {atan(x.x), atan(x.y), atan(x.z)} } atan_vec4 :: proc "c" (x: vec4) -> vec4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } - +atan_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {atan(x.x), atan(x.y)} } +atan_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {atan(x.x), atan(x.y), atan(x.z)} } +atan_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } atan2 :: proc{ atan2_f32, + atan2_f64, atan2_vec2, atan2_vec3, atan2_vec4, + atan2_dvec2, + atan2_dvec3, + atan2_dvec4, } atan2_vec2 :: proc "c" (y, x: vec2) -> vec2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } atan2_vec3 :: proc "c" (y, x: vec3) -> vec3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } atan2_vec4 :: proc "c" (y, x: vec4) -> vec4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } +atan2_dvec2 :: proc "c" (y, x: dvec2) -> dvec2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } +atan2_dvec3 :: proc "c" (y, x: dvec3) -> dvec3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } +atan2_dvec4 :: proc "c" (y, x: dvec4) -> dvec4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } cosh :: proc{ cosh_f32, + cosh_f64, cosh_vec2, cosh_vec3, cosh_vec4, + cosh_dvec2, + cosh_dvec3, + cosh_dvec4, } cosh_vec2 :: proc "c" (x: vec2) -> vec2 { return {cosh(x.x), cosh(x.y)} } cosh_vec3 :: proc "c" (x: vec3) -> vec3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } cosh_vec4 :: proc "c" (x: vec4) -> vec4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } +cosh_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {cosh(x.x), cosh(x.y)} } +cosh_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } +cosh_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } sinh :: proc{ sinh_f32, + sinh_f64, sinh_vec2, sinh_vec3, sinh_vec4, + sinh_dvec2, + sinh_dvec3, + sinh_dvec4, } sinh_vec2 :: proc "c" (x: vec2) -> vec2 { return {sinh(x.x), sinh(x.y)} } sinh_vec3 :: proc "c" (x: vec3) -> vec3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } sinh_vec4 :: proc "c" (x: vec4) -> vec4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } - +sinh_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {sinh(x.x), sinh(x.y)} } +sinh_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } +sinh_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } tanh :: proc{ tanh_f32, + tanh_f64, tanh_vec2, tanh_vec3, tanh_vec4, + tanh_dvec2, + tanh_dvec3, + tanh_dvec4, } tanh_vec2 :: proc "c" (x: vec2) -> vec2 { return {tanh(x.x), tanh(x.y)} } tanh_vec3 :: proc "c" (x: vec3) -> vec3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } tanh_vec4 :: proc "c" (x: vec4) -> vec4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } - +tanh_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {tanh(x.x), tanh(x.y)} } +tanh_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } +tanh_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } acosh :: proc{ acosh_f32, + acosh_f64, acosh_vec2, acosh_vec3, acosh_vec4, + acosh_dvec2, + acosh_dvec3, + acosh_dvec4, } acosh_vec2 :: proc "c" (x: vec2) -> vec2 { return {acosh(x.x), acosh(x.y)} } acosh_vec3 :: proc "c" (x: vec3) -> vec3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } acosh_vec4 :: proc "c" (x: vec4) -> vec4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } - +acosh_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {acosh(x.x), acosh(x.y)} } +acosh_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } +acosh_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } asinh :: proc{ asinh_f32, + asinh_f64, asinh_vec2, asinh_vec3, asinh_vec4, + asinh_dvec2, + asinh_dvec3, + asinh_dvec4, } asinh_vec2 :: proc "c" (x: vec2) -> vec2 { return {asinh(x.x), asinh(x.y)} } asinh_vec3 :: proc "c" (x: vec3) -> vec3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } asinh_vec4 :: proc "c" (x: vec4) -> vec4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } - +asinh_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {asinh(x.x), asinh(x.y)} } +asinh_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } +asinh_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } atanh :: proc{ atanh_f32, + atanh_f64, atanh_vec2, atanh_vec3, atanh_vec4, + atanh_dvec2, + atanh_dvec3, + atanh_dvec4, } atanh_vec2 :: proc "c" (x: vec2) -> vec2 { return {atanh(x.x), atanh(x.y)} } atanh_vec3 :: proc "c" (x: vec3) -> vec3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } atanh_vec4 :: proc "c" (x: vec4) -> vec4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } - +atanh_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {atanh(x.x), atanh(x.y)} } +atanh_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } +atanh_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } sqrt :: proc{ sqrt_f32, + sqrt_f64, sqrt_vec2, sqrt_vec3, sqrt_vec4, + sqrt_dvec2, + sqrt_dvec3, + sqrt_dvec4, } sqrt_vec2 :: proc "c" (x: vec2) -> vec2 { return {sqrt(x.x), sqrt(x.y)} } sqrt_vec3 :: proc "c" (x: vec3) -> vec3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } sqrt_vec4 :: proc "c" (x: vec4) -> vec4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } - +sqrt_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {sqrt(x.x), sqrt(x.y)} } +sqrt_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } +sqrt_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } rsqrt :: inversesqrt inversesqrt :: proc{ inversesqrt_f32, + inversesqrt_f64, inversesqrt_vec2, inversesqrt_vec3, inversesqrt_vec4, + inversesqrt_dvec2, + inversesqrt_dvec3, + inversesqrt_dvec4, } inversesqrt_vec2 :: proc "c" (x: vec2) -> vec2 { return {inversesqrt(x.x), inversesqrt(x.y)} } inversesqrt_vec3 :: proc "c" (x: vec3) -> vec3 { return {inversesqrt(x.x), inversesqrt(x.y), inversesqrt(x.z)} } inversesqrt_vec4 :: proc "c" (x: vec4) -> vec4 { return {inversesqrt(x.x), inversesqrt(x.y), inversesqrt(x.z), inversesqrt(x.w)} } - +inversesqrt_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {inversesqrt(x.x), inversesqrt(x.y)} } +inversesqrt_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {inversesqrt(x.x), inversesqrt(x.y), inversesqrt(x.z)} } +inversesqrt_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {inversesqrt(x.x), inversesqrt(x.y), inversesqrt(x.z), inversesqrt(x.w)} } pow :: proc{ pow_f32, + pow_f64, pow_vec2, pow_vec3, pow_vec4, + pow_dvec2, + pow_dvec3, + pow_dvec4, } pow_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {pow(x.x, y.x), pow(x.y, y.y)} } pow_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } pow_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } +pow_dvec2 :: proc "c" (x, y: dvec2) -> dvec2 { return {pow(x.x, y.x), pow(x.y, y.y)} } +pow_dvec3 :: proc "c" (x, y: dvec3) -> dvec3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } +pow_dvec4 :: proc "c" (x, y: dvec4) -> dvec4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } + exp :: proc{ exp_f32, + exp_f64, exp_vec2, exp_vec3, exp_vec4, + exp_dvec2, + exp_dvec3, + exp_dvec4, } exp_vec2 :: proc "c" (x: vec2) -> vec2 { return {exp(x.x), exp(x.y)} } exp_vec3 :: proc "c" (x: vec3) -> vec3 { return {exp(x.x), exp(x.y), exp(x.z)} } exp_vec4 :: proc "c" (x: vec4) -> vec4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } +exp_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {exp(x.x), exp(x.y)} } +exp_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {exp(x.x), exp(x.y), exp(x.z)} } +exp_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } + log :: proc{ log_f32, + log_f64, log_vec2, log_vec3, log_vec4, + log_dvec2, + log_dvec3, + log_dvec4, } log_vec2 :: proc "c" (x: vec2) -> vec2 { return {log(x.x), log(x.y)} } log_vec3 :: proc "c" (x: vec3) -> vec3 { return {log(x.x), log(x.y), log(x.z)} } log_vec4 :: proc "c" (x: vec4) -> vec4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } +log_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {log(x.x), log(x.y)} } +log_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {log(x.x), log(x.y), log(x.z)} } +log_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } + exp2 :: proc{ exp2_f32, + exp2_f64, exp2_vec2, exp2_vec3, exp2_vec4, + exp2_dvec2, + exp2_dvec3, + exp2_dvec4, } exp2_vec2 :: proc "c" (x: vec2) -> vec2 { return {exp2(x.x), exp2(x.y)} } exp2_vec3 :: proc "c" (x: vec3) -> vec3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } exp2_vec4 :: proc "c" (x: vec4) -> vec4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } +exp2_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {exp2(x.x), exp2(x.y)} } +exp2_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } +exp2_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } sign :: proc{ sign_i32, sign_u32, sign_f32, + sign_f64, sign_vec2, sign_vec3, sign_vec4, + sign_dvec2, + sign_dvec3, + sign_dvec4, sign_ivec2, sign_ivec3, sign_ivec4, @@ -291,6 +445,9 @@ sign_u32 :: proc "c" (x: u32) -> u32 { return +1 if x > 0 else 0 } sign_vec2 :: proc "c" (x: vec2) -> vec2 { return {sign(x.x), sign(x.y)} } sign_vec3 :: proc "c" (x: vec3) -> vec3 { return {sign(x.x), sign(x.y), sign(x.z)} } sign_vec4 :: proc "c" (x: vec4) -> vec4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } +sign_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {sign(x.x), sign(x.y)} } +sign_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } sign_ivec2 :: proc "c" (x: ivec2) -> ivec2 { return {sign(x.x), sign(x.y)} } sign_ivec3 :: proc "c" (x: ivec3) -> ivec3 { return {sign(x.x), sign(x.y), sign(x.z)} } sign_ivec4 :: proc "c" (x: ivec4) -> ivec4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } @@ -300,80 +457,127 @@ sign_uvec4 :: proc "c" (x: uvec4) -> uvec4 { return {sign(x.x), sign(x.y), sign( floor :: proc{ floor_f32, + floor_f64, floor_vec2, floor_vec3, floor_vec4, + floor_dvec2, + floor_dvec3, + floor_dvec4, } floor_vec2 :: proc "c" (x: vec2) -> vec2 { return {floor(x.x), floor(x.y)} } floor_vec3 :: proc "c" (x: vec3) -> vec3 { return {floor(x.x), floor(x.y), floor(x.z)} } floor_vec4 :: proc "c" (x: vec4) -> vec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } +floor_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {floor(x.x), floor(x.y)} } +floor_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {floor(x.x), floor(x.y), floor(x.z)} } +floor_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } ceil :: proc{ ceil_f32, + ceil_f64, ceil_vec2, ceil_vec3, ceil_vec4, + ceil_dvec2, + ceil_dvec3, + ceil_dvec4, } ceil_vec2 :: proc "c" (x: vec2) -> vec2 { return {ceil(x.x), ceil(x.y)} } ceil_vec3 :: proc "c" (x: vec3) -> vec3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } ceil_vec4 :: proc "c" (x: vec4) -> vec4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } +ceil_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {ceil(x.x), ceil(x.y)} } +ceil_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } +ceil_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } mod :: proc{ mod_f32, + mod_f64, mod_vec2, mod_vec3, mod_vec4, + mod_dvec2, + mod_dvec3, + mod_dvec4, } mod_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {mod(x.x, y.x), mod(x.y, y.y)} } mod_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {mod(x.x, y.x), mod(x.y, y.y), mod(x.z, y.z)} } mod_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {mod(x.x, y.x), mod(x.y, y.y), mod(x.z, y.z), mod(x.w, y.w)} } +mod_dvec2 :: proc "c" (x, y: dvec2) -> dvec2 { return {mod(x.x, y.x), mod(x.y, y.y)} } +mod_dvec3 :: proc "c" (x, y: dvec3) -> dvec3 { return {mod(x.x, y.x), mod(x.y, y.y), mod(x.z, y.z)} } +mod_dvec4 :: proc "c" (x, y: dvec4) -> dvec4 { return {mod(x.x, y.x), mod(x.y, y.y), mod(x.z, y.z), mod(x.w, y.w)} } fract :: proc{ fract_f32, + fract_f64, fract_vec2, fract_vec3, fract_vec4, + fract_dvec2, + fract_dvec3, + fract_dvec4, } fract_vec2 :: proc "c" (x: vec2) -> vec2 { return {fract(x.x), fract(x.y)} } fract_vec3 :: proc "c" (x: vec3) -> vec3 { return {fract(x.x), fract(x.y), fract(x.z)} } fract_vec4 :: proc "c" (x: vec4) -> vec4 { return {fract(x.x), fract(x.y), fract(x.z), fract(x.w)} } +fract_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {fract(x.x), fract(x.y)} } +fract_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {fract(x.x), fract(x.y), fract(x.z)} } +fract_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {fract(x.x), fract(x.y), fract(x.z), fract(x.w)} } radians :: proc{ radians_f32, + radians_f64, radians_vec2, radians_vec3, radians_vec4, + radians_dvec2, + radians_dvec3, + radians_dvec4, } radians_f32 :: proc "c" (degrees: f32) -> f32 { return degrees * TAU / 360.0 } +radians_f64 :: proc "c" (degrees: f64) -> f64 { return degrees * TAU / 360.0 } radians_vec2 :: proc "c" (degrees: vec2) -> vec2 { return degrees * TAU / 360.0 } radians_vec3 :: proc "c" (degrees: vec3) -> vec3 { return degrees * TAU / 360.0 } radians_vec4 :: proc "c" (degrees: vec4) -> vec4 { return degrees * TAU / 360.0 } +radians_dvec2 :: proc "c" (degrees: dvec2) -> dvec2 { return degrees * TAU / 360.0 } +radians_dvec3 :: proc "c" (degrees: dvec3) -> dvec3 { return degrees * TAU / 360.0 } +radians_dvec4 :: proc "c" (degrees: dvec4) -> dvec4 { return degrees * TAU / 360.0 } degrees :: proc{ degrees_f32, + degrees_f64, degrees_vec2, degrees_vec3, degrees_vec4, + degrees_dvec2, + degrees_dvec3, + degrees_dvec4, } degrees_f32 :: proc "c" (radians: f32) -> f32 { return radians * 360.0 / TAU } +degrees_f64 :: proc "c" (radians: f64) -> f64 { return radians * 360.0 / TAU } degrees_vec2 :: proc "c" (radians: vec2) -> vec2 { return radians * 360.0 / TAU } degrees_vec3 :: proc "c" (radians: vec3) -> vec3 { return radians * 360.0 / TAU } degrees_vec4 :: proc "c" (radians: vec4) -> vec4 { return radians * 360.0 / TAU } - +degrees_dvec2 :: proc "c" (radians: dvec2) -> dvec2 { return radians * 360.0 / TAU } +degrees_dvec3 :: proc "c" (radians: dvec3) -> dvec3 { return radians * 360.0 / TAU } +degrees_dvec4 :: proc "c" (radians: dvec4) -> dvec4 { return radians * 360.0 / TAU } min :: proc{ min_i32, min_u32, min_f32, + min_f64, min_vec2, min_vec3, min_vec4, + min_dvec2, + min_dvec3, + min_dvec4, min_ivec2, min_ivec3, min_ivec4, @@ -384,9 +588,13 @@ min :: proc{ min_i32 :: proc "c" (x, y: i32) -> i32 { return builtin.min(x, y) } min_u32 :: proc "c" (x, y: u32) -> u32 { return builtin.min(x, y) } min_f32 :: proc "c" (x, y: f32) -> f32 { return builtin.min(x, y) } +min_f64 :: proc "c" (x, y: f64) -> f64 { return builtin.min(x, y) } min_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {min(x.x, y.x), min(x.y, y.y)} } min_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } min_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } +min_dvec2 :: proc "c" (x, y: dvec2) -> dvec2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_dvec3 :: proc "c" (x, y: dvec3) -> dvec3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_dvec4 :: proc "c" (x, y: dvec4) -> dvec4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } min_ivec2 :: proc "c" (x, y: ivec2) -> ivec2 { return {min(x.x, y.x), min(x.y, y.y)} } min_ivec3 :: proc "c" (x, y: ivec3) -> ivec3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } min_ivec4 :: proc "c" (x, y: ivec4) -> ivec4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } @@ -399,9 +607,13 @@ max :: proc{ max_i32, max_u32, max_f32, + max_f64, max_vec2, max_vec3, max_vec4, + max_dvec2, + max_dvec3, + max_dvec4, max_ivec2, max_ivec3, max_ivec4, @@ -412,9 +624,13 @@ max :: proc{ max_i32 :: proc "c" (x, y: i32) -> i32 { return builtin.max(x, y) } max_u32 :: proc "c" (x, y: u32) -> u32 { return builtin.max(x, y) } max_f32 :: proc "c" (x, y: f32) -> f32 { return builtin.max(x, y) } +max_f64 :: proc "c" (x, y: f64) -> f64 { return builtin.max(x, y) } max_vec2 :: proc "c" (x, y: vec2) -> vec2 { return {max(x.x, y.x), max(x.y, y.y)} } max_vec3 :: proc "c" (x, y: vec3) -> vec3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } max_vec4 :: proc "c" (x, y: vec4) -> vec4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } +max_dvec2 :: proc "c" (x, y: dvec2) -> dvec2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_dvec3 :: proc "c" (x, y: dvec3) -> dvec3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_dvec4 :: proc "c" (x, y: dvec4) -> dvec4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } max_ivec2 :: proc "c" (x, y: ivec2) -> ivec2 { return {max(x.x, y.x), max(x.y, y.y)} } max_ivec3 :: proc "c" (x, y: ivec3) -> ivec3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } max_ivec4 :: proc "c" (x, y: ivec4) -> ivec4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } @@ -428,9 +644,13 @@ clamp :: proc{ clamp_i32, clamp_u32, clamp_f32, + clamp_f64, clamp_vec2, clamp_vec3, clamp_vec4, + clamp_dvec2, + clamp_dvec3, + clamp_dvec4, clamp_ivec2, clamp_ivec3, clamp_ivec4, @@ -441,9 +661,13 @@ clamp :: proc{ clamp_i32 :: proc "c" (x, y, z: i32) -> i32 { return builtin.clamp(x, y, z) } clamp_u32 :: proc "c" (x, y, z: u32) -> u32 { return builtin.clamp(x, y, z) } clamp_f32 :: proc "c" (x, y, z: f32) -> f32 { return builtin.clamp(x, y, z) } +clamp_f64 :: proc "c" (x, y, z: f64) -> f64 { return builtin.clamp(x, y, z) } clamp_vec2 :: proc "c" (x, y, z: vec2) -> vec2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } clamp_vec3 :: proc "c" (x, y, z: vec3) -> vec3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } clamp_vec4 :: proc "c" (x, y, z: vec4) -> vec4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } +clamp_dvec2 :: proc "c" (x, y, z: dvec2) -> dvec2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_dvec3 :: proc "c" (x, y, z: dvec3) -> dvec3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_dvec4 :: proc "c" (x, y, z: dvec4) -> dvec4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } clamp_ivec2 :: proc "c" (x, y, z: ivec2) -> ivec2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } clamp_ivec3 :: proc "c" (x, y, z: ivec3) -> ivec3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } clamp_ivec4 :: proc "c" (x, y, z: ivec4) -> ivec4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } @@ -455,9 +679,13 @@ saturate :: proc{ saturate_i32, saturate_u32, saturate_f32, + saturate_f64, saturate_vec2, saturate_vec3, saturate_vec4, + saturate_dvec2, + saturate_dvec3, + saturate_dvec4, saturate_ivec2, saturate_ivec3, saturate_ivec4, @@ -468,9 +696,13 @@ saturate :: proc{ saturate_i32 :: proc "c" (x, y, z: i32) -> i32 { return builtin.clamp(x, 0, 1) } saturate_u32 :: proc "c" (x, y, z: u32) -> u32 { return builtin.clamp(x, 0, 1) } saturate_f32 :: proc "c" (x, y, z: f32) -> f32 { return builtin.clamp(x, 0, 1) } +saturate_f64 :: proc "c" (x, y, z: f64) -> f64 { return builtin.clamp(x, 0, 1) } saturate_vec2 :: proc "c" (x, y, z: vec2) -> vec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} } saturate_vec3 :: proc "c" (x, y, z: vec3) -> vec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} } saturate_vec4 :: proc "c" (x, y, z: vec4) -> vec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} } +saturate_dvec2 :: proc "c" (x, y, z: dvec2) -> dvec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} } +saturate_dvec3 :: proc "c" (x, y, z: dvec3) -> dvec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} } +saturate_dvec4 :: proc "c" (x, y, z: dvec4) -> dvec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} } saturate_ivec2 :: proc "c" (x, y, z: ivec2) -> ivec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} } saturate_ivec3 :: proc "c" (x, y, z: ivec3) -> ivec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} } saturate_ivec4 :: proc "c" (x, y, z: ivec4) -> ivec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} } @@ -481,46 +713,74 @@ saturate_uvec4 :: proc "c" (x, y, z: uvec4) -> uvec4 { return {builtin.clamp(x.x mix :: proc{ mix_f32, + mix_f64, mix_vec2, mix_vec3, mix_vec4, + mix_dvec2, + mix_dvec3, + mix_dvec4, } mix_f32 :: proc "c" (x, y, t: f32) -> f32 { return x*(1-t) + y*t } +mix_f64 :: proc "c" (x, y, t: f64) -> f64 { return x*(1-t) + y*t } mix_vec2 :: proc "c" (x, y, t: vec2) -> vec2 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, t.y)} } mix_vec3 :: proc "c" (x, y, t: vec3) -> vec3 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, t.y), mix(x.z, y.z, t.z)} } mix_vec4 :: proc "c" (x, y, t: vec4) -> vec4 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, y.y), mix(x.z, y.z, t.z), mix(x.w, y.w, t.w)} } +mix_dvec2 :: proc "c" (x, y, t: dvec2) -> dvec2 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, t.y)} } +mix_dvec3 :: proc "c" (x, y, t: dvec3) -> dvec3 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, t.y), mix(x.z, y.z, t.z)} } +mix_dvec4 :: proc "c" (x, y, t: dvec4) -> dvec4 { return {mix(x.x, y.x, t.x), mix(x.y, y.y, y.y), mix(x.z, y.z, t.z), mix(x.w, y.w, t.w)} } lerp :: proc{ lerp_f32, + lerp_f64, lerp_vec2, lerp_vec3, lerp_vec4, + lerp_dvec2, + lerp_dvec3, + lerp_dvec4, } lerp_f32 :: proc "c" (x, y, t: f32) -> f32 { return x*(1-t) + y*t } +lerp_f64 :: proc "c" (x, y, t: f64) -> f64 { return x*(1-t) + y*t } lerp_vec2 :: proc "c" (x, y, t: vec2) -> vec2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } lerp_vec3 :: proc "c" (x, y, t: vec3) -> vec3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } lerp_vec4 :: proc "c" (x, y, t: vec4) -> vec4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } +lerp_dvec2 :: proc "c" (x, y, t: dvec2) -> dvec2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } +lerp_dvec3 :: proc "c" (x, y, t: dvec3) -> dvec3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } +lerp_dvec4 :: proc "c" (x, y, t: dvec4) -> dvec4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } step :: proc{ step_f32, + step_f64, step_vec2, step_vec3, step_vec4, + step_dvec2, + step_dvec3, + step_dvec4, } step_f32 :: proc "c" (edge, x: f32) -> f32 { return 0 if x < edge else 1 } +step_f64 :: proc "c" (edge, x: f64) -> f64 { return 0 if x < edge else 1 } step_vec2 :: proc "c" (edge, x: vec2) -> vec2 { return {step(edge.x, x.x), step(edge.y, x.y)} } step_vec3 :: proc "c" (edge, x: vec3) -> vec3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } step_vec4 :: proc "c" (edge, x: vec4) -> vec4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } +step_dvec2 :: proc "c" (edge, x: dvec2) -> dvec2 { return {step(edge.x, x.x), step(edge.y, x.y)} } +step_dvec3 :: proc "c" (edge, x: dvec3) -> dvec3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } +step_dvec4 :: proc "c" (edge, x: dvec4) -> dvec4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } abs :: proc{ abs_i32, abs_u32, abs_f32, + abs_f64, abs_vec2, abs_vec3, abs_vec4, + abs_dvec2, + abs_dvec3, + abs_dvec4, abs_ivec2, abs_ivec3, abs_ivec4, @@ -531,9 +791,13 @@ abs :: proc{ abs_i32 :: proc "c" (x: i32) -> i32 { return builtin.abs(x) } abs_u32 :: proc "c" (x: u32) -> u32 { return x } abs_f32 :: proc "c" (x: f32) -> f32 { return builtin.abs(x) } +abs_f64 :: proc "c" (x: f64) -> f64 { return builtin.abs(x) } abs_vec2 :: proc "c" (x: vec2) -> vec2 { return {abs(x.x), abs(x.y)} } abs_vec3 :: proc "c" (x: vec3) -> vec3 { return {abs(x.x), abs(x.y), abs(x.z)} } abs_vec4 :: proc "c" (x: vec4) -> vec4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } +abs_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {abs(x.x), abs(x.y)} } +abs_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {abs(x.x), abs(x.y), abs(x.z)} } +abs_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } abs_ivec2 :: proc "c" (x: ivec2) -> ivec2 { return {abs(x.x), abs(x.y)} } abs_ivec3 :: proc "c" (x: ivec3) -> ivec3 { return {abs(x.x), abs(x.y), abs(x.z)} } abs_ivec4 :: proc "c" (x: ivec4) -> ivec4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } @@ -545,9 +809,13 @@ dot :: proc{ dot_i32, dot_u32, dot_f32, + dot_f64, dot_vec2, dot_vec3, dot_vec4, + dot_dvec2, + dot_dvec3, + dot_dvec4, dot_ivec2, dot_ivec3, dot_ivec4, @@ -559,9 +827,13 @@ dot :: proc{ dot_i32 :: proc "c" (a, b: i32) -> i32 { return a*b } dot_u32 :: proc "c" (a, b: u32) -> u32 { return a*b } dot_f32 :: proc "c" (a, b: f32) -> f32 { return a*b } +dot_f64 :: proc "c" (a, b: f64) -> f64 { return a*b } dot_vec2 :: proc "c" (a, b: vec2) -> f32 { return a.x*b.x + a.y*b.y } dot_vec3 :: proc "c" (a, b: vec3) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z } dot_vec4 :: proc "c" (a, b: vec4) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_dvec2 :: proc "c" (a, b: dvec2) -> f64 { return a.x*b.x + a.y*b.y } +dot_dvec3 :: proc "c" (a, b: dvec3) -> f64 { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_dvec4 :: proc "c" (a, b: dvec4) -> f64 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } dot_ivec2 :: proc "c" (a, b: ivec2) -> i32 { return a.x*b.x + a.y*b.y } dot_ivec3 :: proc "c" (a, b: ivec3) -> i32 { return a.x*b.x + a.y*b.y + a.z*b.z } dot_ivec4 :: proc "c" (a, b: ivec4) -> i32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } @@ -572,32 +844,51 @@ dot_quat :: proc "c" (a, b: quat) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z + length :: proc{ length_f32, + length_f64, length_vec2, length_vec3, length_vec4, + length_dvec2, + length_dvec3, + length_dvec4, length_quat, + length_dquat, } length_f32 :: proc "c" (x: f32) -> f32 { return builtin.abs(x) } +length_f64 :: proc "c" (x: f64) -> f64 { return builtin.abs(x) } length_vec2 :: proc "c" (x: vec2) -> f32 { return sqrt(x.x*x.x + x.y*x.y) } length_vec3 :: proc "c" (x: vec3) -> f32 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } length_vec4 :: proc "c" (x: vec4) -> f32 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } +length_dvec2 :: proc "c" (x: dvec2) -> f64 { return sqrt(x.x*x.x + x.y*x.y) } +length_dvec3 :: proc "c" (x: dvec3) -> f64 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } +length_dvec4 :: proc "c" (x: dvec4) -> f64 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } length_quat :: proc "c" (x: quat) -> f32 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } +length_dquat :: proc "c" (x: dquat) -> f64 { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } distance :: proc{ distance_f32, + distance_f64, distance_vec2, distance_vec3, distance_vec4, + distance_dvec2, + distance_dvec3, + distance_dvec4, } distance_f32 :: proc "c" (x, y: f32) -> f32 { return length(y-x) } +distance_f64 :: proc "c" (x, y: f64) -> f64 { return length(y-x) } distance_vec2 :: proc "c" (x, y: vec2) -> f32 { return length(y-x) } distance_vec3 :: proc "c" (x, y: vec3) -> f32 { return length(y-x) } distance_vec4 :: proc "c" (x, y: vec4) -> f32 { return length(y-x) } +distance_dvec2 :: proc "c" (x, y: dvec2) -> f64 { return length(y-x) } +distance_dvec3 :: proc "c" (x, y: dvec3) -> f64 { return length(y-x) } +distance_dvec4 :: proc "c" (x, y: dvec4) -> f64 { return length(y-x) } cross :: proc{ cross_vec3, + cross_dvec3, cross_ivec3, } @@ -607,6 +898,12 @@ cross_vec3 :: proc "c" (a, b: vec3) -> (c: vec3) { c.z = a.x*b.y - b.x*a.y return } +cross_dvec3 :: proc "c" (a, b: dvec3) -> (c: dvec3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} cross_ivec3 :: proc "c" (a, b: ivec3) -> (c: ivec3) { c.x = a.y*b.z - b.y*a.z c.y = a.z*b.x - b.z*a.x @@ -616,48 +913,79 @@ cross_ivec3 :: proc "c" (a, b: ivec3) -> (c: ivec3) { normalize :: proc{ normalize_f32, + normalize_f64, normalize_vec2, normalize_vec3, normalize_vec4, + normalize_dvec2, + normalize_dvec3, + normalize_dvec4, normalize_quat, + normalize_dquat, } normalize_f32 :: proc "c" (x: f32) -> f32 { return 1.0 } +normalize_f64 :: proc "c" (x: f64) -> f64 { return 1.0 } normalize_vec2 :: proc "c" (x: vec2) -> vec2 { return x / length(x) } normalize_vec3 :: proc "c" (x: vec3) -> vec3 { return x / length(x) } normalize_vec4 :: proc "c" (x: vec4) -> vec4 { return x / length(x) } +normalize_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return x / length(x) } +normalize_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return x / length(x) } +normalize_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return x / length(x) } normalize_quat :: proc "c" (x: quat) -> quat { return x / quat(length(x)) } +normalize_dquat :: proc "c" (x: dquat) -> dquat { return x / dquat(length(x)) } faceForward :: proc{ faceForward_f32, + faceForward_f64, faceForward_vec2, faceForward_vec3, faceForward_vec4, + faceForward_dvec2, + faceForward_dvec3, + faceForward_dvec4, } faceForward_f32 :: proc "c" (N, I, Nref: f32) -> f32 { return N if dot(I, Nref) < 0 else -N } +faceForward_f64 :: proc "c" (N, I, Nref: f64) -> f64 { return N if dot(I, Nref) < 0 else -N } faceForward_vec2 :: proc "c" (N, I, Nref: vec2) -> vec2 { return N if dot(I, Nref) < 0 else -N } faceForward_vec3 :: proc "c" (N, I, Nref: vec3) -> vec3 { return N if dot(I, Nref) < 0 else -N } faceForward_vec4 :: proc "c" (N, I, Nref: vec4) -> vec4 { return N if dot(I, Nref) < 0 else -N } +faceForward_dvec2 :: proc "c" (N, I, Nref: dvec2) -> dvec2 { return N if dot(I, Nref) < 0 else -N } +faceForward_dvec3 :: proc "c" (N, I, Nref: dvec3) -> dvec3 { return N if dot(I, Nref) < 0 else -N } +faceForward_dvec4 :: proc "c" (N, I, Nref: dvec4) -> dvec4 { return N if dot(I, Nref) < 0 else -N } reflect :: proc{ reflect_f32, + reflect_f64, reflect_vec2, reflect_vec3, reflect_vec4, + reflect_dvec2, + reflect_dvec3, + reflect_dvec4, } reflect_f32 :: proc "c" (I, N: f32) -> f32 { return I - 2*N*dot(N, I) } +reflect_f64 :: proc "c" (I, N: f64) -> f64 { return I - 2*N*dot(N, I) } reflect_vec2 :: proc "c" (I, N: vec2) -> vec2 { return I - 2*N*dot(N, I) } reflect_vec3 :: proc "c" (I, N: vec3) -> vec3 { return I - 2*N*dot(N, I) } reflect_vec4 :: proc "c" (I, N: vec4) -> vec4 { return I - 2*N*dot(N, I) } +reflect_dvec2 :: proc "c" (I, N: dvec2) -> dvec2 { return I - 2*N*dot(N, I) } +reflect_dvec3 :: proc "c" (I, N: dvec3) -> dvec3 { return I - 2*N*dot(N, I) } +reflect_dvec4 :: proc "c" (I, N: dvec4) -> dvec4 { return I - 2*N*dot(N, I) } + refract :: proc{ refract_f32, + refract_f64, refract_vec2, refract_vec3, refract_vec4, + refract_dvec2, + refract_dvec3, + refract_dvec4, } refract_f32 :: proc "c" (i, n, eta: f32) -> f32 { cosi := dot(-i, n) @@ -665,6 +993,12 @@ refract_f32 :: proc "c" (i, n, eta: f32) -> f32 { t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) return t * f32(i32(cost2 > 0)) } +refract_f64 :: proc "c" (i, n, eta: f64) -> f64 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * f64(i32(cost2 > 0)) +} refract_vec2 :: proc "c" (i, n, eta: vec2) -> vec2 { cosi := dot(-i, n) cost2 := 1 - eta*eta*(1 - cosi*cosi) @@ -683,176 +1017,257 @@ refract_vec4 :: proc "c" (i, n, eta: vec4) -> vec4 { t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) return t * vec4{f32(i32(cost2.x > 0)), f32(i32(cost2.y > 0)), f32(i32(cost2.z > 0)), f32(i32(cost2.w > 0))} } +refract_dvec2 :: proc "c" (i, n, eta: dvec2) -> dvec2 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * dvec2{f64(i32(cost2.x > 0)), f64(i32(cost2.y > 0))} +} +refract_dvec3 :: proc "c" (i, n, eta: dvec3) -> dvec3 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * dvec3{f64(i32(cost2.x > 0)), f64(i32(cost2.y > 0)), f64(i32(cost2.z > 0))} +} +refract_dvec4 :: proc "c" (i, n, eta: dvec4) -> dvec4 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * dvec4{f64(i32(cost2.x > 0)), f64(i32(cost2.y > 0)), f64(i32(cost2.z > 0)), f64(i32(cost2.w > 0))} +} -scalarTripleProduct :: proc "c" (a, b, c: vec3) -> f32 { return dot(a, cross(b, c)) } -vectorTripleProduct :: proc "c" (a, b, c: vec3) -> vec3 { return cross(a, cross(b, c)) } +scalarTripleProduct :: proc{ + scalarTripleProduct_vec3, + scalarTripleProduct_dvec3, + scalarTripleProduct_ivec3, +} +scalarTripleProduct_vec3 :: proc "c" (a, b, c: vec3) -> f32 { return dot(a, cross(b, c)) } +scalarTripleProduct_dvec3 :: proc "c" (a, b, c: dvec3) -> f64 { return dot(a, cross(b, c)) } +scalarTripleProduct_ivec3 :: proc "c" (a, b, c: ivec3) -> i32 { return dot(a, cross(b, c)) } + +vectorTripleProduct :: proc { + vectorTripleProduct_vec3, + vectorTripleProduct_dvec3, + vectorTripleProduct_ivec3, +} +vectorTripleProduct_vec3 :: proc "c" (a, b, c: vec3) -> vec3 { return cross(a, cross(b, c)) } +vectorTripleProduct_dvec3 :: proc "c" (a, b, c: dvec3) -> dvec3 { return cross(a, cross(b, c)) } +vectorTripleProduct_ivec3 :: proc "c" (a, b, c: ivec3) -> ivec3 { return cross(a, cross(b, c)) } // Vector Relational Procedures lessThan :: proc{ lessThan_f32, + lessThan_f64, lessThan_i32, lessThan_u32, lessThan_vec2, + lessThan_dvec2, lessThan_ivec2, lessThan_uvec2, lessThan_vec3, + lessThan_dvec3, lessThan_ivec3, lessThan_uvec3, lessThan_vec4, + lessThan_dvec4, lessThan_ivec4, lessThan_uvec4, } lessThan_f32 :: proc "c" (a, b: f32) -> bool { return a < b } +lessThan_f64 :: proc "c" (a, b: f64) -> bool { return a < b } lessThan_i32 :: proc "c" (a, b: i32) -> bool { return a < b } lessThan_u32 :: proc "c" (a, b: u32) -> bool { return a < b } lessThan_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } +lessThan_dvec2 :: proc "c" (a, b: dvec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } lessThan_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } lessThan_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x < b.x, a.y < b.y} } lessThan_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_dvec3 :: proc "c" (a, b: dvec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } lessThan_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } lessThan_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } lessThan_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } +lessThan_dvec4 :: proc "c" (a, b: dvec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } lessThan_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } lessThan_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } lessThanEqual :: proc{ lessThanEqual_f32, + lessThanEqual_f64, lessThanEqual_i32, lessThanEqual_u32, lessThanEqual_vec2, + lessThanEqual_dvec2, lessThanEqual_ivec2, lessThanEqual_uvec2, lessThanEqual_vec3, + lessThanEqual_dvec3, lessThanEqual_ivec3, lessThanEqual_uvec3, lessThanEqual_vec4, + lessThanEqual_dvec4, lessThanEqual_ivec4, lessThanEqual_uvec4, } lessThanEqual_f32 :: proc "c" (a, b: f32) -> bool { return a <= b } +lessThanEqual_f64 :: proc "c" (a, b: f64) -> bool { return a <= b } lessThanEqual_i32 :: proc "c" (a, b: i32) -> bool { return a <= b } lessThanEqual_u32 :: proc "c" (a, b: u32) -> bool { return a <= b } lessThanEqual_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_dvec2 :: proc "c" (a, b: dvec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } lessThanEqual_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } lessThanEqual_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x <= b.x, a.y <= b.y} } lessThanEqual_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_dvec3 :: proc "c" (a, b: dvec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } lessThanEqual_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } lessThanEqual_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } lessThanEqual_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } +lessThanEqual_dvec4 :: proc "c" (a, b: dvec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } lessThanEqual_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } lessThanEqual_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } greaterThan :: proc{ greaterThan_f32, + greaterThan_f64, greaterThan_i32, greaterThan_u32, greaterThan_vec2, + greaterThan_dvec2, greaterThan_ivec2, greaterThan_uvec2, greaterThan_vec3, + greaterThan_dvec3, greaterThan_ivec3, greaterThan_uvec3, greaterThan_vec4, + greaterThan_dvec4, greaterThan_ivec4, greaterThan_uvec4, } greaterThan_f32 :: proc "c" (a, b: f32) -> bool { return a > b } +greaterThan_f64 :: proc "c" (a, b: f64) -> bool { return a > b } greaterThan_i32 :: proc "c" (a, b: i32) -> bool { return a > b } greaterThan_u32 :: proc "c" (a, b: u32) -> bool { return a > b } greaterThan_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } +greaterThan_dvec2 :: proc "c" (a, b: dvec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } greaterThan_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } greaterThan_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x > b.x, a.y > b.y} } greaterThan_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_dvec3 :: proc "c" (a, b: dvec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } greaterThan_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } greaterThan_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } greaterThan_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } +greaterThan_dvec4 :: proc "c" (a, b: dvec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } greaterThan_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } greaterThan_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } greaterThanEqual :: proc{ greaterThanEqual_f32, + greaterThanEqual_f64, greaterThanEqual_i32, greaterThanEqual_u32, greaterThanEqual_vec2, + greaterThanEqual_dvec2, greaterThanEqual_ivec2, greaterThanEqual_uvec2, greaterThanEqual_vec3, + greaterThanEqual_dvec3, greaterThanEqual_ivec3, greaterThanEqual_uvec3, greaterThanEqual_vec4, + greaterThanEqual_dvec4, greaterThanEqual_ivec4, greaterThanEqual_uvec4, } greaterThanEqual_f32 :: proc "c" (a, b: f32) -> bool { return a >= b } +greaterThanEqual_f64 :: proc "c" (a, b: f64) -> bool { return a >= b } greaterThanEqual_i32 :: proc "c" (a, b: i32) -> bool { return a >= b } greaterThanEqual_u32 :: proc "c" (a, b: u32) -> bool { return a >= b } greaterThanEqual_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_dvec2 :: proc "c" (a, b: dvec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } greaterThanEqual_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } greaterThanEqual_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x >= b.x, a.y >= b.y} } greaterThanEqual_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_dvec3 :: proc "c" (a, b: dvec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } greaterThanEqual_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } greaterThanEqual_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } greaterThanEqual_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } +greaterThanEqual_dvec4 :: proc "c" (a, b: dvec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } greaterThanEqual_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } greaterThanEqual_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } equal :: proc{ equal_f32, + equal_f64, equal_i32, equal_u32, equal_vec2, + equal_dvec2, equal_ivec2, equal_uvec2, equal_vec3, + equal_dvec3, equal_ivec3, equal_uvec3, equal_vec4, + equal_dvec4, equal_ivec4, equal_uvec4, } equal_f32 :: proc "c" (a, b: f32) -> bool { return a == b } +equal_f64 :: proc "c" (a, b: f64) -> bool { return a == b } equal_i32 :: proc "c" (a, b: i32) -> bool { return a == b } equal_u32 :: proc "c" (a, b: u32) -> bool { return a == b } equal_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } +equal_dvec2 :: proc "c" (a, b: dvec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } equal_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } equal_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x == b.x, a.y == b.y} } equal_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_dvec3 :: proc "c" (a, b: dvec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } equal_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } equal_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } equal_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } +equal_dvec4 :: proc "c" (a, b: dvec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } equal_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } equal_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } notEqual :: proc{ notEqual_f32, + notEqual_f64, notEqual_i32, notEqual_u32, notEqual_vec2, + notEqual_dvec2, notEqual_ivec2, notEqual_uvec2, notEqual_vec3, + notEqual_dvec3, notEqual_ivec3, notEqual_uvec3, notEqual_vec4, + notEqual_dvec4, notEqual_ivec4, notEqual_uvec4, } notEqual_f32 :: proc "c" (a, b: f32) -> bool { return a != b } +notEqual_f64 :: proc "c" (a, b: f64) -> bool { return a != b } notEqual_i32 :: proc "c" (a, b: i32) -> bool { return a != b } notEqual_u32 :: proc "c" (a, b: u32) -> bool { return a != b } notEqual_vec2 :: proc "c" (a, b: vec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } +notEqual_dvec2 :: proc "c" (a, b: dvec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } notEqual_ivec2 :: proc "c" (a, b: ivec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } notEqual_uvec2 :: proc "c" (a, b: uvec2) -> bvec2 { return {a.x != b.x, a.y != b.y} } notEqual_vec3 :: proc "c" (a, b: vec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_dvec3 :: proc "c" (a, b: dvec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } notEqual_ivec3 :: proc "c" (a, b: ivec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } notEqual_uvec3 :: proc "c" (a, b: uvec3) -> bvec3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } notEqual_vec4 :: proc "c" (a, b: vec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } +notEqual_dvec4 :: proc "c" (a, b: dvec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } notEqual_ivec4 :: proc "c" (a, b: ivec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } notEqual_uvec4 :: proc "c" (a, b: uvec4) -> bvec4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } @@ -894,7 +1309,7 @@ not_bvec4 :: proc "c" (v: bvec4) -> bvec4 { return {!v.x, !v.y, !v.z, !v.w} } /// Matrix Utilities -identity :: proc "c" ($M: typeid/matrix[$N, N]f32) -> M { return 1 } +identity :: proc "c" ($M: typeid/matrix[$N, N]$T) -> M { return 1 } mat4Perspective :: proc "c" (fovy, aspect, near, far: f32) -> (m: mat4) { tan_half_fovy := tan(0.5 * fovy) @@ -924,8 +1339,6 @@ mat4Ortho3d :: proc "c" (left, right, bottom, top, near, far: f32) -> (m: mat4) m[3, 3] = 1 return m } - - mat4LookAt :: proc "c" (eye, centre, up: vec3) -> (m: mat4) { f := normalize(centre - eye) s := normalize(cross(f, up)) @@ -938,14 +1351,7 @@ mat4LookAt :: proc "c" (eye, centre, up: vec3) -> (m: mat4) { m[2] = {+s.z, +u.z, -f.z, 0} m[3] = {-dot(s, eye), -dot(u, eye), +fe, 1} return - // return mat4{ - // +s.x, +s.y, +s.z, -dot(s, eye), - // +u.x, +u.y, +u.z, -dot(u, eye), - // -f.x, -f.y, -f.z, +fe, - // 0, 0, 0, 1, - // } } - mat4Rotate :: proc "c" (v: vec3, radians: f32) -> (rot: mat4) { c := cos(radians) s := sin(radians) @@ -972,7 +1378,6 @@ mat4Rotate :: proc "c" (v: vec3, radians: f32) -> (rot: mat4) { return rot } - mat4Translate :: proc "c" (v: vec3) -> (m: mat4) { m = 1 m[3].xyz = v.xyz @@ -985,7 +1390,6 @@ mat4Scale :: proc "c" (v: vec3) -> (m: mat4) { m[3, 3] = 1 return } - mat4Orientation :: proc "c" (normal, up: vec3) -> mat4 { if normal == up { return 1 @@ -996,7 +1400,6 @@ mat4Orientation :: proc "c" (normal, up: vec3) -> mat4 { return mat4Rotate(rotation_axis, angle) } - mat4FromQuat :: proc "c" (q: quat) -> (m: mat4) { qxx := q.x * q.x qyy := q.y * q.y @@ -1034,11 +1437,9 @@ quatAxisAngle :: proc "c" (axis: vec3, radians: f32) -> (q: quat) { q.w = cos(t) return } - -quatDot :: proc "c" (a, b: quat) -> f32 { +dquatot :: proc "c" (a, b: quat) -> f32 { return dot(transmute(vec4)a, transmute(vec4)b) } - quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) { c.x = a.x + (b.x-a.x)*t c.y = a.y + (b.y-a.y)*t @@ -1049,7 +1450,7 @@ quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) { quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) { a, b := x, y - cos_angle := quatDot(a, b) + cos_angle := dquatot(a, b) if cos_angle < 0 { b = -b cos_angle = -cos_angle @@ -1073,7 +1474,6 @@ quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) { q.w = factor_a * a.w + factor_b * b.w return } - quatFromMat3 :: proc "c" (m: mat3) -> (q: quat) { 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] @@ -1123,7 +1523,6 @@ quatFromMat3 :: proc "c" (m: mat3) -> (q: quat) { } return } - quatFromMat4 :: proc "c" (m: mat4) -> (q: quat) { return quatFromMat3(mat3(m)) } @@ -1134,6 +1533,235 @@ quatMulVec3 :: proc "c" (q: quat, v: vec3) -> vec3 { return v + q.w*t + cross(xyz, t) } + + +dmat4Perspective :: proc "c" (fovy, aspect, near, far: f64) -> (m: dmat4) { + tan_half_fovy := 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[3, 2] = -1 + m[2, 3] = -2*far*near / (far - near) + return +} +dmat4PerspectiveInfinite :: proc "c" (fovy, aspect, near: f64) -> (m: dmat4) { + tan_half_fovy := tan(0.5 * fovy) + m[0, 0] = 1 / (aspect*tan_half_fovy) + m[1, 1] = 1 / (tan_half_fovy) + m[2, 2] = -1 + m[3, 2] = -1 + m[2, 3] = -2*near + return +} +dmat4Ortho3d :: proc "c" (left, right, bottom, top, near, far: f64) -> (m: dmat4) { + m[0, 0] = +2 / (right - left) + m[1, 1] = +2 / (top - bottom) + m[2, 2] = -2 / (far - near) + m[0, 3] = -(right + left) / (right - left) + m[1, 3] = -(top + bottom) / (top - bottom) + m[2, 3] = -(far + near) / (far- near) + m[3, 3] = 1 + return m +} +dmat4LookAt :: proc "c" (eye, centre, up: dvec3) -> (m: dmat4) { + f := normalize(centre - eye) + s := normalize(cross(f, up)) + u := cross(s, f) + + fe := dot(f, eye) + + m[0] = {+s.x, +u.x, -f.x, 0} + m[1] = {+s.y, +u.y, -f.y, 0} + m[2] = {+s.z, +u.z, -f.z, 0} + m[3] = {-dot(s, eye), -dot(u, eye), +fe, 1} + return +} +dmat4Rotate :: proc "c" (v: dvec3, radians: f64) -> (rot: dmat4) { + c := cos(radians) + s := sin(radians) + + a := normalize(v) + t := a * (1-c) + + rot = 1 + + rot[0, 0] = c + t[0]*a[0] + rot[1, 0] = 0 + t[0]*a[1] + s*a[2] + rot[2, 0] = 0 + t[0]*a[2] - s*a[1] + rot[3, 0] = 0 + + rot[0, 1] = 0 + t[1]*a[0] - s*a[2] + rot[1, 1] = c + t[1]*a[1] + rot[2, 1] = 0 + t[1]*a[2] + s*a[0] + rot[3, 1] = 0 + + rot[0, 2] = 0 + t[2]*a[0] + s*a[1] + rot[1, 2] = 0 + t[2]*a[1] - s*a[0] + rot[2, 2] = c + t[2]*a[2] + rot[3, 2] = 0 + + return rot +} +dmat4Translate :: proc "c" (v: dvec3) -> (m: dmat4) { + m = 1 + m[3].xyz = v.xyz + return +} +dmat4Scale :: proc "c" (v: dvec3) -> (m: dmat4) { + m[0, 0] = v[0] + m[1, 1] = v[1] + m[2, 2] = v[2] + m[3, 3] = 1 + return +} +dmat4Orientation :: proc "c" (normal, up: dvec3) -> dmat4 { + if normal == up { + return 1 + } + + rotation_axis := cross(up, normal) + angle := acos(dot(normal, up)) + + return dmat4Rotate(rotation_axis, angle) +} +dmat4FromDquat :: proc "c" (q: dquat) -> (m: dmat4) { + 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[1, 0] = 2 * (qxy + qwz) + m[2, 0] = 2 * (qxz - qwy) + + m[0, 1] = 2 * (qxy - qwz) + m[1, 1] = 1 - 2 * (qxx + qzz) + m[2, 1] = 2 * (qyz + qwx) + + m[0, 2] = 2 * (qxz + qwy) + m[1, 2] = 2 * (qyz - qwx) + m[2, 2] = 1 - 2 * (qxx + qyy) + + m[3, 3] = 1 + + return +} + + + +dquatAxisAngle :: proc "c" (axis: dvec3, radians: f64) -> (q: dquat) { + t := radians*0.5 + v := normalize(axis) * sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = cos(t) + return +} +dquatDot :: proc "c" (a, b: dquat) -> f64 { + return dot(transmute(dvec4)a, transmute(dvec4)b) +} +dquatNlerp :: proc "c" (a, b: dquat, t: f64) -> (c: dquat) { + 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 c/builtin.abs(c) +} + +dquatSlerp :: proc "c" (x, y: dquat, t: f64) -> (q: dquat) { + a, b := x, y + cos_angle := dquatDot(a, b) + if cos_angle < 0 { + 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 + } + + angle := acos(cos_angle) + sin_angle := sin(angle) + factor_a := sin((1-t) * angle) / sin_angle + factor_b := 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 +} +dquatFromdMat3 :: proc "c" (m: dmat3) -> (q: dquat) { + 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 + if four_x_squared_minus_1 > four_biggest_squared_minus_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 + } + if four_z_squared_minus_1 > four_biggest_squared_minus_1 { + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 + } + + biggest_val := sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val + + q = 1 + switch biggest_index { + case 0: + q.w = biggest_val + q.x = (m[2, 1] - m[1, 2]) * mult + q.y = (m[0, 2] - m[2, 0]) * mult + q.z = (m[1, 0] - m[0, 1]) * mult + case 1: + q.w = (m[2, 1] - m[1, 2]) * mult + q.x = biggest_val + q.y = (m[1, 0] + m[0, 1]) * mult + q.z = (m[0, 2] + m[2, 0]) * mult + case 2: + q.w = (m[0, 2] - m[2, 0]) * mult + q.x = (m[1, 0] + m[0, 1]) * mult + q.y = biggest_val + q.z = (m[2, 1] + m[1, 2]) * mult + case 3: + q.w = (m[1, 0] - m[0, 1]) * mult + q.x = (m[0, 2] + m[2, 0]) * mult + q.y = (m[2, 1] + m[1, 2]) * mult + q.z = biggest_val + } + return +} +dquatFromDmat4 :: proc "c" (m: dmat4) -> (q: dquat) { + return dquatFromdMat3(dmat3(m)) +} + +dquatMulDvec3 :: proc "c" (q: dquat, v: dvec3) -> dvec3 { + xyz := dvec3{q.x, q.y, q.z} + t := cross(xyz, v) + return v + q.w*t + cross(xyz, t) +} + + + + inverse_mat2 :: proc "c" (m: mat2) -> mat2 { return builtin.inverse(m) } inverse_mat3 :: proc "c" (m: mat3) -> mat3 { return builtin.inverse(m) } inverse_mat4 :: proc "c" (m: mat4) -> mat4 { return builtin.inverse(m) } diff --git a/core/math/linalg/glsl/linalg_glsl_math.odin b/core/math/linalg/glsl/linalg_glsl_math.odin index 5d06c02a1..68f43a2f7 100644 --- a/core/math/linalg/glsl/linalg_glsl_math.odin +++ b/core/math/linalg/glsl/linalg_glsl_math.odin @@ -16,11 +16,11 @@ acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) } asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) } atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) } sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) } -inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/sqrt(x) } +inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/math.sqrt(x) } pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) } exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) } log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) } -exp2_f32 :: proc "c" (x: f32) -> f32 { return pow(2, x) } +exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) } sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) } floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) } ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) } @@ -31,3 +31,33 @@ fract_f32 :: proc "c" (x: f32) -> f32 { } return math.trunc(-x) + x } + +cos_f64 :: proc "c" (x: f64) -> f64 { return math.cos(x) } +sin_f64 :: proc "c" (x: f64) -> f64 { return math.sin(x) } +tan_f64 :: proc "c" (x: f64) -> f64 { return math.tan(x) } +acos_f64 :: proc "c" (x: f64) -> f64 { return math.acos(x) } +asin_f64 :: proc "c" (x: f64) -> f64 { return math.asin(x) } +atan_f64 :: proc "c" (x: f64) -> f64 { return math.atan(x) } +atan2_f64 :: proc "c" (y, x: f64) -> f64 { return math.atan2(y, x) } +cosh_f64 :: proc "c" (x: f64) -> f64 { return math.cosh(x) } +sinh_f64 :: proc "c" (x: f64) -> f64 { return math.sinh(x) } +tanh_f64 :: proc "c" (x: f64) -> f64 { return math.tanh(x) } +acosh_f64 :: proc "c" (x: f64) -> f64 { return math.acosh(x) } +asinh_f64 :: proc "c" (x: f64) -> f64 { return math.asinh(x) } +atanh_f64 :: proc "c" (x: f64) -> f64 { return math.atanh(x) } +sqrt_f64 :: proc "c" (x: f64) -> f64 { return math.sqrt(x) } +inversesqrt_f64 :: proc "c" (x: f64) -> f64 { return 1.0/math.sqrt(x) } +pow_f64 :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) } +exp_f64 :: proc "c" (x: f64) -> f64 { return math.exp(x) } +log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) } +exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) } +sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) } +floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) } +ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) } +mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) } +fract_f64 :: proc "c" (x: f64) -> f64 { + if x >= 0 { + return x - math.trunc(x) + } + return math.trunc(-x) + x +} From 95f36d4fa50c360428fb2bc5747d0fd23966c7ad Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:54:55 +0000 Subject: [PATCH 11/13] Minor reorganization --- core/math/linalg/glsl/linalg_glsl.odin | 225 +++++++++++++------------ 1 file changed, 114 insertions(+), 111 deletions(-) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index a77a91505..9cce68149 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -823,6 +823,7 @@ dot :: proc{ dot_uvec3, dot_uvec4, dot_quat, + dot_dquat, } dot_i32 :: proc "c" (a, b: i32) -> i32 { return a*b } dot_u32 :: proc "c" (a, b: u32) -> u32 { return a*b } @@ -841,6 +842,7 @@ dot_uvec2 :: proc "c" (a, b: uvec2) -> u32 { return a.x*b.x + a.y*b.y } dot_uvec3 :: proc "c" (a, b: uvec3) -> u32 { return a.x*b.x + a.y*b.y + a.z*b.z } dot_uvec4 :: proc "c" (a, b: uvec4) -> u32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } dot_quat :: proc "c" (a, b: quat) -> f32 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_dquat :: proc "c" (a, b: dquat) -> f64 { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } length :: proc{ length_f32, @@ -1428,112 +1430,6 @@ mat4FromQuat :: proc "c" (q: quat) -> (m: mat4) { return } -quatAxisAngle :: proc "c" (axis: vec3, radians: f32) -> (q: quat) { - t := radians*0.5 - v := normalize(axis) * sin(t) - q.x = v.x - q.y = v.y - q.z = v.z - q.w = cos(t) - return -} -dquatot :: proc "c" (a, b: quat) -> f32 { - return dot(transmute(vec4)a, transmute(vec4)b) -} -quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) { - 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 c/builtin.abs(c) -} - -quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) { - a, b := x, y - cos_angle := dquatot(a, b) - if cos_angle < 0 { - 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 - } - - angle := acos(cos_angle) - sin_angle := sin(angle) - factor_a := sin((1-t) * angle) / sin_angle - factor_b := 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 -} -quatFromMat3 :: proc "c" (m: mat3) -> (q: quat) { - 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 - if four_x_squared_minus_1 > four_biggest_squared_minus_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 - } - if four_z_squared_minus_1 > four_biggest_squared_minus_1 { - four_biggest_squared_minus_1 = four_z_squared_minus_1 - biggest_index = 3 - } - - biggest_val := sqrt(four_biggest_squared_minus_1 + 1) * 0.5 - mult := 0.25 / biggest_val - - q = 1 - switch biggest_index { - case 0: - q.w = biggest_val - q.x = (m[2, 1] - m[1, 2]) * mult - q.y = (m[0, 2] - m[2, 0]) * mult - q.z = (m[1, 0] - m[0, 1]) * mult - case 1: - q.w = (m[2, 1] - m[1, 2]) * mult - q.x = biggest_val - q.y = (m[1, 0] + m[0, 1]) * mult - q.z = (m[0, 2] + m[2, 0]) * mult - case 2: - q.w = (m[0, 2] - m[2, 0]) * mult - q.x = (m[1, 0] + m[0, 1]) * mult - q.y = biggest_val - q.z = (m[2, 1] + m[1, 2]) * mult - case 3: - q.w = (m[1, 0] - m[0, 1]) * mult - q.x = (m[0, 2] + m[2, 0]) * mult - q.y = (m[2, 1] + m[1, 2]) * mult - q.z = biggest_val - } - return -} -quatFromMat4 :: proc "c" (m: mat4) -> (q: quat) { - return quatFromMat3(mat3(m)) -} - -quatMulVec3 :: proc "c" (q: quat, v: vec3) -> vec3 { - xyz := vec3{q.x, q.y, q.z} - t := cross(xyz, v) - return v + q.w*t + cross(xyz, t) -} - - dmat4Perspective :: proc "c" (fovy, aspect, near, far: f64) -> (m: dmat4) { tan_half_fovy := tan(0.5 * fovy) @@ -1652,8 +1548,118 @@ dmat4FromDquat :: proc "c" (q: dquat) -> (m: dmat4) { return } +nlerp :: proc{ + quatNlerp, + dquatNlerp, +} +slerp :: proc{ + quatSlerp, + dquatSlerp, +} +quatAxisAngle :: proc "c" (axis: vec3, radians: f32) -> (q: quat) { + t := radians*0.5 + v := normalize(axis) * sin(t) + q.x = v.x + q.y = v.y + q.z = v.z + q.w = cos(t) + return +} +quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) { + 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 c/builtin.abs(c) +} + +quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) { + a, b := x, y + cos_angle := dot(a, b) + if cos_angle < 0 { + 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 + } + + angle := acos(cos_angle) + sin_angle := sin(angle) + factor_a := sin((1-t) * angle) / sin_angle + factor_b := 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 +} +quatFromMat3 :: proc "c" (m: mat3) -> (q: quat) { + 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 + if four_x_squared_minus_1 > four_biggest_squared_minus_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 + } + if four_z_squared_minus_1 > four_biggest_squared_minus_1 { + four_biggest_squared_minus_1 = four_z_squared_minus_1 + biggest_index = 3 + } + + biggest_val := sqrt(four_biggest_squared_minus_1 + 1) * 0.5 + mult := 0.25 / biggest_val + + q = 1 + switch biggest_index { + case 0: + q.w = biggest_val + q.x = (m[2, 1] - m[1, 2]) * mult + q.y = (m[0, 2] - m[2, 0]) * mult + q.z = (m[1, 0] - m[0, 1]) * mult + case 1: + q.w = (m[2, 1] - m[1, 2]) * mult + q.x = biggest_val + q.y = (m[1, 0] + m[0, 1]) * mult + q.z = (m[0, 2] + m[2, 0]) * mult + case 2: + q.w = (m[0, 2] - m[2, 0]) * mult + q.x = (m[1, 0] + m[0, 1]) * mult + q.y = biggest_val + q.z = (m[2, 1] + m[1, 2]) * mult + case 3: + q.w = (m[1, 0] - m[0, 1]) * mult + q.x = (m[0, 2] + m[2, 0]) * mult + q.y = (m[2, 1] + m[1, 2]) * mult + q.z = biggest_val + } + return +} +quatFromMat4 :: proc "c" (m: mat4) -> (q: quat) { + return quatFromMat3(mat3(m)) +} + +quatMulVec3 :: proc "c" (q: quat, v: vec3) -> vec3 { + xyz := vec3{q.x, q.y, q.z} + t := cross(xyz, v) + return v + q.w*t + cross(xyz, t) +} + dquatAxisAngle :: proc "c" (axis: dvec3, radians: f64) -> (q: dquat) { t := radians*0.5 v := normalize(axis) * sin(t) @@ -1663,9 +1669,6 @@ dquatAxisAngle :: proc "c" (axis: dvec3, radians: f64) -> (q: dquat) { q.w = cos(t) return } -dquatDot :: proc "c" (a, b: dquat) -> f64 { - return dot(transmute(dvec4)a, transmute(dvec4)b) -} dquatNlerp :: proc "c" (a, b: dquat, t: f64) -> (c: dquat) { c.x = a.x + (b.x-a.x)*t c.y = a.y + (b.y-a.y)*t @@ -1676,12 +1679,12 @@ dquatNlerp :: proc "c" (a, b: dquat, t: f64) -> (c: dquat) { dquatSlerp :: proc "c" (x, y: dquat, t: f64) -> (q: dquat) { a, b := x, y - cos_angle := dquatDot(a, b) + cos_angle := dot(a, b) if cos_angle < 0 { b = -b cos_angle = -cos_angle } - if cos_angle > 1 - F32_EPSILON { + 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 From 2718ade2bcdf62371b31b80293c379ca0b9661de Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 14:56:16 +0000 Subject: [PATCH 12/13] Add `core:math/linalg/glsl` to all_main.odin --- examples/all/all_main.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 2351a87f8..92026fe2c 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -29,6 +29,7 @@ import big "core:math/big" import bits "core:math/bits" import fixed "core:math/fixed" import linalg "core:math/linalg" +import glm "core:math/linalg/glsl" import rand "core:math/rand" import mem "core:mem" import ast "core:odin/ast" @@ -84,6 +85,7 @@ _ :: big _ :: bits _ :: fixed _ :: linalg +_ :: glm _ :: rand _ :: mem _ :: ast From 57eedfc4f4f4dd8ebb0b6b017e6a199e50d37f4c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 15:01:31 +0000 Subject: [PATCH 13/13] Fix `lb_emit_array_epi` for matrix types --- src/llvm_backend_utility.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 1359d93c2..ab50b8c1e 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1168,7 +1168,7 @@ lbValue lb_emit_array_ep(lbProcedure *p, lbValue s, lbValue index) { Type *t = s.type; GB_ASSERT_MSG(is_type_pointer(t), "%s", type_to_string(t)); Type *st = base_type(type_deref(t)); - GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st), "%s", type_to_string(st)); + GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); GB_ASSERT_MSG(is_type_integer(core_type(index.type)), "%s", type_to_string(index.type)); LLVMValueRef indices[2] = {}; @@ -1186,7 +1186,7 @@ lbValue lb_emit_array_epi(lbProcedure *p, lbValue s, isize index) { Type *t = s.type; GB_ASSERT(is_type_pointer(t)); Type *st = base_type(type_deref(t)); - GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st), "%s", type_to_string(st)); + GB_ASSERT_MSG(is_type_array(st) || is_type_enumerated_array(st) || is_type_matrix(st), "%s", type_to_string(st)); GB_ASSERT(0 <= index); Type *ptr = base_array_type(st);