implement floor, ceil and trunc with SIMD

This commit is contained in:
jakubtomsu
2026-04-10 17:10:24 +02:00
parent 47371791b3
commit d5e4e61c1c

View File

@@ -1,6 +1,7 @@
package linalg
import "base:builtin"
import "base:intrinsics"
import "core:math"
@(require_results)
@@ -413,26 +414,12 @@ pow :: proc "contextless" (x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
ceil :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.ceil(x[i])
}
} else {
out = #force_inline math.ceil(x)
}
return
return _from_simd4(T, intrinsics.simd_ceil(_to_simd4(x)))
}
@(require_results)
floor :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.floor(x[i])
}
} else {
out = #force_inline math.floor(x)
}
return
return _from_simd4(T, intrinsics.simd_floor(_to_simd4(x)))
}
@(require_results)
@@ -447,6 +434,11 @@ round :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
@(require_results)
trunc :: proc "contextless" (x: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return _from_simd4(T, intrinsics.simd_trunc(_to_simd4(x)))
}
@(require_results)
fract :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x)
@@ -613,3 +605,46 @@ not :: proc "contextless" (x: $A/[$N]bool) -> (out: A) {
}
return
}
@(require_results)
_to_simd4 :: #force_inline proc "contextless" (a: $T) -> (out: #simd[4]ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) #no_bounds_check {
when IS_ARRAY(T) {
when len(T) == 1 {
_a: [4]ELEM_TYPE(T)
_a.x = a.x
return transmute(#simd[4]ELEM_TYPE(T))_a
} else when len(T) == 2 {
_a: [4]ELEM_TYPE(T)
_a.xy = a
return transmute(#simd[4]ELEM_TYPE(T))_a
} else when len(T) == 3 {
_a: [4]ELEM_TYPE(T)
_a.xyz = a
return transmute(#simd[4]ELEM_TYPE(T))_a
} else {
return transmute(#simd[4]ELEM_TYPE(T))a
}
} else {
_a: [4]ELEM_TYPE(T)
_a.x = a
return transmute(#simd[4]ELEM_TYPE(T))_a
}
}
@(require_results)
_from_simd4 :: #force_inline proc "contextless" ($T: typeid, a: $V/#simd[4]$E) -> T where IS_NUMERIC(ELEM_TYPE(T)) #no_bounds_check {
when IS_ARRAY(T) {
when len(T) == 1 {
return (transmute([4]ELEM_TYPE(T))a).x
} else when len(T) == 2 {
return (transmute([4]ELEM_TYPE(T))a).xy
} else when len(T) == 3 {
return (transmute([4]ELEM_TYPE(T))a).xyz
} else {
return transmute([4]ELEM_TYPE(T))a
}
} else {
return (transmute([4]ELEM_TYPE(T))a).x
}
}