package linalg import "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; }