mirror of
https://github.com/odin-lang/Odin.git
synced 2026-05-25 21:28:13 +00:00
More improvements to linalg functions
This commit is contained in:
@@ -7,7 +7,7 @@ import "core:math"
|
||||
@(require_results)
|
||||
to_radians :: proc "contextless" (degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = degrees[i] * RAD_PER_DEG
|
||||
}
|
||||
} else {
|
||||
@@ -19,7 +19,7 @@ to_radians :: proc "contextless" (degrees: $T) -> (out: T) where IS_NUMERIC(ELEM
|
||||
@(require_results)
|
||||
to_degrees :: proc "contextless" (radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = radians[i] * DEG_PER_RAD
|
||||
}
|
||||
} else {
|
||||
@@ -31,7 +31,7 @@ to_degrees :: proc "contextless" (radians: $T) -> (out: T) where IS_NUMERIC(ELEM
|
||||
@(require_results)
|
||||
min_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = builtin.min(a[i], b[i])
|
||||
}
|
||||
} else {
|
||||
@@ -51,7 +51,7 @@ min_single :: proc "contextless" (a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC
|
||||
out = builtin.min(a[0], a[1])
|
||||
} else {
|
||||
out = builtin.min(a[0], a[1])
|
||||
for i in 2..<N {
|
||||
#no_bounds_check for i in 2..<N {
|
||||
out = builtin.min(out, a[i])
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ min :: proc{min_single, min_double, min_triple}
|
||||
@(require_results)
|
||||
max_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = builtin.max(a[i], b[i])
|
||||
}
|
||||
} else {
|
||||
@@ -93,7 +93,7 @@ max_single :: proc "contextless" (a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC
|
||||
out = builtin.max(a[0], a[1], a[2])
|
||||
}else {
|
||||
out = builtin.max(a[0], a[1])
|
||||
for i in 2..<N {
|
||||
#no_bounds_check for i in 2..<N {
|
||||
out = builtin.max(out, a[i])
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ max :: proc{max_single, max_double, max_triple}
|
||||
@(require_results)
|
||||
abs :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = auto_cast builtin.abs(a[i])
|
||||
}
|
||||
} else {
|
||||
@@ -125,7 +125,7 @@ abs :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
sign :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = #force_inline math.sign(a[i])
|
||||
}
|
||||
} else {
|
||||
@@ -137,7 +137,7 @@ sign :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
clamp :: proc "contextless" (x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = builtin.clamp(x[i], a[i], b[i])
|
||||
}
|
||||
} else {
|
||||
@@ -155,7 +155,7 @@ saturate :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
lerp :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = a[i]*(1-t[i]) + b[i]*t[i]
|
||||
}
|
||||
} else {
|
||||
@@ -166,7 +166,7 @@ lerp :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)
|
||||
@(require_results)
|
||||
mix :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = a[i]*(1-t[i]) + b[i]*t[i]
|
||||
}
|
||||
} else {
|
||||
@@ -183,7 +183,7 @@ unlerp :: proc "contextless" (a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
step :: proc "contextless" (e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = x[i] < e[i] ? 0.0 : 1.0
|
||||
}
|
||||
} else {
|
||||
@@ -208,7 +208,7 @@ smootherstep :: proc "contextless" (e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE
|
||||
@(require_results)
|
||||
sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.sqrt(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -220,7 +220,7 @@ sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
inverse_sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = 1.0/math.sqrt(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -232,7 +232,7 @@ inverse_sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(
|
||||
@(require_results)
|
||||
cos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.cos(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -244,7 +244,7 @@ cos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
sin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.sin(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -256,7 +256,7 @@ sin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
tan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.tan(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -268,7 +268,7 @@ tan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
acos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.acos(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -280,7 +280,7 @@ acos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
asin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.asin(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -292,7 +292,7 @@ asin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
atan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.atan(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -303,7 +303,7 @@ atan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
atan2 :: proc "contextless" (y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.atan2(y[i], x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -316,7 +316,7 @@ atan2 :: proc "contextless" (y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T))
|
||||
@(require_results)
|
||||
ln :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.ln(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -329,7 +329,7 @@ ln :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
log2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
INVLN2 :: 1.4426950408889634073599246810018921374266459541529859341354494069
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = INVLN2 * math.ln(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -342,7 +342,7 @@ log2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
log10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
INVLN10 :: 0.4342944819032518276511289189166050822943970058036665661144537831
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = INVLN10 * math.ln(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -354,7 +354,7 @@ log10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
log :: proc "contextless" (x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i])
|
||||
}
|
||||
} else {
|
||||
@@ -366,7 +366,7 @@ log :: proc "contextless" (x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
exp :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.exp(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -378,7 +378,7 @@ exp :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
exp2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.exp(LN2 * x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -390,7 +390,7 @@ exp2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
exp10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.exp(LN10 * x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -402,7 +402,7 @@ exp10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
pow :: proc "contextless" (x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = math.pow(x[i], e[i])
|
||||
}
|
||||
} else {
|
||||
@@ -425,7 +425,7 @@ floor :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
@(require_results)
|
||||
round :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
|
||||
when IS_ARRAY(T) {
|
||||
for i in 0..<len(T) {
|
||||
#no_bounds_check for i in 0..<len(T) {
|
||||
out[i] = #force_inline math.round(x[i])
|
||||
}
|
||||
} else {
|
||||
@@ -486,7 +486,7 @@ is_nan_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) {
|
||||
|
||||
@(require_results)
|
||||
is_nan_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = #force_inline is_nan(x[i])
|
||||
}
|
||||
return
|
||||
@@ -499,7 +499,7 @@ is_inf_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) {
|
||||
|
||||
@(require_results)
|
||||
is_inf_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = #force_inline is_inf(x[i])
|
||||
}
|
||||
return
|
||||
@@ -512,7 +512,7 @@ classify_single :: proc "contextless" (x: $T) -> math.Float_Class where IS_FLOAT
|
||||
|
||||
@(require_results)
|
||||
classify_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = #force_inline classify_single(x[i])
|
||||
}
|
||||
return
|
||||
@@ -532,42 +532,42 @@ classify :: proc{classify_single, classify_array}
|
||||
|
||||
@(require_results)
|
||||
less_than_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = x[i] < y[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@(require_results)
|
||||
less_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = x[i] <= y[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@(require_results)
|
||||
greater_than_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = x[i] > y[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@(require_results)
|
||||
greater_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = x[i] >= y[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@(require_results)
|
||||
equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = x[i] == y[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
@(require_results)
|
||||
not_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
|
||||
for i in 0..<N {
|
||||
#no_bounds_check for i in 0..<N {
|
||||
out[i] = x[i] != y[i]
|
||||
}
|
||||
return
|
||||
@@ -601,7 +601,7 @@ all :: proc "contextless" (x: $A/[$N]bool) -> (out: bool) {
|
||||
@(require_results)
|
||||
not :: proc "contextless" (x: $A/[$N]bool) -> (out: A) {
|
||||
for e, i in x {
|
||||
out[i] = !e
|
||||
#no_bounds_check out[i] = !e
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -46,18 +46,17 @@ scalar_dot :: proc "contextless" (a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T)
|
||||
|
||||
@(require_results)
|
||||
vector_dot :: proc "contextless" (a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check {
|
||||
ab := a * b
|
||||
when N == 1 {
|
||||
return ab.x
|
||||
return a.x*b.x
|
||||
} else when N == 2 {
|
||||
return ab.x + ab.y
|
||||
return a.x*b.x + a.y*b.y
|
||||
} else when N == 3 {
|
||||
return ab.x + ab.y + ab.z
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z
|
||||
} else when N == 4 {
|
||||
return ab.x + ab.y + ab.z + ab.w
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w
|
||||
} else {
|
||||
for elem in ab {
|
||||
c += elem
|
||||
#unroll for _, i in a {
|
||||
c += a[i]*b[i]
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user