Files
lo/exp/simd/unsafe.go
T
Samuel Berthe 035f1b358a Experiments: adding SIMD helpers (#801)
* feat(exp,simd): adding SumAxB helpers

* feat(exp,simd): adding MeanAxB and ClampAxB helpers

* feat(exp,simd): adding MinAxB and MaxAxB helpers

* refactor(exp,simd): group perf helper category + architecture

* feat(exp,simd): adding ContainsAxB helpers

* perf(exp,simd): cast to unsafe slice once

* feat(exp,simd): call the right SIMD helper based on local architecture

* chore: internal dependency linking

* Update exp/simd/math.go

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* style: fix linter

* style: fix linter

* chore: enable simd in makefile

* chore(ci): add simd package to test runs

* chore(ci): add simd package to test runs only for go 1.26

* fix(simd): fix overflow

* fix(simd): fix overflow and apply the same behavior than lo.Mean

* doc(exp,simd): adding initial doc

* refactor(simd): move intersect_avx2 and intersect_sse code into intersect_avx512

* fix(simd): call SSE fallback instead of lo.Sum for default helpers

* feat(simd): cache simd features on package init to avoid repeated checks

* perf(exp,simd): precompute length + improve code quality

* perf(exp,simd): faster iteration for min/max value

* test(exp,simd): adding benchmarks

* test(exp,simd): adding benchmarks results

* test(exp,simd): adding benchmarks results

* doc(exp,simd): adding warning for overflows in SIMD operations

* feat(exp,simd): adding more dispatch helpers

* feat(exp,simd): adding SumBy variants

* feat(exp,simd): adding MeanBy variants

* fix(exp,simd): faster clamp

* 💄

* doc(exp,simd): adding SumBy + MeanBy

* fix(exp,simd): faster SIMD operations

* chore(ci): enable the benchmarks temporary

* chore(ci): display cpu architecture before running tests

* chore(ci): github actions are hidding some useful stuffs

* chore(ci): no SIMD VM available at Github during the weekend ???

* test(exp,simd): larger epsilon

* oops

* perf(exp,simd): faster iterations

* doc(exp,simd): report last version of benchmarks

* 💄

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-02-21 19:19:36 +01:00

87 lines
3.0 KiB
Go

//go:build go1.26 && goexperiment.simd && amd64
package simd
import "unsafe"
// unsafeSliceInt8 converts a []T (where T ~int8) to []int8 via unsafe operations.
// This helper reduces code duplication and the risk of copy-paste errors.
//
//go:nosplit
func unsafeSliceInt8[T ~int8](collection []T, length uint) []int8 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*int8)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceInt16 converts a []T (where T ~int16) to []int16 via unsafe operations.
//
//go:nosplit
func unsafeSliceInt16[T ~int16](collection []T, length uint) []int16 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*int16)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceInt32 converts a []T (where T ~int32) to []int32 via unsafe operations.
//
//go:nosplit
func unsafeSliceInt32[T ~int32](collection []T, length uint) []int32 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*int32)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceInt64 converts a []T (where T ~int64) to []int64 via unsafe operations.
//
//go:nosplit
func unsafeSliceInt64[T ~int64](collection []T, length uint) []int64 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*int64)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceUint8 converts a []T (where T ~uint8) to []uint8 via unsafe operations.
//
//go:nosplit
func unsafeSliceUint8[T ~uint8](collection []T, length uint) []uint8 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*uint8)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceUint16 converts a []T (where T ~uint16) to []uint16 via unsafe operations.
//
//go:nosplit
func unsafeSliceUint16[T ~uint16](collection []T, length uint) []uint16 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*uint16)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceUint32 converts a []T (where T ~uint32) to []uint32 via unsafe operations.
//
//go:nosplit
func unsafeSliceUint32[T ~uint32](collection []T, length uint) []uint32 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*uint32)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceUint64 converts a []T (where T ~uint64) to []uint64 via unsafe operations.
//
//go:nosplit
func unsafeSliceUint64[T ~uint64](collection []T, length uint) []uint64 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*uint64)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceFloat32 converts a []T (where T ~float32) to []float32 via unsafe operations.
//
//go:nosplit
func unsafeSliceFloat32[T ~float32](collection []T, length uint) []float32 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*float32)(unsafe.Pointer(&collection[0])), length)
}
// unsafeSliceFloat64 converts a []T (where T ~float64) to []float64 via unsafe operations.
//
//go:nosplit
func unsafeSliceFloat64[T ~float64](collection []T, length uint) []float64 {
// bearer:disable go_gosec_unsafe_unsafe
return unsafe.Slice((*float64)(unsafe.Pointer(&collection[0])), length)
}