package linalg import "core:builtin" import "core:math" radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { N :: len(T) when N == 1 { out = a[0] } else when N == 2 { out = builtin.min(a[0], a[1]) } else { out = builtin.min(a[0], a[1]) for i in 2.. T where IS_NUMERIC(ELEM_TYPE(T)) { return min_double(a, min_double(b, c)) } min :: proc{min_single, min_double, min_triple} max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { N :: len(T) when N == 1 { out = a[0] } else when N == 2 { out = builtin.max(a[0], a[1]) } else when N == 3 { out = builtin.max(a[0], a[1], a[3]) }else { out = builtin.max(a[0], a[1]) for i in 2.. T where IS_NUMERIC(ELEM_TYPE(T)) { return max_double(a, max_double(b, c)) } max :: proc{max_single, max_double, max_triple} abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_NUMERIC(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. T where IS_FLOAT(ELEM_TYPE(T)) { return clamp(x, 0.0, 1.0) } lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. T where IS_FLOAT(ELEM_TYPE(T)) { return (x - a) / (b - a) } step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. T where IS_FLOAT(ELEM_TYPE(T)) { t := saturate(unlerp(e0, e1, x)) return t * t * (3.0 - 2.0 * t) } smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { t := saturate(unlerp(e0, e1, x)) return t * t * t * (t * (6*t - 15) + 10) } sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. (out: T) where IS_FLOAT(ELEM_TYPE(T)) { when IS_ARRAY(T) { for i in 0.. T where IS_FLOAT(ELEM_TYPE(T)) { f := #force_inline floor(x) return x - f } mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) { f := #force_inline floor(x / m) return x - f * m } face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { return dot(N_ref, I) < 0 ? N : -N } distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) { return length(p1 - p0) } reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { b := n * (2 * dot(n, i)) return i - b } refract :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) { dv := dot(n, i) k := 1 - eta*eta - (1 - dv*dv) a := i * eta b := n * eta*dv*math.sqrt(k) return (a - b) * E(int(k >= 0)) } is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) { return #force_inline math.is_nan(x) } is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { for i in 0.. bool where IS_FLOAT(T) { return #force_inline math.is_inf(x) } is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) { for i in 0.. math.Float_Class where IS_FLOAT(T) { return #force_inline math.classify(x) } classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) { for i in 0.. (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y } less_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y } greater_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y } greater_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y } equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y } not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y } less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0.. y[i] } return } greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0..= y[i] } return } equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0.. (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) { for i in 0.. (out: bool) { for e in x { if x { return true } } return false } all :: proc(x: $A/[$N]bool) -> (out: bool) { for e in x { if !e { return false } } return true } not :: proc(x: $A/[$N]bool) -> (out: A) { for e, i in x { out[i] = !e } return }