mirror of
https://github.com/samber/lo.git
synced 2026-04-22 15:37:14 +08:00
035f1b358a
* 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>
87 lines
3.0 KiB
Go
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)
|
|
}
|