mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.simd] simd: move test generation into Go repo
This pairs with CL 689275 which removes test generation from simdgen
This uses generics and attempts to encode the tests as compactly as
possible.
Some files, *_helpers_test.go, are generated.
Use t.Helper() to get the line number right for a failure.
Adds helper error return values and early exits to only report a
single test failure per operations and vector shape, for the
generated test failures.
Include the entire got and wanted vectors for that failure.
Provide an option to include the input vectors to failures, also
report the type of the test.
Sample failure test output (obtained by intentionally breaking
the "want" value for AndNot):
=== RUN TestAndNot
binary_test.go:214: For int16 vector elements:
binary_test.go:214: got =[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
binary_test.go:214: want=[-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1]
binary_test.go:214: x=[1 -1 0 2 4 8 1024 3 5 7 11 13 3000 5555 7777 11111]
binary_test.go:214: y=[1 -1 0 2 4 8 1024 3 5 7 11 13 3000 5555 7777 11111]
binary_test.go:214: at index 0, got=0, want=-1
binary_test.go:215: For int16 vector elements:
binary_test.go:215: got =[0 0 0 0 0 0 0 0]
binary_test.go:215: want=[-1 -1 -1 -1 -1 -1 -1 -1]
binary_test.go:215: x=[1 -1 0 2 4 8 1024 3]
binary_test.go:215: y=[1 -1 0 2 4 8 1024 3]
binary_test.go:215: at index 0, got=0, want=-1
binary_test.go:216: For int32 vector elements:
binary_test.go:216: got =[0 0 0 0]
binary_test.go:216: want=[-1 -1 -1 -1]
binary_test.go:216: x=[1 -1 0 2]
binary_test.go:216: y=[1 -1 0 2]
binary_test.go:216: at index 0, got=0, want=-1
(etc)
Change-Id: I0f6ee8390ebe7a2333002e9415b4d71527fa3c38
Reviewed-on: https://go-review.googlesource.com/c/go/+/686057
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
6f7a1164e7
commit
88568519b4
18 changed files with 4182 additions and 8242 deletions
464
src/simd/binary_helpers_test.go
Normal file
464
src/simd/binary_helpers_test.go
Normal file
|
|
@ -0,0 +1,464 @@
|
||||||
|
// Code generated by 'go run genfiles.go'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
// This file contains functions testing binary simd methods.
|
||||||
|
// Each function in this file is specialized for a
|
||||||
|
// particular simd type <BaseType><Width>x<Count>.
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testInt8x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt8x16Binary(t *testing.T, f func(_, _ simd.Int8x16) simd.Int8x16, want func(_, _ []int8) []int8) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int8s, n, func(x, y []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x16Slice(x)
|
||||||
|
b := simd.LoadInt8x16Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint8x16Binary(t *testing.T, f func(_, _ simd.Uint8x16) simd.Uint8x16, want func(_, _ []uint8) []uint8) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint8s, n, func(x, y []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x16Slice(x)
|
||||||
|
b := simd.LoadUint8x16Slice(y)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt16x8Binary(t *testing.T, f func(_, _ simd.Int16x8) simd.Int16x8, want func(_, _ []int16) []int16) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int16s, n, func(x, y []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x8Slice(x)
|
||||||
|
b := simd.LoadInt16x8Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint16x8Binary(t *testing.T, f func(_, _ simd.Uint16x8) simd.Uint16x8, want func(_, _ []uint16) []uint16) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint16s, n, func(x, y []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x8Slice(x)
|
||||||
|
b := simd.LoadUint16x8Slice(y)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x4Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt32x4Binary(t *testing.T, f func(_, _ simd.Int32x4) simd.Int32x4, want func(_, _ []int32) []int32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int32s, n, func(x, y []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x4Slice(x)
|
||||||
|
b := simd.LoadInt32x4Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x4Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint32x4Binary(t *testing.T, f func(_, _ simd.Uint32x4) simd.Uint32x4, want func(_, _ []uint32) []uint32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint32s, n, func(x, y []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x4Slice(x)
|
||||||
|
b := simd.LoadUint32x4Slice(y)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x2Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt64x2Binary(t *testing.T, f func(_, _ simd.Int64x2) simd.Int64x2, want func(_, _ []int64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int64s, n, func(x, y []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x2Slice(x)
|
||||||
|
b := simd.LoadInt64x2Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x2Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint64x2Binary(t *testing.T, f func(_, _ simd.Uint64x2) simd.Uint64x2, want func(_, _ []uint64) []uint64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint64s, n, func(x, y []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x2Slice(x)
|
||||||
|
b := simd.LoadUint64x2Slice(y)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x4Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x4Binary(t *testing.T, f func(_, _ simd.Float32x4) simd.Float32x4, want func(_, _ []float32) []float32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float32s, n, func(x, y []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x4Slice(x)
|
||||||
|
b := simd.LoadFloat32x4Slice(y)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x2Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x2Binary(t *testing.T, f func(_, _ simd.Float64x2) simd.Float64x2, want func(_, _ []float64) []float64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float64s, n, func(x, y []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x2Slice(x)
|
||||||
|
b := simd.LoadFloat64x2Slice(y)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x32Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt8x32Binary(t *testing.T, f func(_, _ simd.Int8x32) simd.Int8x32, want func(_, _ []int8) []int8) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int8s, n, func(x, y []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x32Slice(x)
|
||||||
|
b := simd.LoadInt8x32Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x32Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint8x32Binary(t *testing.T, f func(_, _ simd.Uint8x32) simd.Uint8x32, want func(_, _ []uint8) []uint8) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint8s, n, func(x, y []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x32Slice(x)
|
||||||
|
b := simd.LoadUint8x32Slice(y)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt16x16Binary(t *testing.T, f func(_, _ simd.Int16x16) simd.Int16x16, want func(_, _ []int16) []int16) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int16s, n, func(x, y []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x16Slice(x)
|
||||||
|
b := simd.LoadInt16x16Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint16x16Binary(t *testing.T, f func(_, _ simd.Uint16x16) simd.Uint16x16, want func(_, _ []uint16) []uint16) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint16s, n, func(x, y []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x16Slice(x)
|
||||||
|
b := simd.LoadUint16x16Slice(y)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt32x8Binary(t *testing.T, f func(_, _ simd.Int32x8) simd.Int32x8, want func(_, _ []int32) []int32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int32s, n, func(x, y []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x8Slice(x)
|
||||||
|
b := simd.LoadInt32x8Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint32x8Binary(t *testing.T, f func(_, _ simd.Uint32x8) simd.Uint32x8, want func(_, _ []uint32) []uint32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint32s, n, func(x, y []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x8Slice(x)
|
||||||
|
b := simd.LoadUint32x8Slice(y)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x4Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt64x4Binary(t *testing.T, f func(_, _ simd.Int64x4) simd.Int64x4, want func(_, _ []int64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int64s, n, func(x, y []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x4Slice(x)
|
||||||
|
b := simd.LoadInt64x4Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x4Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint64x4Binary(t *testing.T, f func(_, _ simd.Uint64x4) simd.Uint64x4, want func(_, _ []uint64) []uint64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint64s, n, func(x, y []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x4Slice(x)
|
||||||
|
b := simd.LoadUint64x4Slice(y)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x8Binary(t *testing.T, f func(_, _ simd.Float32x8) simd.Float32x8, want func(_, _ []float32) []float32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float32s, n, func(x, y []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x8Slice(x)
|
||||||
|
b := simd.LoadFloat32x8Slice(y)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x4Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x4Binary(t *testing.T, f func(_, _ simd.Float64x4) simd.Float64x4, want func(_, _ []float64) []float64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float64s, n, func(x, y []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x4Slice(x)
|
||||||
|
b := simd.LoadFloat64x4Slice(y)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x64Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt8x64Binary(t *testing.T, f func(_, _ simd.Int8x64) simd.Int8x64, want func(_, _ []int8) []int8) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int8s, n, func(x, y []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x64Slice(x)
|
||||||
|
b := simd.LoadInt8x64Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x64Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint8x64Binary(t *testing.T, f func(_, _ simd.Uint8x64) simd.Uint8x64, want func(_, _ []uint8) []uint8) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint8s, n, func(x, y []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x64Slice(x)
|
||||||
|
b := simd.LoadUint8x64Slice(y)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x32Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt16x32Binary(t *testing.T, f func(_, _ simd.Int16x32) simd.Int16x32, want func(_, _ []int16) []int16) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int16s, n, func(x, y []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x32Slice(x)
|
||||||
|
b := simd.LoadInt16x32Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x32Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint16x32Binary(t *testing.T, f func(_, _ simd.Uint16x32) simd.Uint16x32, want func(_, _ []uint16) []uint16) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint16s, n, func(x, y []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x32Slice(x)
|
||||||
|
b := simd.LoadUint16x32Slice(y)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt32x16Binary(t *testing.T, f func(_, _ simd.Int32x16) simd.Int32x16, want func(_, _ []int32) []int32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int32s, n, func(x, y []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x16Slice(x)
|
||||||
|
b := simd.LoadInt32x16Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint32x16Binary(t *testing.T, f func(_, _ simd.Uint32x16) simd.Uint32x16, want func(_, _ []uint32) []uint32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint32s, n, func(x, y []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x16Slice(x)
|
||||||
|
b := simd.LoadUint32x16Slice(y)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testInt64x8Binary(t *testing.T, f func(_, _ simd.Int64x8) simd.Int64x8, want func(_, _ []int64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int64s, n, func(x, y []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x8Slice(x)
|
||||||
|
b := simd.LoadInt64x8Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testUint64x8Binary(t *testing.T, f func(_, _ simd.Uint64x8) simd.Uint64x8, want func(_, _ []uint64) []uint64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint64s, n, func(x, y []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x8Slice(x)
|
||||||
|
b := simd.LoadUint64x8Slice(y)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x16Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x16Binary(t *testing.T, f func(_, _ simd.Float32x16) simd.Float32x16, want func(_, _ []float32) []float32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float32s, n, func(x, y []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x16Slice(x)
|
||||||
|
b := simd.LoadFloat32x16Slice(y)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x8Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x8Binary(t *testing.T, f func(_, _ simd.Float64x8) simd.Float64x8, want func(_, _ []float64) []float64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float64s, n, func(x, y []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x8Slice(x)
|
||||||
|
b := simd.LoadFloat64x8Slice(y)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
361
src/simd/binary_test.go
Normal file
361
src/simd/binary_test.go
Normal file
|
|
@ -0,0 +1,361 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd && amd64
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAdd(t *testing.T) {
|
||||||
|
testFloat32x4Binary(t, simd.Float32x4.Add, addSlice[float32])
|
||||||
|
testFloat32x8Binary(t, simd.Float32x8.Add, addSlice[float32])
|
||||||
|
testFloat64x2Binary(t, simd.Float64x2.Add, addSlice[float64])
|
||||||
|
testFloat64x4Binary(t, simd.Float64x4.Add, addSlice[float64])
|
||||||
|
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.Add, addSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.Add, addSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.Add, addSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.Add, addSlice[int32])
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.Add, addSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.Add, addSlice[int64])
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.Add, addSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.Add, addSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.Add, addSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.Add, addSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.Add, addSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.Add, addSlice[uint32])
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.Add, addSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.Add, addSlice[uint64])
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.Add, addSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.Add, addSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x16Binary(t, simd.Float32x16.Add, addSlice[float32])
|
||||||
|
testFloat64x8Binary(t, simd.Float64x8.Add, addSlice[float64])
|
||||||
|
testInt8x64Binary(t, simd.Int8x64.Add, addSlice[int8])
|
||||||
|
testInt16x32Binary(t, simd.Int16x32.Add, addSlice[int16])
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.Add, addSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.Add, addSlice[int64])
|
||||||
|
testUint8x64Binary(t, simd.Uint8x64.Add, addSlice[uint8])
|
||||||
|
testUint16x32Binary(t, simd.Uint16x32.Add, addSlice[uint16])
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.Add, addSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.Add, addSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSub(t *testing.T) {
|
||||||
|
testFloat32x4Binary(t, simd.Float32x4.Sub, subSlice[float32])
|
||||||
|
testFloat32x8Binary(t, simd.Float32x8.Sub, subSlice[float32])
|
||||||
|
testFloat64x2Binary(t, simd.Float64x2.Sub, subSlice[float64])
|
||||||
|
testFloat64x4Binary(t, simd.Float64x4.Sub, subSlice[float64])
|
||||||
|
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.Sub, subSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.Sub, subSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.Sub, subSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.Sub, subSlice[int32])
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.Sub, subSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.Sub, subSlice[int64])
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.Sub, subSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.Sub, subSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.Sub, subSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.Sub, subSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.Sub, subSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.Sub, subSlice[uint32])
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.Sub, subSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.Sub, subSlice[uint64])
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.Sub, subSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.Sub, subSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x16Binary(t, simd.Float32x16.Sub, subSlice[float32])
|
||||||
|
testFloat64x8Binary(t, simd.Float64x8.Sub, subSlice[float64])
|
||||||
|
testInt8x64Binary(t, simd.Int8x64.Sub, subSlice[int8])
|
||||||
|
testInt16x32Binary(t, simd.Int16x32.Sub, subSlice[int16])
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.Sub, subSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.Sub, subSlice[int64])
|
||||||
|
testUint8x64Binary(t, simd.Uint8x64.Sub, subSlice[uint8])
|
||||||
|
testUint16x32Binary(t, simd.Uint16x32.Sub, subSlice[uint16])
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.Sub, subSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.Sub, subSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMax(t *testing.T) {
|
||||||
|
// testFloat32x4Binary(t, simd.Float32x4.Max, maxSlice[float32]) // nan is wrong
|
||||||
|
// testFloat32x8Binary(t, simd.Float32x8.Max, maxSlice[float32]) // nan is wrong
|
||||||
|
// testFloat64x2Binary(t, simd.Float64x2.Max, maxSlice[float64]) // nan is wrong
|
||||||
|
// testFloat64x4Binary(t, simd.Float64x4.Max, maxSlice[float64]) // nan is wrong
|
||||||
|
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.Max, maxSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.Max, maxSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.Max, maxSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.Max, maxSlice[int32])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.Max, maxSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.Max, maxSlice[int64])
|
||||||
|
}
|
||||||
|
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.Max, maxSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.Max, maxSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.Max, maxSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.Max, maxSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.Max, maxSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.Max, maxSlice[uint32])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.Max, maxSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.Max, maxSlice[uint64])
|
||||||
|
}
|
||||||
|
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.Max, maxSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.Max, maxSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testFloat32x16Binary(t, simd.Float32x16.Max, maxSlice[float32]) // nan is wrong
|
||||||
|
// testFloat64x8Binary(t, simd.Float64x8.Max, maxSlice[float64]) // nan is wrong
|
||||||
|
testInt8x64Binary(t, simd.Int8x64.Max, maxSlice[int8])
|
||||||
|
testInt16x32Binary(t, simd.Int16x32.Max, maxSlice[int16])
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.Max, maxSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.Max, maxSlice[int64])
|
||||||
|
testUint8x64Binary(t, simd.Uint8x64.Max, maxSlice[uint8])
|
||||||
|
testUint16x32Binary(t, simd.Uint16x32.Max, maxSlice[uint16])
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.Max, maxSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.Max, maxSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMin(t *testing.T) {
|
||||||
|
// testFloat32x4Binary(t, simd.Float32x4.Min, minSlice[float32]) // nan is wrong
|
||||||
|
// testFloat32x8Binary(t, simd.Float32x8.Min, minSlice[float32]) // nan is wrong
|
||||||
|
// testFloat64x2Binary(t, simd.Float64x2.Min, minSlice[float64]) // nan is wrong
|
||||||
|
// testFloat64x4Binary(t, simd.Float64x4.Min, minSlice[float64]) // nan is wrong
|
||||||
|
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.Min, minSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.Min, minSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.Min, minSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.Min, minSlice[int32])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.Min, minSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.Min, minSlice[int64])
|
||||||
|
}
|
||||||
|
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.Min, minSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.Min, minSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.Min, minSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.Min, minSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.Min, minSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.Min, minSlice[uint32])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.Min, minSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.Min, minSlice[uint64])
|
||||||
|
}
|
||||||
|
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.Min, minSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.Min, minSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testFloat32x16Binary(t, simd.Float32x16.Min, minSlice[float32]) // nan is wrong
|
||||||
|
// testFloat64x8Binary(t, simd.Float64x8.Min, minSlice[float64]) // nan is wrong
|
||||||
|
testInt8x64Binary(t, simd.Int8x64.Min, minSlice[int8])
|
||||||
|
testInt16x32Binary(t, simd.Int16x32.Min, minSlice[int16])
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.Min, minSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.Min, minSlice[int64])
|
||||||
|
testUint8x64Binary(t, simd.Uint8x64.Min, minSlice[uint8])
|
||||||
|
testUint16x32Binary(t, simd.Uint16x32.Min, minSlice[uint16])
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.Min, minSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.Min, minSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAnd(t *testing.T) {
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.And, andSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.And, andSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.And, andSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.And, andSlice[int32])
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.And, andSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.And, andSlice[int64])
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.And, andSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.And, andSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.And, andSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.And, andSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.And, andSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.And, andSlice[uint32])
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.And, andSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.And, andSlice[uint64])
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.And, andSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.And, andSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testInt8x64Binary(t, simd.Int8x64.And, andISlice[int8]) // missing
|
||||||
|
// testInt16x32Binary(t, simd.Int16x32.And, andISlice[int16]) // missing
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.And, andSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.And, andSlice[int64])
|
||||||
|
// testUint8x64Binary(t, simd.Uint8x64.And, andISlice[uint8]) // missing
|
||||||
|
// testUint16x32Binary(t, simd.Uint16x32.And, andISlice[uint16]) // missing
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.And, andSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.And, andSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAndNot(t *testing.T) {
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.AndNot, andNotSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.AndNot, andNotSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.AndNot, andNotSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.AndNot, andNotSlice[int32])
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.AndNot, andNotSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.AndNot, andNotSlice[int64])
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.AndNot, andNotSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.AndNot, andNotSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.AndNot, andNotSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.AndNot, andNotSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.AndNot, andNotSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.AndNot, andNotSlice[uint32])
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.AndNot, andNotSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.AndNot, andNotSlice[uint64])
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.AndNot, andNotSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.AndNot, andNotSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testInt8x64Binary(t, simd.Int8x64.AndNot, andNotSlice[int8]) // missing
|
||||||
|
// testInt16x32Binary(t, simd.Int16x32.AndNot, andNotSlice[int16]) // missing
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.AndNot, andNotSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.AndNot, andNotSlice[int64])
|
||||||
|
// testUint8x64Binary(t, simd.Uint8x64.AndNot, andNotSlice[uint8]) // missing
|
||||||
|
// testUint16x32Binary(t, simd.Uint16x32.AndNot, andNotSlice[uint16]) // missing
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.AndNot, andNotSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.AndNot, andNotSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestXor(t *testing.T) {
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.Xor, xorSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.Xor, xorSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.Xor, xorSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.Xor, xorSlice[int32])
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.Xor, xorSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.Xor, xorSlice[int64])
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.Xor, xorSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.Xor, xorSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.Xor, xorSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.Xor, xorSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.Xor, xorSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.Xor, xorSlice[uint32])
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.Xor, xorSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.Xor, xorSlice[uint64])
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.Xor, xorSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.Xor, xorSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testInt8x64Binary(t, simd.Int8x64.Xor, andISlice[int8]) // missing
|
||||||
|
// testInt16x32Binary(t, simd.Int16x32.Xor, andISlice[int16]) // missing
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.Xor, xorSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.Xor, xorSlice[int64])
|
||||||
|
// testUint8x64Binary(t, simd.Uint8x64.Xor, andISlice[uint8]) // missing
|
||||||
|
// testUint16x32Binary(t, simd.Uint16x32.Xor, andISlice[uint16]) // missing
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.Xor, xorSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.Xor, xorSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestOr(t *testing.T) {
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.Or, orSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.Or, orSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.Or, orSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.Or, orSlice[int32])
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.Or, orSlice[int64])
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.Or, orSlice[int64])
|
||||||
|
testInt8x16Binary(t, simd.Int8x16.Or, orSlice[int8])
|
||||||
|
testInt8x32Binary(t, simd.Int8x32.Or, orSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Binary(t, simd.Uint16x16.Or, orSlice[uint16])
|
||||||
|
testUint16x8Binary(t, simd.Uint16x8.Or, orSlice[uint16])
|
||||||
|
testUint32x4Binary(t, simd.Uint32x4.Or, orSlice[uint32])
|
||||||
|
testUint32x8Binary(t, simd.Uint32x8.Or, orSlice[uint32])
|
||||||
|
testUint64x2Binary(t, simd.Uint64x2.Or, orSlice[uint64])
|
||||||
|
testUint64x4Binary(t, simd.Uint64x4.Or, orSlice[uint64])
|
||||||
|
testUint8x16Binary(t, simd.Uint8x16.Or, orSlice[uint8])
|
||||||
|
testUint8x32Binary(t, simd.Uint8x32.Or, orSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testInt8x64Binary(t, simd.Int8x64.Or, andISlice[int8]) // missing
|
||||||
|
// testInt16x32Binary(t, simd.Int16x32.Or, andISlice[int16]) // missing
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.Or, orSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.Or, orSlice[int64])
|
||||||
|
// testUint8x64Binary(t, simd.Uint8x64.Or, andISlice[uint8]) // missing
|
||||||
|
// testUint16x32Binary(t, simd.Uint16x32.Or, andISlice[uint16]) // missing
|
||||||
|
testUint32x16Binary(t, simd.Uint32x16.Or, orSlice[uint32])
|
||||||
|
testUint64x8Binary(t, simd.Uint64x8.Or, orSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMul(t *testing.T) {
|
||||||
|
testFloat32x4Binary(t, simd.Float32x4.Mul, mulSlice[float32])
|
||||||
|
testFloat32x8Binary(t, simd.Float32x8.Mul, mulSlice[float32])
|
||||||
|
testFloat64x2Binary(t, simd.Float64x2.Mul, mulSlice[float64])
|
||||||
|
testFloat64x4Binary(t, simd.Float64x4.Mul, mulSlice[float64])
|
||||||
|
|
||||||
|
testInt16x16Binary(t, simd.Int16x16.MulLow, mulSlice[int16])
|
||||||
|
testInt16x8Binary(t, simd.Int16x8.MulLow, mulSlice[int16])
|
||||||
|
testInt32x4Binary(t, simd.Int32x4.MulLow, mulSlice[int32])
|
||||||
|
testInt32x8Binary(t, simd.Int32x8.MulLow, mulSlice[int32])
|
||||||
|
|
||||||
|
// testInt8x16Binary(t, simd.Int8x16.MulLow, mulSlice[int8]) // nope
|
||||||
|
// testInt8x32Binary(t, simd.Int8x32.MulLow, mulSlice[int8])
|
||||||
|
|
||||||
|
// TODO we should be able to do these, there's no difference between signed/unsigned mulLow
|
||||||
|
// testUint16x16Binary(t, simd.Uint16x16.MulLow, mulSlice[uint16])
|
||||||
|
// testUint16x8Binary(t, simd.Uint16x8.MulLow, mulSlice[uint16])
|
||||||
|
// testUint32x4Binary(t, simd.Uint32x4.MulLow, mulSlice[uint32])
|
||||||
|
// testUint32x8Binary(t, simd.Uint32x8.MulLow, mulSlice[uint32])
|
||||||
|
// testUint64x2Binary(t, simd.Uint64x2.MulLow, mulSlice[uint64])
|
||||||
|
// testUint64x4Binary(t, simd.Uint64x4.MulLow, mulSlice[uint64])
|
||||||
|
|
||||||
|
// testUint8x16Binary(t, simd.Uint8x16.MulLow, mulSlice[uint8]) // nope
|
||||||
|
// testUint8x32Binary(t, simd.Uint8x32.MulLow, mulSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testInt64x2Binary(t, simd.Int64x2.MulLow, mulSlice[int64]) // avx512 only
|
||||||
|
testInt64x4Binary(t, simd.Int64x4.MulLow, mulSlice[int64])
|
||||||
|
|
||||||
|
testFloat32x16Binary(t, simd.Float32x16.Mul, mulSlice[float32])
|
||||||
|
testFloat64x8Binary(t, simd.Float64x8.Mul, mulSlice[float64])
|
||||||
|
|
||||||
|
// testInt8x64Binary(t, simd.Int8x64.MulLow, mulSlice[int8]) // nope
|
||||||
|
testInt16x32Binary(t, simd.Int16x32.MulLow, mulSlice[int16])
|
||||||
|
testInt32x16Binary(t, simd.Int32x16.MulLow, mulSlice[int32])
|
||||||
|
testInt64x8Binary(t, simd.Int64x8.MulLow, mulSlice[int64])
|
||||||
|
// testUint8x64Binary(t, simd.Uint8x64.MulLow, mulSlice[uint8]) // nope
|
||||||
|
|
||||||
|
// TODO signed should do the job
|
||||||
|
// testUint16x32Binary(t, simd.Uint16x32.MulLow, mulSlice[uint16])
|
||||||
|
// testUint32x16Binary(t, simd.Uint32x16.MulLow, mulSlice[uint32])
|
||||||
|
// testUint64x8Binary(t, simd.Uint64x8.MulLow, mulSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiv(t *testing.T) {
|
||||||
|
testFloat32x4Binary(t, simd.Float32x4.Div, divSlice[float32])
|
||||||
|
testFloat32x8Binary(t, simd.Float32x8.Div, divSlice[float32])
|
||||||
|
testFloat64x2Binary(t, simd.Float64x2.Div, divSlice[float64])
|
||||||
|
testFloat64x4Binary(t, simd.Float64x4.Div, divSlice[float64])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x16Binary(t, simd.Float32x16.Div, divSlice[float32])
|
||||||
|
testFloat64x8Binary(t, simd.Float64x8.Div, divSlice[float64])
|
||||||
|
}
|
||||||
|
}
|
||||||
464
src/simd/compare_helpers_test.go
Normal file
464
src/simd/compare_helpers_test.go
Normal file
|
|
@ -0,0 +1,464 @@
|
||||||
|
// Code generated by 'go run genfiles.go'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
// This file contains functions testing simd methods that compare two operands.
|
||||||
|
// Each function in this file is specialized for a
|
||||||
|
// particular simd type <BaseType><Width>x<Count>.
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testInt8x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt8x16Compare(t *testing.T, f func(_, _ simd.Int8x16) simd.Mask8x16, want func(_, _ []int8) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int8s, n, func(x, y []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x16Slice(x)
|
||||||
|
b := simd.LoadInt8x16Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).AsInt8x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint8x16Compare(t *testing.T, f func(_, _ simd.Uint8x16) simd.Mask8x16, want func(_, _ []uint8) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint8s, n, func(x, y []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x16Slice(x)
|
||||||
|
b := simd.LoadUint8x16Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).AsInt8x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt16x8Compare(t *testing.T, f func(_, _ simd.Int16x8) simd.Mask16x8, want func(_, _ []int16) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int16s, n, func(x, y []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x8Slice(x)
|
||||||
|
b := simd.LoadInt16x8Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).AsInt16x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint16x8Compare(t *testing.T, f func(_, _ simd.Uint16x8) simd.Mask16x8, want func(_, _ []uint16) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint16s, n, func(x, y []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x8Slice(x)
|
||||||
|
b := simd.LoadUint16x8Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).AsInt16x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x4Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt32x4Compare(t *testing.T, f func(_, _ simd.Int32x4) simd.Mask32x4, want func(_, _ []int32) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int32s, n, func(x, y []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x4Slice(x)
|
||||||
|
b := simd.LoadInt32x4Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x4Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint32x4Compare(t *testing.T, f func(_, _ simd.Uint32x4) simd.Mask32x4, want func(_, _ []uint32) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint32s, n, func(x, y []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x4Slice(x)
|
||||||
|
b := simd.LoadUint32x4Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x2Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt64x2Compare(t *testing.T, f func(_, _ simd.Int64x2) simd.Mask64x2, want func(_, _ []int64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int64s, n, func(x, y []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x2Slice(x)
|
||||||
|
b := simd.LoadInt64x2Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x2().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x2Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint64x2Compare(t *testing.T, f func(_, _ simd.Uint64x2) simd.Mask64x2, want func(_, _ []uint64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint64s, n, func(x, y []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x2Slice(x)
|
||||||
|
b := simd.LoadUint64x2Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x2().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x4Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testFloat32x4Compare(t *testing.T, f func(_, _ simd.Float32x4) simd.Mask32x4, want func(_, _ []float32) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float32s, n, func(x, y []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x4Slice(x)
|
||||||
|
b := simd.LoadFloat32x4Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x2Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testFloat64x2Compare(t *testing.T, f func(_, _ simd.Float64x2) simd.Mask64x2, want func(_, _ []float64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float64s, n, func(x, y []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x2Slice(x)
|
||||||
|
b := simd.LoadFloat64x2Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x2().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x32Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt8x32Compare(t *testing.T, f func(_, _ simd.Int8x32) simd.Mask8x32, want func(_, _ []int8) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int8s, n, func(x, y []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x32Slice(x)
|
||||||
|
b := simd.LoadInt8x32Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).AsInt8x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x32Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint8x32Compare(t *testing.T, f func(_, _ simd.Uint8x32) simd.Mask8x32, want func(_, _ []uint8) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint8s, n, func(x, y []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x32Slice(x)
|
||||||
|
b := simd.LoadUint8x32Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).AsInt8x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt16x16Compare(t *testing.T, f func(_, _ simd.Int16x16) simd.Mask16x16, want func(_, _ []int16) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int16s, n, func(x, y []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x16Slice(x)
|
||||||
|
b := simd.LoadInt16x16Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).AsInt16x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint16x16Compare(t *testing.T, f func(_, _ simd.Uint16x16) simd.Mask16x16, want func(_, _ []uint16) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint16s, n, func(x, y []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x16Slice(x)
|
||||||
|
b := simd.LoadUint16x16Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).AsInt16x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt32x8Compare(t *testing.T, f func(_, _ simd.Int32x8) simd.Mask32x8, want func(_, _ []int32) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int32s, n, func(x, y []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x8Slice(x)
|
||||||
|
b := simd.LoadInt32x8Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint32x8Compare(t *testing.T, f func(_, _ simd.Uint32x8) simd.Mask32x8, want func(_, _ []uint32) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint32s, n, func(x, y []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x8Slice(x)
|
||||||
|
b := simd.LoadUint32x8Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x4Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt64x4Compare(t *testing.T, f func(_, _ simd.Int64x4) simd.Mask64x4, want func(_, _ []int64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int64s, n, func(x, y []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x4Slice(x)
|
||||||
|
b := simd.LoadInt64x4Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x4Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint64x4Compare(t *testing.T, f func(_, _ simd.Uint64x4) simd.Mask64x4, want func(_, _ []uint64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint64s, n, func(x, y []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x4Slice(x)
|
||||||
|
b := simd.LoadUint64x4Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testFloat32x8Compare(t *testing.T, f func(_, _ simd.Float32x8) simd.Mask32x8, want func(_, _ []float32) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float32s, n, func(x, y []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x8Slice(x)
|
||||||
|
b := simd.LoadFloat32x8Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x4Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testFloat64x4Compare(t *testing.T, f func(_, _ simd.Float64x4) simd.Mask64x4, want func(_, _ []float64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float64s, n, func(x, y []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x4Slice(x)
|
||||||
|
b := simd.LoadFloat64x4Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x64Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt8x64Compare(t *testing.T, f func(_, _ simd.Int8x64) simd.Mask8x64, want func(_, _ []int8) []int64) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int8s, n, func(x, y []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x64Slice(x)
|
||||||
|
b := simd.LoadInt8x64Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).AsInt8x64().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x64Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint8x64Compare(t *testing.T, f func(_, _ simd.Uint8x64) simd.Mask8x64, want func(_, _ []uint8) []int64) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint8s, n, func(x, y []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x64Slice(x)
|
||||||
|
b := simd.LoadUint8x64Slice(y)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b).AsInt8x64().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x32Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt16x32Compare(t *testing.T, f func(_, _ simd.Int16x32) simd.Mask16x32, want func(_, _ []int16) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int16s, n, func(x, y []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x32Slice(x)
|
||||||
|
b := simd.LoadInt16x32Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).AsInt16x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x32Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint16x32Compare(t *testing.T, f func(_, _ simd.Uint16x32) simd.Mask16x32, want func(_, _ []uint16) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint16s, n, func(x, y []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x32Slice(x)
|
||||||
|
b := simd.LoadUint16x32Slice(y)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b).AsInt16x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt32x16Compare(t *testing.T, f func(_, _ simd.Int32x16) simd.Mask32x16, want func(_, _ []int32) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int32s, n, func(x, y []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x16Slice(x)
|
||||||
|
b := simd.LoadInt32x16Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint32x16Compare(t *testing.T, f func(_, _ simd.Uint32x16) simd.Mask32x16, want func(_, _ []uint32) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint32s, n, func(x, y []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x16Slice(x)
|
||||||
|
b := simd.LoadUint32x16Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testInt64x8Compare(t *testing.T, f func(_, _ simd.Int64x8) simd.Mask64x8, want func(_, _ []int64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, int64s, n, func(x, y []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x8Slice(x)
|
||||||
|
b := simd.LoadInt64x8Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testUint64x8Compare(t *testing.T, f func(_, _ simd.Uint64x8) simd.Mask64x8, want func(_, _ []uint64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, uint64s, n, func(x, y []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x8Slice(x)
|
||||||
|
b := simd.LoadUint64x8Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x16Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testFloat32x16Compare(t *testing.T, f func(_, _ simd.Float32x16) simd.Mask32x16, want func(_, _ []float32) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float32s, n, func(x, y []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x16Slice(x)
|
||||||
|
b := simd.LoadFloat32x16Slice(y)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b).AsInt32x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x8Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func testFloat64x8Compare(t *testing.T, f func(_, _ simd.Float64x8) simd.Mask64x8, want func(_, _ []float64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, float64s, n, func(x, y []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x8Slice(x)
|
||||||
|
b := simd.LoadFloat64x8Slice(y)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b).AsInt64x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
|
||||||
|
})
|
||||||
|
}
|
||||||
295
src/simd/compare_test.go
Normal file
295
src/simd/compare_test.go
Normal file
|
|
@ -0,0 +1,295 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd && amd64
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AVX 2 lacks most comparisons, but they can be synthesized
|
||||||
|
// from > and =
|
||||||
|
var comparisonFixed bool = simd.HasAVX512()
|
||||||
|
|
||||||
|
func TestLessMasked(t *testing.T) {
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x4CompareMasked(t, simd.Float32x4.LessMasked, lessSlice[float32])
|
||||||
|
testFloat32x8CompareMasked(t, simd.Float32x8.LessMasked, lessSlice[float32])
|
||||||
|
testFloat64x2CompareMasked(t, simd.Float64x2.LessMasked, lessSlice[float64])
|
||||||
|
testFloat64x4CompareMasked(t, simd.Float64x4.LessMasked, lessSlice[float64])
|
||||||
|
|
||||||
|
testInt16x16CompareMasked(t, simd.Int16x16.LessMasked, lessSlice[int16])
|
||||||
|
testInt16x8CompareMasked(t, simd.Int16x8.LessMasked, lessSlice[int16])
|
||||||
|
testInt32x4CompareMasked(t, simd.Int32x4.LessMasked, lessSlice[int32])
|
||||||
|
testInt32x8CompareMasked(t, simd.Int32x8.LessMasked, lessSlice[int32])
|
||||||
|
testInt64x2CompareMasked(t, simd.Int64x2.LessMasked, lessSlice[int64])
|
||||||
|
testInt64x4CompareMasked(t, simd.Int64x4.LessMasked, lessSlice[int64])
|
||||||
|
testInt8x16CompareMasked(t, simd.Int8x16.LessMasked, lessSlice[int8])
|
||||||
|
testInt8x32CompareMasked(t, simd.Int8x32.LessMasked, lessSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16CompareMasked(t, simd.Uint16x16.LessMasked, lessSlice[uint16])
|
||||||
|
testUint16x8CompareMasked(t, simd.Uint16x8.LessMasked, lessSlice[uint16])
|
||||||
|
testUint32x4CompareMasked(t, simd.Uint32x4.LessMasked, lessSlice[uint32])
|
||||||
|
testUint32x8CompareMasked(t, simd.Uint32x8.LessMasked, lessSlice[uint32])
|
||||||
|
testUint64x2CompareMasked(t, simd.Uint64x2.LessMasked, lessSlice[uint64])
|
||||||
|
testUint64x4CompareMasked(t, simd.Uint64x4.LessMasked, lessSlice[uint64])
|
||||||
|
testUint8x16CompareMasked(t, simd.Uint8x16.LessMasked, lessSlice[uint8])
|
||||||
|
testUint8x32CompareMasked(t, simd.Uint8x32.LessMasked, lessSlice[uint8])
|
||||||
|
|
||||||
|
testFloat32x16CompareMasked(t, simd.Float32x16.LessMasked, lessSlice[float32])
|
||||||
|
testFloat64x8CompareMasked(t, simd.Float64x8.LessMasked, lessSlice[float64])
|
||||||
|
testInt8x64CompareMasked(t, simd.Int8x64.LessMasked, lessSlice[int8])
|
||||||
|
testInt16x32CompareMasked(t, simd.Int16x32.LessMasked, lessSlice[int16])
|
||||||
|
testInt32x16CompareMasked(t, simd.Int32x16.LessMasked, lessSlice[int32])
|
||||||
|
testInt64x8CompareMasked(t, simd.Int64x8.LessMasked, lessSlice[int64])
|
||||||
|
testUint8x64CompareMasked(t, simd.Uint8x64.LessMasked, lessSlice[uint8])
|
||||||
|
testUint16x32CompareMasked(t, simd.Uint16x32.LessMasked, lessSlice[uint16])
|
||||||
|
testUint32x16CompareMasked(t, simd.Uint32x16.LessMasked, lessSlice[uint32])
|
||||||
|
testUint64x8CompareMasked(t, simd.Uint64x8.LessMasked, lessSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLess(t *testing.T) {
|
||||||
|
testFloat32x4Compare(t, simd.Float32x4.Less, lessSlice[float32])
|
||||||
|
testFloat32x8Compare(t, simd.Float32x8.Less, lessSlice[float32])
|
||||||
|
testFloat64x2Compare(t, simd.Float64x2.Less, lessSlice[float64])
|
||||||
|
testFloat64x4Compare(t, simd.Float64x4.Less, lessSlice[float64])
|
||||||
|
|
||||||
|
if comparisonFixed {
|
||||||
|
testInt16x16Compare(t, simd.Int16x16.Less, lessSlice[int16])
|
||||||
|
testInt16x8Compare(t, simd.Int16x8.Less, lessSlice[int16])
|
||||||
|
testInt32x4Compare(t, simd.Int32x4.Less, lessSlice[int32])
|
||||||
|
testInt32x8Compare(t, simd.Int32x8.Less, lessSlice[int32])
|
||||||
|
testInt64x2Compare(t, simd.Int64x2.Less, lessSlice[int64])
|
||||||
|
testInt64x4Compare(t, simd.Int64x4.Less, lessSlice[int64])
|
||||||
|
testInt8x16Compare(t, simd.Int8x16.Less, lessSlice[int8])
|
||||||
|
testInt8x32Compare(t, simd.Int8x32.Less, lessSlice[int8])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testUint16x16Compare(t, simd.Uint16x16.Less, lessSlice[uint16])
|
||||||
|
testUint16x8Compare(t, simd.Uint16x8.Less, lessSlice[uint16])
|
||||||
|
testUint32x4Compare(t, simd.Uint32x4.Less, lessSlice[uint32])
|
||||||
|
testUint32x8Compare(t, simd.Uint32x8.Less, lessSlice[uint32])
|
||||||
|
testUint64x2Compare(t, simd.Uint64x2.Less, lessSlice[uint64])
|
||||||
|
testUint64x4Compare(t, simd.Uint64x4.Less, lessSlice[uint64])
|
||||||
|
testUint8x16Compare(t, simd.Uint8x16.Less, lessSlice[uint8])
|
||||||
|
testUint8x32Compare(t, simd.Uint8x32.Less, lessSlice[uint8])
|
||||||
|
|
||||||
|
testFloat32x16Compare(t, simd.Float32x16.Less, lessSlice[float32])
|
||||||
|
testFloat64x8Compare(t, simd.Float64x8.Less, lessSlice[float64])
|
||||||
|
testInt8x64Compare(t, simd.Int8x64.Less, lessSlice[int8])
|
||||||
|
testInt16x32Compare(t, simd.Int16x32.Less, lessSlice[int16])
|
||||||
|
testInt32x16Compare(t, simd.Int32x16.Less, lessSlice[int32])
|
||||||
|
testInt64x8Compare(t, simd.Int64x8.Less, lessSlice[int64])
|
||||||
|
testUint8x64Compare(t, simd.Uint8x64.Less, lessSlice[uint8])
|
||||||
|
testUint16x32Compare(t, simd.Uint16x32.Less, lessSlice[uint16])
|
||||||
|
testUint32x16Compare(t, simd.Uint32x16.Less, lessSlice[uint32])
|
||||||
|
testUint64x8Compare(t, simd.Uint64x8.Less, lessSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLessEqual(t *testing.T) {
|
||||||
|
testFloat32x4Compare(t, simd.Float32x4.LessEqual, lessEqualSlice[float32])
|
||||||
|
testFloat32x8Compare(t, simd.Float32x8.LessEqual, lessEqualSlice[float32])
|
||||||
|
testFloat64x2Compare(t, simd.Float64x2.LessEqual, lessEqualSlice[float64])
|
||||||
|
testFloat64x4Compare(t, simd.Float64x4.LessEqual, lessEqualSlice[float64])
|
||||||
|
|
||||||
|
if comparisonFixed {
|
||||||
|
testInt16x16Compare(t, simd.Int16x16.LessEqual, lessEqualSlice[int16])
|
||||||
|
testInt16x8Compare(t, simd.Int16x8.LessEqual, lessEqualSlice[int16])
|
||||||
|
testInt32x4Compare(t, simd.Int32x4.LessEqual, lessEqualSlice[int32])
|
||||||
|
testInt32x8Compare(t, simd.Int32x8.LessEqual, lessEqualSlice[int32])
|
||||||
|
testInt64x2Compare(t, simd.Int64x2.LessEqual, lessEqualSlice[int64])
|
||||||
|
testInt64x4Compare(t, simd.Int64x4.LessEqual, lessEqualSlice[int64])
|
||||||
|
testInt8x16Compare(t, simd.Int8x16.LessEqual, lessEqualSlice[int8])
|
||||||
|
testInt8x32Compare(t, simd.Int8x32.LessEqual, lessEqualSlice[int8])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testUint16x16Compare(t, simd.Uint16x16.LessEqual, lessEqualSlice[uint16])
|
||||||
|
testUint16x8Compare(t, simd.Uint16x8.LessEqual, lessEqualSlice[uint16])
|
||||||
|
testUint32x4Compare(t, simd.Uint32x4.LessEqual, lessEqualSlice[uint32])
|
||||||
|
testUint32x8Compare(t, simd.Uint32x8.LessEqual, lessEqualSlice[uint32])
|
||||||
|
testUint64x2Compare(t, simd.Uint64x2.LessEqual, lessEqualSlice[uint64])
|
||||||
|
testUint64x4Compare(t, simd.Uint64x4.LessEqual, lessEqualSlice[uint64])
|
||||||
|
testUint8x16Compare(t, simd.Uint8x16.LessEqual, lessEqualSlice[uint8])
|
||||||
|
testUint8x32Compare(t, simd.Uint8x32.LessEqual, lessEqualSlice[uint8])
|
||||||
|
|
||||||
|
testFloat32x16Compare(t, simd.Float32x16.LessEqual, lessEqualSlice[float32])
|
||||||
|
testFloat64x8Compare(t, simd.Float64x8.LessEqual, lessEqualSlice[float64])
|
||||||
|
testInt8x64Compare(t, simd.Int8x64.LessEqual, lessEqualSlice[int8])
|
||||||
|
testInt16x32Compare(t, simd.Int16x32.LessEqual, lessEqualSlice[int16])
|
||||||
|
testInt32x16Compare(t, simd.Int32x16.LessEqual, lessEqualSlice[int32])
|
||||||
|
testInt64x8Compare(t, simd.Int64x8.LessEqual, lessEqualSlice[int64])
|
||||||
|
testUint8x64Compare(t, simd.Uint8x64.LessEqual, lessEqualSlice[uint8])
|
||||||
|
testUint16x32Compare(t, simd.Uint16x32.LessEqual, lessEqualSlice[uint16])
|
||||||
|
testUint32x16Compare(t, simd.Uint32x16.LessEqual, lessEqualSlice[uint32])
|
||||||
|
testUint64x8Compare(t, simd.Uint64x8.LessEqual, lessEqualSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGreater(t *testing.T) {
|
||||||
|
testFloat32x4Compare(t, simd.Float32x4.Greater, greaterSlice[float32])
|
||||||
|
testFloat32x8Compare(t, simd.Float32x8.Greater, greaterSlice[float32])
|
||||||
|
testFloat64x2Compare(t, simd.Float64x2.Greater, greaterSlice[float64])
|
||||||
|
testFloat64x4Compare(t, simd.Float64x4.Greater, greaterSlice[float64])
|
||||||
|
|
||||||
|
testInt16x16Compare(t, simd.Int16x16.Greater, greaterSlice[int16])
|
||||||
|
testInt16x8Compare(t, simd.Int16x8.Greater, greaterSlice[int16])
|
||||||
|
testInt32x4Compare(t, simd.Int32x4.Greater, greaterSlice[int32])
|
||||||
|
testInt32x8Compare(t, simd.Int32x8.Greater, greaterSlice[int32])
|
||||||
|
|
||||||
|
testInt64x2Compare(t, simd.Int64x2.Greater, greaterSlice[int64])
|
||||||
|
testInt64x4Compare(t, simd.Int64x4.Greater, greaterSlice[int64])
|
||||||
|
testInt8x16Compare(t, simd.Int8x16.Greater, greaterSlice[int8])
|
||||||
|
testInt8x32Compare(t, simd.Int8x32.Greater, greaterSlice[int8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testUint16x16Compare(t, simd.Uint16x16.Greater, greaterSlice[uint16])
|
||||||
|
testUint16x8Compare(t, simd.Uint16x8.Greater, greaterSlice[uint16])
|
||||||
|
testUint32x4Compare(t, simd.Uint32x4.Greater, greaterSlice[uint32])
|
||||||
|
testUint32x8Compare(t, simd.Uint32x8.Greater, greaterSlice[uint32])
|
||||||
|
|
||||||
|
testUint64x2Compare(t, simd.Uint64x2.Greater, greaterSlice[uint64])
|
||||||
|
testUint64x4Compare(t, simd.Uint64x4.Greater, greaterSlice[uint64])
|
||||||
|
testUint8x16Compare(t, simd.Uint8x16.Greater, greaterSlice[uint8])
|
||||||
|
testUint8x32Compare(t, simd.Uint8x32.Greater, greaterSlice[uint8])
|
||||||
|
|
||||||
|
testFloat32x16Compare(t, simd.Float32x16.Greater, greaterSlice[float32])
|
||||||
|
testFloat64x8Compare(t, simd.Float64x8.Greater, greaterSlice[float64])
|
||||||
|
testInt8x64Compare(t, simd.Int8x64.Greater, greaterSlice[int8])
|
||||||
|
testInt16x32Compare(t, simd.Int16x32.Greater, greaterSlice[int16])
|
||||||
|
testInt32x16Compare(t, simd.Int32x16.Greater, greaterSlice[int32])
|
||||||
|
testInt64x8Compare(t, simd.Int64x8.Greater, greaterSlice[int64])
|
||||||
|
testUint8x64Compare(t, simd.Uint8x64.Greater, greaterSlice[uint8])
|
||||||
|
testUint16x32Compare(t, simd.Uint16x32.Greater, greaterSlice[uint16])
|
||||||
|
testUint32x16Compare(t, simd.Uint32x16.Greater, greaterSlice[uint32])
|
||||||
|
testUint64x8Compare(t, simd.Uint64x8.Greater, greaterSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGreaterEqual(t *testing.T) {
|
||||||
|
testFloat32x4Compare(t, simd.Float32x4.GreaterEqual, greaterEqualSlice[float32])
|
||||||
|
testFloat32x8Compare(t, simd.Float32x8.GreaterEqual, greaterEqualSlice[float32])
|
||||||
|
testFloat64x2Compare(t, simd.Float64x2.GreaterEqual, greaterEqualSlice[float64])
|
||||||
|
testFloat64x4Compare(t, simd.Float64x4.GreaterEqual, greaterEqualSlice[float64])
|
||||||
|
|
||||||
|
if comparisonFixed {
|
||||||
|
testInt16x16Compare(t, simd.Int16x16.GreaterEqual, greaterEqualSlice[int16])
|
||||||
|
testInt16x8Compare(t, simd.Int16x8.GreaterEqual, greaterEqualSlice[int16])
|
||||||
|
testInt32x4Compare(t, simd.Int32x4.GreaterEqual, greaterEqualSlice[int32])
|
||||||
|
testInt32x8Compare(t, simd.Int32x8.GreaterEqual, greaterEqualSlice[int32])
|
||||||
|
testInt64x2Compare(t, simd.Int64x2.GreaterEqual, greaterEqualSlice[int64])
|
||||||
|
testInt64x4Compare(t, simd.Int64x4.GreaterEqual, greaterEqualSlice[int64])
|
||||||
|
testInt8x16Compare(t, simd.Int8x16.GreaterEqual, greaterEqualSlice[int8])
|
||||||
|
testInt8x32Compare(t, simd.Int8x32.GreaterEqual, greaterEqualSlice[int8])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testUint16x16Compare(t, simd.Uint16x16.GreaterEqual, greaterEqualSlice[uint16])
|
||||||
|
testUint16x8Compare(t, simd.Uint16x8.GreaterEqual, greaterEqualSlice[uint16])
|
||||||
|
testUint32x4Compare(t, simd.Uint32x4.GreaterEqual, greaterEqualSlice[uint32])
|
||||||
|
testUint32x8Compare(t, simd.Uint32x8.GreaterEqual, greaterEqualSlice[uint32])
|
||||||
|
testUint64x2Compare(t, simd.Uint64x2.GreaterEqual, greaterEqualSlice[uint64])
|
||||||
|
testUint64x4Compare(t, simd.Uint64x4.GreaterEqual, greaterEqualSlice[uint64])
|
||||||
|
testUint8x16Compare(t, simd.Uint8x16.GreaterEqual, greaterEqualSlice[uint8])
|
||||||
|
testUint8x32Compare(t, simd.Uint8x32.GreaterEqual, greaterEqualSlice[uint8])
|
||||||
|
|
||||||
|
testFloat32x16Compare(t, simd.Float32x16.GreaterEqual, greaterEqualSlice[float32])
|
||||||
|
testFloat64x8Compare(t, simd.Float64x8.GreaterEqual, greaterEqualSlice[float64])
|
||||||
|
testInt8x64Compare(t, simd.Int8x64.GreaterEqual, greaterEqualSlice[int8])
|
||||||
|
testInt16x32Compare(t, simd.Int16x32.GreaterEqual, greaterEqualSlice[int16])
|
||||||
|
testInt32x16Compare(t, simd.Int32x16.GreaterEqual, greaterEqualSlice[int32])
|
||||||
|
testInt64x8Compare(t, simd.Int64x8.GreaterEqual, greaterEqualSlice[int64])
|
||||||
|
testUint8x64Compare(t, simd.Uint8x64.GreaterEqual, greaterEqualSlice[uint8])
|
||||||
|
testUint16x32Compare(t, simd.Uint16x32.GreaterEqual, greaterEqualSlice[uint16])
|
||||||
|
testUint32x16Compare(t, simd.Uint32x16.GreaterEqual, greaterEqualSlice[uint32])
|
||||||
|
testUint64x8Compare(t, simd.Uint64x8.GreaterEqual, greaterEqualSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEqual(t *testing.T) {
|
||||||
|
testFloat32x4Compare(t, simd.Float32x4.Equal, equalSlice[float32])
|
||||||
|
testFloat32x8Compare(t, simd.Float32x8.Equal, equalSlice[float32])
|
||||||
|
testFloat64x2Compare(t, simd.Float64x2.Equal, equalSlice[float64])
|
||||||
|
testFloat64x4Compare(t, simd.Float64x4.Equal, equalSlice[float64])
|
||||||
|
|
||||||
|
testInt16x16Compare(t, simd.Int16x16.Equal, equalSlice[int16])
|
||||||
|
testInt16x8Compare(t, simd.Int16x8.Equal, equalSlice[int16])
|
||||||
|
testInt32x4Compare(t, simd.Int32x4.Equal, equalSlice[int32])
|
||||||
|
testInt32x8Compare(t, simd.Int32x8.Equal, equalSlice[int32])
|
||||||
|
testInt64x2Compare(t, simd.Int64x2.Equal, equalSlice[int64])
|
||||||
|
testInt64x4Compare(t, simd.Int64x4.Equal, equalSlice[int64])
|
||||||
|
testInt8x16Compare(t, simd.Int8x16.Equal, equalSlice[int8])
|
||||||
|
testInt8x32Compare(t, simd.Int8x32.Equal, equalSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Compare(t, simd.Uint16x16.Equal, equalSlice[uint16])
|
||||||
|
testUint16x8Compare(t, simd.Uint16x8.Equal, equalSlice[uint16])
|
||||||
|
testUint32x4Compare(t, simd.Uint32x4.Equal, equalSlice[uint32])
|
||||||
|
testUint32x8Compare(t, simd.Uint32x8.Equal, equalSlice[uint32])
|
||||||
|
testUint64x2Compare(t, simd.Uint64x2.Equal, equalSlice[uint64])
|
||||||
|
testUint64x4Compare(t, simd.Uint64x4.Equal, equalSlice[uint64])
|
||||||
|
testUint8x16Compare(t, simd.Uint8x16.Equal, equalSlice[uint8])
|
||||||
|
testUint8x32Compare(t, simd.Uint8x32.Equal, equalSlice[uint8])
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x16Compare(t, simd.Float32x16.Equal, equalSlice[float32])
|
||||||
|
testFloat64x8Compare(t, simd.Float64x8.Equal, equalSlice[float64])
|
||||||
|
testInt8x64Compare(t, simd.Int8x64.Equal, equalSlice[int8])
|
||||||
|
testInt16x32Compare(t, simd.Int16x32.Equal, equalSlice[int16])
|
||||||
|
testInt32x16Compare(t, simd.Int32x16.Equal, equalSlice[int32])
|
||||||
|
testInt64x8Compare(t, simd.Int64x8.Equal, equalSlice[int64])
|
||||||
|
testUint8x64Compare(t, simd.Uint8x64.Equal, equalSlice[uint8])
|
||||||
|
testUint16x32Compare(t, simd.Uint16x32.Equal, equalSlice[uint16])
|
||||||
|
testUint32x16Compare(t, simd.Uint32x16.Equal, equalSlice[uint32])
|
||||||
|
testUint64x8Compare(t, simd.Uint64x8.Equal, equalSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNotEqual(t *testing.T) {
|
||||||
|
testFloat32x4Compare(t, simd.Float32x4.NotEqual, notEqualSlice[float32])
|
||||||
|
testFloat32x8Compare(t, simd.Float32x8.NotEqual, notEqualSlice[float32])
|
||||||
|
testFloat64x2Compare(t, simd.Float64x2.NotEqual, notEqualSlice[float64])
|
||||||
|
testFloat64x4Compare(t, simd.Float64x4.NotEqual, notEqualSlice[float64])
|
||||||
|
|
||||||
|
if comparisonFixed {
|
||||||
|
testInt16x16Compare(t, simd.Int16x16.NotEqual, notEqualSlice[int16])
|
||||||
|
testInt16x8Compare(t, simd.Int16x8.NotEqual, notEqualSlice[int16])
|
||||||
|
testInt32x4Compare(t, simd.Int32x4.NotEqual, notEqualSlice[int32])
|
||||||
|
testInt32x8Compare(t, simd.Int32x8.NotEqual, notEqualSlice[int32])
|
||||||
|
testInt64x2Compare(t, simd.Int64x2.NotEqual, notEqualSlice[int64])
|
||||||
|
testInt64x4Compare(t, simd.Int64x4.NotEqual, notEqualSlice[int64])
|
||||||
|
testInt8x16Compare(t, simd.Int8x16.NotEqual, notEqualSlice[int8])
|
||||||
|
testInt8x32Compare(t, simd.Int8x32.NotEqual, notEqualSlice[int8])
|
||||||
|
|
||||||
|
testUint16x16Compare(t, simd.Uint16x16.NotEqual, notEqualSlice[uint16])
|
||||||
|
testUint16x8Compare(t, simd.Uint16x8.NotEqual, notEqualSlice[uint16])
|
||||||
|
testUint32x4Compare(t, simd.Uint32x4.NotEqual, notEqualSlice[uint32])
|
||||||
|
testUint32x8Compare(t, simd.Uint32x8.NotEqual, notEqualSlice[uint32])
|
||||||
|
testUint64x2Compare(t, simd.Uint64x2.NotEqual, notEqualSlice[uint64])
|
||||||
|
testUint64x4Compare(t, simd.Uint64x4.NotEqual, notEqualSlice[uint64])
|
||||||
|
testUint8x16Compare(t, simd.Uint8x16.NotEqual, notEqualSlice[uint8])
|
||||||
|
testUint8x32Compare(t, simd.Uint8x32.NotEqual, notEqualSlice[uint8])
|
||||||
|
}
|
||||||
|
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x16Compare(t, simd.Float32x16.NotEqual, notEqualSlice[float32])
|
||||||
|
testFloat64x8Compare(t, simd.Float64x8.NotEqual, notEqualSlice[float64])
|
||||||
|
testInt8x64Compare(t, simd.Int8x64.NotEqual, notEqualSlice[int8])
|
||||||
|
testInt16x32Compare(t, simd.Int16x32.NotEqual, notEqualSlice[int16])
|
||||||
|
testInt32x16Compare(t, simd.Int32x16.NotEqual, notEqualSlice[int32])
|
||||||
|
testInt64x8Compare(t, simd.Int64x8.NotEqual, notEqualSlice[int64])
|
||||||
|
testUint8x64Compare(t, simd.Uint8x64.NotEqual, notEqualSlice[uint8])
|
||||||
|
testUint16x32Compare(t, simd.Uint16x32.NotEqual, notEqualSlice[uint16])
|
||||||
|
testUint32x16Compare(t, simd.Uint32x16.NotEqual, notEqualSlice[uint32])
|
||||||
|
testUint64x8Compare(t, simd.Uint64x8.NotEqual, notEqualSlice[uint64])
|
||||||
|
}
|
||||||
|
}
|
||||||
734
src/simd/comparemasked_helpers_test.go
Normal file
734
src/simd/comparemasked_helpers_test.go
Normal file
|
|
@ -0,0 +1,734 @@
|
||||||
|
// Code generated by 'go run genfiles.go'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
// This file contains functions testing simd methods that compare two operands under a mask.
|
||||||
|
// Each function in this file is specialized for a
|
||||||
|
// particular simd type <BaseType><Width>x<Count>.
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testInt8x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt8x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int8x16, m simd.Mask8x16) simd.Mask8x16,
|
||||||
|
want func(_, _ []int8) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int8s, n, func(x, y []int8, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x16Slice(x)
|
||||||
|
b := simd.LoadInt8x16Slice(y)
|
||||||
|
k := simd.LoadInt8x16Slice(toVect[int8](m)).AsMask8x16()
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, k).AsInt8x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint8x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint8x16, m simd.Mask8x16) simd.Mask8x16,
|
||||||
|
want func(_, _ []uint8) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint8s, n, func(x, y []uint8, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x16Slice(x)
|
||||||
|
b := simd.LoadUint8x16Slice(y)
|
||||||
|
k := simd.LoadInt8x16Slice(toVect[int8](m)).AsMask8x16()
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, k).AsInt8x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt16x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int16x8, m simd.Mask16x8) simd.Mask16x8,
|
||||||
|
want func(_, _ []int16) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int16s, n, func(x, y []int16, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x8Slice(x)
|
||||||
|
b := simd.LoadInt16x8Slice(y)
|
||||||
|
k := simd.LoadInt16x8Slice(toVect[int16](m)).AsMask16x8()
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, k).AsInt16x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint16x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint16x8, m simd.Mask16x8) simd.Mask16x8,
|
||||||
|
want func(_, _ []uint16) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint16s, n, func(x, y []uint16, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x8Slice(x)
|
||||||
|
b := simd.LoadUint16x8Slice(y)
|
||||||
|
k := simd.LoadInt16x8Slice(toVect[int16](m)).AsMask16x8()
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, k).AsInt16x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt32x4CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int32x4, m simd.Mask32x4) simd.Mask32x4,
|
||||||
|
want func(_, _ []int32) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int32s, n, func(x, y []int32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x4Slice(x)
|
||||||
|
b := simd.LoadInt32x4Slice(y)
|
||||||
|
k := simd.LoadInt32x4Slice(toVect[int32](m)).AsMask32x4()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint32x4CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint32x4, m simd.Mask32x4) simd.Mask32x4,
|
||||||
|
want func(_, _ []uint32) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint32s, n, func(x, y []uint32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x4Slice(x)
|
||||||
|
b := simd.LoadUint32x4Slice(y)
|
||||||
|
k := simd.LoadInt32x4Slice(toVect[int32](m)).AsMask32x4()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x2CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt64x2CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int64x2, m simd.Mask64x2) simd.Mask64x2,
|
||||||
|
want func(_, _ []int64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int64s, n, func(x, y []int64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x2Slice(x)
|
||||||
|
b := simd.LoadInt64x2Slice(y)
|
||||||
|
k := simd.LoadInt64x2Slice(toVect[int64](m)).AsMask64x2()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x2().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x2CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint64x2CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint64x2, m simd.Mask64x2) simd.Mask64x2,
|
||||||
|
want func(_, _ []uint64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint64s, n, func(x, y []uint64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x2Slice(x)
|
||||||
|
b := simd.LoadUint64x2Slice(y)
|
||||||
|
k := simd.LoadInt64x2Slice(toVect[int64](m)).AsMask64x2()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x2().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testFloat32x4CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Float32x4, m simd.Mask32x4) simd.Mask32x4,
|
||||||
|
want func(_, _ []float32) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, float32s, n, func(x, y []float32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x4Slice(x)
|
||||||
|
b := simd.LoadFloat32x4Slice(y)
|
||||||
|
k := simd.LoadInt32x4Slice(toVect[int32](m)).AsMask32x4()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x2CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testFloat64x2CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Float64x2, m simd.Mask64x2) simd.Mask64x2,
|
||||||
|
want func(_, _ []float64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, float64s, n, func(x, y []float64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x2Slice(x)
|
||||||
|
b := simd.LoadFloat64x2Slice(y)
|
||||||
|
k := simd.LoadInt64x2Slice(toVect[int64](m)).AsMask64x2()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x2().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt8x32CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int8x32, m simd.Mask8x32) simd.Mask8x32,
|
||||||
|
want func(_, _ []int8) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int8s, n, func(x, y []int8, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x32Slice(x)
|
||||||
|
b := simd.LoadInt8x32Slice(y)
|
||||||
|
k := simd.LoadInt8x32Slice(toVect[int8](m)).AsMask8x32()
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, k).AsInt8x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint8x32CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint8x32, m simd.Mask8x32) simd.Mask8x32,
|
||||||
|
want func(_, _ []uint8) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint8s, n, func(x, y []uint8, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x32Slice(x)
|
||||||
|
b := simd.LoadUint8x32Slice(y)
|
||||||
|
k := simd.LoadInt8x32Slice(toVect[int8](m)).AsMask8x32()
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, k).AsInt8x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt16x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int16x16, m simd.Mask16x16) simd.Mask16x16,
|
||||||
|
want func(_, _ []int16) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int16s, n, func(x, y []int16, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x16Slice(x)
|
||||||
|
b := simd.LoadInt16x16Slice(y)
|
||||||
|
k := simd.LoadInt16x16Slice(toVect[int16](m)).AsMask16x16()
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, k).AsInt16x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint16x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint16x16, m simd.Mask16x16) simd.Mask16x16,
|
||||||
|
want func(_, _ []uint16) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint16s, n, func(x, y []uint16, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x16Slice(x)
|
||||||
|
b := simd.LoadUint16x16Slice(y)
|
||||||
|
k := simd.LoadInt16x16Slice(toVect[int16](m)).AsMask16x16()
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, k).AsInt16x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt32x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int32x8, m simd.Mask32x8) simd.Mask32x8,
|
||||||
|
want func(_, _ []int32) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int32s, n, func(x, y []int32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x8Slice(x)
|
||||||
|
b := simd.LoadInt32x8Slice(y)
|
||||||
|
k := simd.LoadInt32x8Slice(toVect[int32](m)).AsMask32x8()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint32x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint32x8, m simd.Mask32x8) simd.Mask32x8,
|
||||||
|
want func(_, _ []uint32) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint32s, n, func(x, y []uint32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x8Slice(x)
|
||||||
|
b := simd.LoadUint32x8Slice(y)
|
||||||
|
k := simd.LoadInt32x8Slice(toVect[int32](m)).AsMask32x8()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt64x4CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int64x4, m simd.Mask64x4) simd.Mask64x4,
|
||||||
|
want func(_, _ []int64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int64s, n, func(x, y []int64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x4Slice(x)
|
||||||
|
b := simd.LoadInt64x4Slice(y)
|
||||||
|
k := simd.LoadInt64x4Slice(toVect[int64](m)).AsMask64x4()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint64x4CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint64x4, m simd.Mask64x4) simd.Mask64x4,
|
||||||
|
want func(_, _ []uint64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint64s, n, func(x, y []uint64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x4Slice(x)
|
||||||
|
b := simd.LoadUint64x4Slice(y)
|
||||||
|
k := simd.LoadInt64x4Slice(toVect[int64](m)).AsMask64x4()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testFloat32x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Float32x8, m simd.Mask32x8) simd.Mask32x8,
|
||||||
|
want func(_, _ []float32) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, float32s, n, func(x, y []float32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x8Slice(x)
|
||||||
|
b := simd.LoadFloat32x8Slice(y)
|
||||||
|
k := simd.LoadInt32x8Slice(toVect[int32](m)).AsMask32x8()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x4CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testFloat64x4CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Float64x4, m simd.Mask64x4) simd.Mask64x4,
|
||||||
|
want func(_, _ []float64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, float64s, n, func(x, y []float64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x4Slice(x)
|
||||||
|
b := simd.LoadFloat64x4Slice(y)
|
||||||
|
k := simd.LoadInt64x4Slice(toVect[int64](m)).AsMask64x4()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x4().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x64CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt8x64CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int8x64, m simd.Mask8x64) simd.Mask8x64,
|
||||||
|
want func(_, _ []int8) []int64) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int8s, n, func(x, y []int8, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x64Slice(x)
|
||||||
|
b := simd.LoadInt8x64Slice(y)
|
||||||
|
k := simd.LoadInt8x64Slice(toVect[int8](m)).AsMask8x64()
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, k).AsInt8x64().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x64CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint8x64CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint8x64, m simd.Mask8x64) simd.Mask8x64,
|
||||||
|
want func(_, _ []uint8) []int64) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint8s, n, func(x, y []uint8, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x64Slice(x)
|
||||||
|
b := simd.LoadUint8x64Slice(y)
|
||||||
|
k := simd.LoadInt8x64Slice(toVect[int8](m)).AsMask8x64()
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, k).AsInt8x64().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt16x32CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int16x32, m simd.Mask16x32) simd.Mask16x32,
|
||||||
|
want func(_, _ []int16) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int16s, n, func(x, y []int16, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x32Slice(x)
|
||||||
|
b := simd.LoadInt16x32Slice(y)
|
||||||
|
k := simd.LoadInt16x32Slice(toVect[int16](m)).AsMask16x32()
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, k).AsInt16x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x32CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint16x32CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint16x32, m simd.Mask16x32) simd.Mask16x32,
|
||||||
|
want func(_, _ []uint16) []int64) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint16s, n, func(x, y []uint16, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x32Slice(x)
|
||||||
|
b := simd.LoadUint16x32Slice(y)
|
||||||
|
k := simd.LoadInt16x32Slice(toVect[int16](m)).AsMask16x32()
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, k).AsInt16x32().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt32x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int32x16, m simd.Mask32x16) simd.Mask32x16,
|
||||||
|
want func(_, _ []int32) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int32s, n, func(x, y []int32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x16Slice(x)
|
||||||
|
b := simd.LoadInt32x16Slice(y)
|
||||||
|
k := simd.LoadInt32x16Slice(toVect[int32](m)).AsMask32x16()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint32x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint32x16, m simd.Mask32x16) simd.Mask32x16,
|
||||||
|
want func(_, _ []uint32) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint32s, n, func(x, y []uint32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x16Slice(x)
|
||||||
|
b := simd.LoadUint32x16Slice(y)
|
||||||
|
k := simd.LoadInt32x16Slice(toVect[int32](m)).AsMask32x16()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testInt64x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Int64x8, m simd.Mask64x8) simd.Mask64x8,
|
||||||
|
want func(_, _ []int64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, int64s, n, func(x, y []int64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x8Slice(x)
|
||||||
|
b := simd.LoadInt64x8Slice(y)
|
||||||
|
k := simd.LoadInt64x8Slice(toVect[int64](m)).AsMask64x8()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testUint64x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Uint64x8, m simd.Mask64x8) simd.Mask64x8,
|
||||||
|
want func(_, _ []uint64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, uint64s, n, func(x, y []uint64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x8Slice(x)
|
||||||
|
b := simd.LoadUint64x8Slice(y)
|
||||||
|
k := simd.LoadInt64x8Slice(toVect[int64](m)).AsMask64x8()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x16CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testFloat32x16CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Float32x16, m simd.Mask32x16) simd.Mask32x16,
|
||||||
|
want func(_, _ []float32) []int64) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, float32s, n, func(x, y []float32, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x16Slice(x)
|
||||||
|
b := simd.LoadFloat32x16Slice(y)
|
||||||
|
k := simd.LoadInt32x16Slice(toVect[int32](m)).AsMask32x16()
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, k).AsInt32x16().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x8CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func testFloat64x8CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.Float64x8, m simd.Mask64x8) simd.Mask64x8,
|
||||||
|
want func(_, _ []float64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, float64s, n, func(x, y []float64, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x8Slice(x)
|
||||||
|
b := simd.LoadFloat64x8Slice(y)
|
||||||
|
k := simd.LoadInt64x8Slice(toVect[int64](m)).AsMask64x8()
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, k).AsInt64x8().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
|
||||||
|
})
|
||||||
|
}
|
||||||
287
src/simd/genfiles.go
Normal file
287
src/simd/genfiles.go
Normal file
|
|
@ -0,0 +1,287 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// this generates type-instantiated boilerplate code for
|
||||||
|
// slice operations and tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
func oneTemplate(t *template.Template, baseType string, width, count int, out io.Writer) {
|
||||||
|
b := width * count
|
||||||
|
if b < 128 || b > 512 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
BaseType := strings.ToUpper(baseType[:1]) + baseType[1:]
|
||||||
|
eType := fmt.Sprintf("%s%d", baseType, width)
|
||||||
|
wxc := fmt.Sprintf("%dx%d", width, count)
|
||||||
|
vType := fmt.Sprintf("%s%s", BaseType, wxc)
|
||||||
|
aOrAn := "a"
|
||||||
|
if strings.Contains("aeiou", baseType[:1]) {
|
||||||
|
aOrAn = "an"
|
||||||
|
}
|
||||||
|
t.Execute(out, struct {
|
||||||
|
Vec string
|
||||||
|
AOrAn string
|
||||||
|
Width int
|
||||||
|
Count int
|
||||||
|
WxC string
|
||||||
|
Type string
|
||||||
|
}{
|
||||||
|
Vec: vType,
|
||||||
|
AOrAn: aOrAn,
|
||||||
|
Width: width,
|
||||||
|
Count: count,
|
||||||
|
WxC: wxc,
|
||||||
|
Type: eType,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func forTemplates(t *template.Template, out io.Writer) {
|
||||||
|
vecs := []int{128, 256, 512}
|
||||||
|
ints := []int{8, 16, 32, 64}
|
||||||
|
floats := []int{32, 64}
|
||||||
|
for _, v := range vecs {
|
||||||
|
for _, w := range ints {
|
||||||
|
c := v / w
|
||||||
|
oneTemplate(t, "int", w, c, out)
|
||||||
|
oneTemplate(t, "uint", w, c, out)
|
||||||
|
}
|
||||||
|
for _, w := range floats {
|
||||||
|
c := v / w
|
||||||
|
oneTemplate(t, "float", w, c, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prologue(s string, out io.Writer) {
|
||||||
|
fmt.Fprintf(out,
|
||||||
|
`// Code generated by '%s'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
package simd
|
||||||
|
|
||||||
|
`, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPrologue(t, s string, out io.Writer) {
|
||||||
|
fmt.Fprintf(out,
|
||||||
|
`// Code generated by '%s'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
// This file contains functions testing %s.
|
||||||
|
// Each function in this file is specialized for a
|
||||||
|
// particular simd type <BaseType><Width>x<Count>.
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
`, s, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func curryTestPrologue(t string) func(s string, out io.Writer) {
|
||||||
|
return func(s string, out io.Writer) {
|
||||||
|
testPrologue(t, s, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// //go:noescape
|
||||||
|
// func LoadUint8x16Slice(s []uint8) Uint8x16 {
|
||||||
|
// return LoadUint8x16((*[16]uint8)(s[:16]))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// //go:noescape
|
||||||
|
// func (x Uint8x16) StoreSlice(s []uint8) {
|
||||||
|
// x.Store((*[16]uint8)(s[:16]))
|
||||||
|
// }
|
||||||
|
|
||||||
|
func templateOf(name, temp string) *template.Template {
|
||||||
|
return template.Must(template.New(name).Parse(temp))
|
||||||
|
}
|
||||||
|
|
||||||
|
var sliceTemplate = templateOf("slice", `
|
||||||
|
// Load{{.Vec}}Slice loads {{.AOrAn}} {{.Vec}} from a slice of at least {{.Count}} {{.Type}}s
|
||||||
|
func Load{{.Vec}}Slice(s []{{.Type}}) {{.Vec}} {
|
||||||
|
return Load{{.Vec}}((*[{{.Count}}]{{.Type}})(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StoreSlice stores x into a slice of at least {{.Count}} {{.Type}}s
|
||||||
|
func (x {{.Vec}}) StoreSlice(s []{{.Type}}) {
|
||||||
|
x.Store((*[{{.Count}}]{{.Type}})(s))
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
var unaryTemplate = templateOf("unary_helpers", `
|
||||||
|
// test{{.Vec}}Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func test{{.Vec}}Unary(t *testing.T, f func(_ simd.{{.Vec}}) simd.{{.Vec}}, want func(_ []{{.Type}}) []{{.Type}}) {
|
||||||
|
n := {{.Count}}
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, {{.Type}}s, n, func(x []{{.Type}}) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.Load{{.Vec}}Slice(x)
|
||||||
|
g := make([]{{.Type}}, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
var binaryTemplate = templateOf("binary_helpers", `
|
||||||
|
// test{{.Vec}}Binary tests the simd binary method f against the expected behavior generated by want
|
||||||
|
func test{{.Vec}}Binary(t *testing.T, f func(_, _ simd.{{.Vec}}) simd.{{.Vec}}, want func(_, _ []{{.Type}}) []{{.Type}}) {
|
||||||
|
n := {{.Count}}
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, {{.Type}}s, n, func(x, y []{{.Type}}) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.Load{{.Vec}}Slice(x)
|
||||||
|
b := simd.Load{{.Vec}}Slice(y)
|
||||||
|
g := make([]{{.Type}}, n)
|
||||||
|
f(a, b).StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
var ternaryTemplate = templateOf("ternary_helpers", `
|
||||||
|
// test{{.Vec}}Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func test{{.Vec}}Ternary(t *testing.T, f func(_, _, _ simd.{{.Vec}}) simd.{{.Vec}}, want func(_, _, _ []{{.Type}}) []{{.Type}}) {
|
||||||
|
n := {{.Count}}
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, {{.Type}}s, n, func(x, y, z []{{.Type}}) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.Load{{.Vec}}Slice(x)
|
||||||
|
b := simd.Load{{.Vec}}Slice(y)
|
||||||
|
c := simd.Load{{.Vec}}Slice(z)
|
||||||
|
g := make([]{{.Type}}, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z); })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
var compareTemplate = templateOf("compare_helpers", `
|
||||||
|
// test{{.Vec}}Compare tests the simd comparison method f against the expected behavior generated by want
|
||||||
|
func test{{.Vec}}Compare(t *testing.T, f func(_, _ simd.{{.Vec}}) simd.Mask{{.WxC}}, want func(_, _ []{{.Type}}) []int64) {
|
||||||
|
n := {{.Count}}
|
||||||
|
t.Helper()
|
||||||
|
forSlicePair(t, {{.Type}}s, n, func(x, y []{{.Type}}) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.Load{{.Vec}}Slice(x)
|
||||||
|
b := simd.Load{{.Vec}}Slice(y)
|
||||||
|
g := make([]int{{.Width}}, n)
|
||||||
|
f(a, b).AsInt{{.WxC}}().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
// TODO this has not been tested yet.
|
||||||
|
var compareMaskedTemplate = templateOf("comparemasked_helpers", `
|
||||||
|
// test{{.Vec}}CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
|
||||||
|
// The mask is applied to the output of want; anything not in the mask, is zeroed.
|
||||||
|
func test{{.Vec}}CompareMasked(t *testing.T,
|
||||||
|
f func(_, _ simd.{{.Vec}}, m simd.Mask{{.WxC}}) simd.Mask{{.WxC}},
|
||||||
|
want func(_, _ []{{.Type}}) []int64) {
|
||||||
|
n := {{.Count}}
|
||||||
|
t.Helper()
|
||||||
|
forSlicePairMasked(t, {{.Type}}s, n, func(x, y []{{.Type}}, m []bool) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.Load{{.Vec}}Slice(x)
|
||||||
|
b := simd.Load{{.Vec}}Slice(y)
|
||||||
|
k := simd.LoadInt{{.WxC}}Slice(toVect[int{{.Width}}](m)).AsMask{{.WxC}}()
|
||||||
|
g := make([]int{{.Width}}, n)
|
||||||
|
f(a, b, k).AsInt{{.WxC}}().StoreSlice(g)
|
||||||
|
w := want(x, y)
|
||||||
|
for i := range m {
|
||||||
|
if !m[i] {
|
||||||
|
w[i] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkSlicesLogInput(t, s64(g), w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m); })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
sl := flag.String("sl", "slice_amd64.go", "file name for slice operations")
|
||||||
|
bh := flag.String("bh", "binary_helpers_test.go", "file name for binary test helpers")
|
||||||
|
uh := flag.String("uh", "unary_helpers_test.go", "file name for unary test helpers")
|
||||||
|
th := flag.String("th", "ternary_helpers_test.go", "file name for ternary test helpers")
|
||||||
|
ch := flag.String("ch", "compare_helpers_test.go", "file name for compare test helpers")
|
||||||
|
cmh := flag.String("cmh", "comparemasked_helpers_test.go", "file name for compare-masked test helpers")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *sl != "" {
|
||||||
|
one(*sl, prologue, sliceTemplate)
|
||||||
|
}
|
||||||
|
if *uh != "" {
|
||||||
|
one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate)
|
||||||
|
}
|
||||||
|
if *bh != "" {
|
||||||
|
one(*bh, curryTestPrologue("binary simd methods"), binaryTemplate)
|
||||||
|
}
|
||||||
|
if *th != "" {
|
||||||
|
one(*th, curryTestPrologue("ternary simd methods"), ternaryTemplate)
|
||||||
|
}
|
||||||
|
if *ch != "" {
|
||||||
|
one(*ch, curryTestPrologue("simd methods that compare two operands"), compareTemplate)
|
||||||
|
}
|
||||||
|
if *cmh != "" {
|
||||||
|
one(*cmh, curryTestPrologue("simd methods that compare two operands under a mask"), compareMaskedTemplate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func one(filename string, prologue func(s string, out io.Writer), t *template.Template) {
|
||||||
|
if filename == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ofile := os.Stdout
|
||||||
|
|
||||||
|
if filename != "-" {
|
||||||
|
var err error
|
||||||
|
ofile, err = os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Could not create the output file %s for the generated code, %v", filename, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out := new(bytes.Buffer)
|
||||||
|
|
||||||
|
prologue("go run genfiles.go", out)
|
||||||
|
forTemplates(t, out)
|
||||||
|
|
||||||
|
b, err := format.Source(out.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v", filename, err)
|
||||||
|
os.Exit(1)
|
||||||
|
} else {
|
||||||
|
ofile.Write(b)
|
||||||
|
ofile.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
// Copyright 2025 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build ignore
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
// this generates all the code to load and store simd
|
|
||||||
// vectors to/from slices.
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// //go:noescape
|
|
||||||
// func LoadUint8x16Slice(s []uint8) Uint8x16 {
|
|
||||||
// return LoadUint8x16((*[16]uint8)(s[:16]))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //go:noescape
|
|
||||||
// func (x Uint8x16) StoreSlice(s []uint8) {
|
|
||||||
// x.Store((*[16]uint8)(s[:16]))
|
|
||||||
// }
|
|
||||||
|
|
||||||
func slice(e string, w, c int, out io.Writer) {
|
|
||||||
b := w * c
|
|
||||||
if b < 128 || b > 512 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
E := strings.ToUpper(e[:1]) + e[1:]
|
|
||||||
t := fmt.Sprintf("%s%d", e, w)
|
|
||||||
v := fmt.Sprintf("%s%dx%d", E, w, c)
|
|
||||||
a := "a"
|
|
||||||
if strings.Contains("aeiou", e[:1]) {
|
|
||||||
a = "an"
|
|
||||||
}
|
|
||||||
fmt.Fprintf(out,
|
|
||||||
`
|
|
||||||
// Load%sSlice loads %s %s from a slice of at least %d %ss
|
|
||||||
func Load%sSlice(s []%s) %s {
|
|
||||||
return Load%s((*[%d]%s)(s))
|
|
||||||
}
|
|
||||||
`, v, a, v, c, t, v, t, v, v, c, t)
|
|
||||||
|
|
||||||
fmt.Fprintf(out,
|
|
||||||
`
|
|
||||||
// StoreSlice stores x into a slice of at least %d %ss
|
|
||||||
func (x %s) StoreSlice(s []%s) {
|
|
||||||
x.Store((*[%d]%s)(s))
|
|
||||||
}
|
|
||||||
`, c, t, v, t, c, t)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func prologue(s string, out io.Writer) {
|
|
||||||
fmt.Fprintf(out,
|
|
||||||
`// Code generated by '%s'; DO NOT EDIT.
|
|
||||||
|
|
||||||
//go:build goexperiment.simd
|
|
||||||
|
|
||||||
// The build condition == if the experiment is not on, cmd/api TestCheck will see this and complain
|
|
||||||
// see also go/doc/comment, where "simd" is inserted to the package list of the experiment is not on.
|
|
||||||
|
|
||||||
package simd
|
|
||||||
|
|
||||||
`, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
filename := flag.String("o", "", "write generated code to this file")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
ofile := os.Stdout
|
|
||||||
|
|
||||||
if *filename != "" {
|
|
||||||
var err error
|
|
||||||
ofile, err = os.Create(*filename)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "Could not create the output file for the generated code, %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out := new(bytes.Buffer)
|
|
||||||
|
|
||||||
prologue("go run genslice.go -o slice_amd64.go", out)
|
|
||||||
|
|
||||||
vecs := []int{128, 256, 512}
|
|
||||||
ints := []int{8, 16, 32, 64}
|
|
||||||
floats := []int{32, 64}
|
|
||||||
for _, v := range vecs {
|
|
||||||
for _, w := range ints {
|
|
||||||
c := v / w
|
|
||||||
slice("int", w, c, out)
|
|
||||||
slice("uint", w, c, out)
|
|
||||||
}
|
|
||||||
for _, w := range floats {
|
|
||||||
c := v / w
|
|
||||||
slice("float", w, c, out)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
b, err := format.Source(out.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code, %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
} else {
|
|
||||||
ofile.Write(b)
|
|
||||||
ofile.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
299
src/simd/helpers_test.go
Normal file
299
src/simd/helpers_test.go
Normal file
|
|
@ -0,0 +1,299 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd && amd64
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type signed interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type integer interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type float interface {
|
||||||
|
~float32 | ~float64
|
||||||
|
}
|
||||||
|
|
||||||
|
type number interface {
|
||||||
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSlices[T number](t *testing.T, got, want []T) bool {
|
||||||
|
t.Helper()
|
||||||
|
return checkSlicesLogInput[T](t, got, want, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checkSlices compares two slices for equality,
|
||||||
|
// reporting a test error if there is a problem,
|
||||||
|
// and also consumes the two slices so that a
|
||||||
|
// test/benchmark won't be dead-code eliminated.
|
||||||
|
func checkSlicesLogInput[T number](t *testing.T, got, want []T, logInput func()) bool {
|
||||||
|
t.Helper()
|
||||||
|
var z T
|
||||||
|
for i := range want {
|
||||||
|
if got[i] != want[i] {
|
||||||
|
var ia any = got[i]
|
||||||
|
var ib any = want[i]
|
||||||
|
switch x := ia.(type) {
|
||||||
|
case float32:
|
||||||
|
y := ib.(float32)
|
||||||
|
if math.IsNaN(float64(x)) && math.IsNaN(float64(y)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
y := ib.(float64)
|
||||||
|
if math.IsNaN(x) && math.IsNaN(y) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("For %T vector elements:", z)
|
||||||
|
t.Logf("got =%v", got)
|
||||||
|
t.Logf("want=%v", want)
|
||||||
|
if logInput != nil {
|
||||||
|
logInput()
|
||||||
|
}
|
||||||
|
t.Errorf("at index %d, got=%v, want=%v", i, got[i], want[i])
|
||||||
|
return false
|
||||||
|
} else if got[i] == 0 { // for floating point, 0.0 == -0.0 but a bitwise check can see the difference
|
||||||
|
var ia any = got[i]
|
||||||
|
var ib any = want[i]
|
||||||
|
switch x := ia.(type) {
|
||||||
|
case float32:
|
||||||
|
y := ib.(float32)
|
||||||
|
if math.Float32bits(x) != math.Float32bits(y) {
|
||||||
|
t.Logf("For %T vector elements:", z)
|
||||||
|
t.Logf("got =%v", got)
|
||||||
|
t.Logf("want=%v", want)
|
||||||
|
if logInput != nil {
|
||||||
|
logInput()
|
||||||
|
}
|
||||||
|
t.Errorf("at index %d, different signs of zero", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
case float64:
|
||||||
|
y := ib.(float64)
|
||||||
|
if math.Float64bits(x) != math.Float64bits(y) {
|
||||||
|
t.Logf("For %T vector elements:", z)
|
||||||
|
t.Logf("got =%v", got)
|
||||||
|
t.Logf("want=%v", want)
|
||||||
|
if logInput != nil {
|
||||||
|
logInput()
|
||||||
|
}
|
||||||
|
t.Errorf("at index %d, different signs of zero", i)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// sliceOf returns a slice n T's, with each
|
||||||
|
// element of the slice initialized to its
|
||||||
|
// index + 1.
|
||||||
|
func sliceOf[T number](n int) []T {
|
||||||
|
s := make([]T, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
s[i] = T(i + 1)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func toVect[T signed](b []bool) []T {
|
||||||
|
s := make([]T, len(b))
|
||||||
|
for i := range b {
|
||||||
|
if b[i] {
|
||||||
|
s[i] = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// s64 converts a slice of some integer type into a slice of int64
|
||||||
|
func s64[T number](s []T) []int64 {
|
||||||
|
var is any = s
|
||||||
|
if r, ok := is.([]int64); ok {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
r := make([]int64, len(s))
|
||||||
|
for i := range s {
|
||||||
|
r[i] = int64(s[i])
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do implements slice part testing. It repeatedly calls
|
||||||
|
// body on smaller and smaller slices and an output slice
|
||||||
|
// for the result, then compares the result to its own
|
||||||
|
// calculation of what the result should be.
|
||||||
|
func Do[T number](t *testing.T, n int, body func(a, c []T)) {
|
||||||
|
a := sliceOf[T](n)
|
||||||
|
b := sliceOf[T](n)
|
||||||
|
|
||||||
|
for i := n; i >= 0; i-- {
|
||||||
|
c := make([]T, n, n)
|
||||||
|
body(a[:i], c)
|
||||||
|
checkSlices(t, c, b)
|
||||||
|
if i > 0 {
|
||||||
|
b[i-1] = T(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// map3 returns a function that returns the slice of the results of applying
|
||||||
|
// input parameter elem to the respective elements of its 3 slice inputs.
|
||||||
|
func map3[T, U any](elem func(x, y, z T) U) func(x, y, z []T) []U {
|
||||||
|
return func(x, y, z []T) []U {
|
||||||
|
s := make([]U, len(x))
|
||||||
|
for i := range s {
|
||||||
|
s[i] = elem(x[i], y[i], z[i])
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// map2 returns a function that returns the slice of the results of applying
|
||||||
|
// input parameter elem to the respective elements of its 2 slice inputs.
|
||||||
|
func map2[T, U any](elem func(x, y T) U) func(x, y []T) []U {
|
||||||
|
return func(x, y []T) []U {
|
||||||
|
s := make([]U, len(x))
|
||||||
|
for i := range s {
|
||||||
|
s[i] = elem(x[i], y[i])
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// map1 returns a function that returns the slice of the results of applying
|
||||||
|
// input parameter elem to the respective elements of its single slice input.
|
||||||
|
func map1[T, U any](elem func(x T) U) func(x []T) []U {
|
||||||
|
return func(x []T) []U {
|
||||||
|
s := make([]U, len(x))
|
||||||
|
for i := range s {
|
||||||
|
s[i] = elem(x[i])
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// map1 returns a function that returns the slice of the results of applying
|
||||||
|
// comparison function elem to the respective elements of its two slice inputs.
|
||||||
|
func mapCompare[T number](elem func(x, y T) bool) func(x, y []T) []int64 {
|
||||||
|
return func(x, y []T) []int64 {
|
||||||
|
s := make([]int64, len(x))
|
||||||
|
for i := range s {
|
||||||
|
if elem(x[i], y[i]) {
|
||||||
|
s[i] = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nOf returns a slice of length n whose elements are taken
|
||||||
|
// from input slice s.
|
||||||
|
func nOf[T any](n int, s []T) []T {
|
||||||
|
if len(s) >= n {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
r := make([]T, n)
|
||||||
|
for i := range r {
|
||||||
|
r[i] = s[i%len(s)]
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PN22 = 1.0 / 1024 / 1024 / 4
|
||||||
|
PN24 = 1.0 / 1024 / 1024 / 16
|
||||||
|
PN53 = PN24 * PN24 / 32
|
||||||
|
F0 = float32(1.0 + 513*PN22/2)
|
||||||
|
F1 = float32(1.0 + 511*PN22*8)
|
||||||
|
Aeasy = float32(2046 * PN53)
|
||||||
|
Ahard = float32(2047 * PN53) // 2047 provokes a 2-rounding in 64-bit FMA rounded to 32-bit
|
||||||
|
)
|
||||||
|
|
||||||
|
var zero = 0.0
|
||||||
|
var nan = math.NaN()
|
||||||
|
|
||||||
|
// N controls how large the test vectors are
|
||||||
|
const N = 144
|
||||||
|
|
||||||
|
var float32s = nOf(N, []float32{1, float32(nan), float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1 / zero), float32(-1 / zero), 1 / 2, 1 / 4, 1 / 8, 1 / 1000, 1 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
|
||||||
|
var float64s = nOf(N, []float64{nan, zero, -zero, 1 / zero, -1 / zero, 1 / 1000, 1 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
|
||||||
|
|
||||||
|
var int32s = nOf(N, []int32{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
|
||||||
|
var uint32s = nOf(N, []uint32{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint32(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint32(0x55555), ^uint32(0x77777), ^uint32(0xccccc)})
|
||||||
|
|
||||||
|
var int64s = nOf(N, []int64{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
|
||||||
|
var uint64s = nOf(N, []uint64{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint64(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint64(0x55555), ^uint64(0x77777), ^uint64(0xccccc)})
|
||||||
|
|
||||||
|
var int16s = nOf(N, []int16{1, -1, 0, 2, 4, 8, 1024, 3, 5, 7, 11, 13, 3000, 5555, 7777, 11111, 32767, 32766, -32767, -32768, -11111, -4, -8, -16, -32, -64})
|
||||||
|
var uint16s = nOf(N, []uint16{1, 0, 2, 4, 8, 1024, 3, 5, 7, 11, 13, 3000, 5555, 7777, 11111, 32767, 32766, 32768, 65535, 45678, 56789})
|
||||||
|
|
||||||
|
var int8s = nOf(N, []int8{0, 1, 2, 3, 5, 7, 11, 22, 33, 55, 77, 121, 127, -1, -2, -3, -5, -7, -11, -77, -121, -127, -128, 4, 8, 16, 32, 64, -4, -8, -16, -32, -64})
|
||||||
|
var uint8s = nOf(N, []uint8{0, 1, 2, 3, 5, 7, 11, 22, 33, 55, 77, 121, 127, 128, 255, 233, 211, 177, 144, 4, 8, 16, 32, 64})
|
||||||
|
|
||||||
|
var bools = nOf(N, []bool{
|
||||||
|
true, false, true, true, false, false, true, true, true, false, false, false, true, true, true, true, false, false, false, false})
|
||||||
|
|
||||||
|
func forSlice[T number](t *testing.T, s []T, n int, f func(a []T) bool) {
|
||||||
|
t.Helper()
|
||||||
|
for i := 0; i < len(s)-n; i++ {
|
||||||
|
if !f(s[i : i+n]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func forSlicePair[T number](t *testing.T, s []T, n int, f func(a, b []T) bool) {
|
||||||
|
t.Helper()
|
||||||
|
for i := 0; i < len(s)-n; i++ {
|
||||||
|
for j := 0; j < len(s)-n; j++ {
|
||||||
|
if !f(s[i:i+n], s[j:j+n]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func forSliceTriple[T number](t *testing.T, s []T, n int, f func(a, b, c []T) bool) {
|
||||||
|
t.Helper()
|
||||||
|
for i := 0; i < len(s)-n; i += 3 {
|
||||||
|
for j := 0; j < len(s)-n; j += 3 {
|
||||||
|
for k := 0; k < len(s)-n; k += 3 {
|
||||||
|
if !f(s[i:i+n], s[j:j+n], s[k:k+n]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func forSlicePairMasked[T number](t *testing.T, s []T, n int, f func(a, b []T, m []bool) bool) {
|
||||||
|
t.Helper()
|
||||||
|
m := bools
|
||||||
|
// Step slice pair masked forward much more quickly, otherwise it is slooooow
|
||||||
|
for i := 0; i < len(s)-n; i += 3 {
|
||||||
|
for j := 0; j < len(s)-n; j += 3 {
|
||||||
|
for k := 0; k < len(m)-n; k += 3 {
|
||||||
|
if !f(s[i:i+n], s[j:j+n], m[k:k+n]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,4 +6,4 @@ package simd
|
||||||
|
|
||||||
// This file has no build tag, so that go generate can run without a build tag.
|
// This file has no build tag, so that go generate can run without a build tag.
|
||||||
|
|
||||||
//go:generate go run genslice.go -o slice_amd64.go
|
//go:generate go run genfiles.go
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ package simd_test
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"simd"
|
"simd"
|
||||||
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -135,22 +136,6 @@ func TestMaskConversion(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
|
||||||
testInt32x4Binary(t, []int32{1, 2, 3, 4}, []int32{5, 6, 7, 8}, []int32{6, 8, 10, 12}, "Add")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSub(t *testing.T) {
|
|
||||||
testInt32x4Binary(t, []int32{5, 5, 5, 3}, []int32{3, 3, 3, 3}, []int32{2, 2, 2, 0}, "Sub")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMaskedAdd(t *testing.T) {
|
|
||||||
if !simd.HasAVX512GFNI() {
|
|
||||||
t.Skip("Test requires HasAVX512, not available on this hardware")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
testInt32x4BinaryMasked(t, []int32{1, 2, 3, 4}, []int32{5, 6, 7, 8}, []int32{-1, -1, 0, 0}, []int32{6, 8, 0, 0}, "AddMasked")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPermute(t *testing.T) {
|
func TestPermute(t *testing.T) {
|
||||||
if !simd.HasAVX512() {
|
if !simd.HasAVX512() {
|
||||||
t.Skip("Test requires HasAVX512, not available on this hardware")
|
t.Skip("Test requires HasAVX512, not available on this hardware")
|
||||||
|
|
@ -191,15 +176,15 @@ func TestCompress(t *testing.T) {
|
||||||
t.Skip("Test requires HasAVX512, not available on this hardware")
|
t.Skip("Test requires HasAVX512, not available on this hardware")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
testInt32x4Mask32x4Int32x4(t, []int32{1, 2, 3, 4},
|
v1234 := simd.LoadInt32x4Slice([]int32{1, 2, 3, 4})
|
||||||
[]int32{0, -1, 0, -1},
|
v0101 := simd.LoadInt32x4Slice([]int32{0, -1, 0, -1})
|
||||||
[]int32{2, 4, 0, 0}, "Compress")
|
v2400 := v1234.Compress(v0101.AsMask32x4())
|
||||||
}
|
got := make([]int32, 4)
|
||||||
|
v2400.StoreSlice(got)
|
||||||
func TestAndNot(t *testing.T) {
|
want := []int32{2, 4, 0, 0}
|
||||||
testInt32x4Binary(t, []int32{0b11, 0b00, 0b11, 0b00},
|
if !slices.Equal(got, want) {
|
||||||
[]int32{0b01, 0b01, 0b01, 0b01},
|
t.Errorf("want and got differ, want=%v, got=%v", want, got)
|
||||||
[]int32{0b10, 0b00, 0b10, 0b00}, "AndNot")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPairDotProdAccumulate(t *testing.T) {
|
func TestPairDotProdAccumulate(t *testing.T) {
|
||||||
|
|
@ -231,53 +216,13 @@ func checkInt8Slices(t *testing.T, a, b []int8) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkUint8Slices(t *testing.T, a, b []uint8) {
|
|
||||||
for i := range b {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
t.Errorf("a and b differ at index %d, a=%d, b=%d", i, a[i], b[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkInt16Slices(t *testing.T, a, b []int16) {
|
|
||||||
for i := range b {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
t.Errorf("a and b differ at index %d, a=%d, b=%d", i, a[i], b[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkUint16Slices(t *testing.T, a, b []uint16) {
|
|
||||||
for i := range b {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
t.Errorf("a and b differ at index %d, a=%d, b=%d", i, a[i], b[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkFloat32Slices(t *testing.T, a, b []float32) {
|
|
||||||
for i := range b {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
t.Errorf("a and b differ at index %d, a=%3.0f, b=%3.0f", i, a[i], b[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkFloat64Slices(t *testing.T, a, b []float64) {
|
|
||||||
for i := range b {
|
|
||||||
if a[i] != b[i] {
|
|
||||||
t.Errorf("a and b differ at index %d, a=%3.0f, b=%3.0f", i, a[i], b[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSlicesInt8(t *testing.T) {
|
func TestSlicesInt8(t *testing.T) {
|
||||||
a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}
|
||||||
v := simd.LoadInt8x32Slice(a)
|
v := simd.LoadInt8x32Slice(a)
|
||||||
b := make([]int8, 32, 32)
|
b := make([]int8, 32, 32)
|
||||||
v.StoreSlice(b)
|
v.StoreSlice(b)
|
||||||
checkInt8Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesInt8SetElem(t *testing.T) {
|
func TestSlicesInt8SetElem(t *testing.T) {
|
||||||
|
|
@ -290,7 +235,7 @@ func TestSlicesInt8SetElem(t *testing.T) {
|
||||||
|
|
||||||
b := make([]int8, 16, 16)
|
b := make([]int8, 16, 16)
|
||||||
v.StoreSlice(b)
|
v.StoreSlice(b)
|
||||||
checkInt8Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesInt8GetElem(t *testing.T) {
|
func TestSlicesInt8GetElem(t *testing.T) {
|
||||||
|
|
@ -315,8 +260,8 @@ func TestSlicesInt8Set128(t *testing.T) {
|
||||||
b := make([]int8, 32, 32)
|
b := make([]int8, 32, 32)
|
||||||
w.StoreSlice(b)
|
w.StoreSlice(b)
|
||||||
|
|
||||||
checkInt8Slices(t, a, b[:16])
|
checkSlices(t, a, b[:16])
|
||||||
checkInt8Slices(t, a, b[16:])
|
checkSlices(t, a, b[16:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesInt8Get128(t *testing.T) {
|
func TestSlicesInt8Get128(t *testing.T) {
|
||||||
|
|
@ -330,7 +275,7 @@ func TestSlicesInt8Get128(t *testing.T) {
|
||||||
v.StoreSlice(b[:16])
|
v.StoreSlice(b[:16])
|
||||||
w.StoreSlice(b[16:])
|
w.StoreSlice(b[16:])
|
||||||
|
|
||||||
checkInt8Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesFloat32Set128(t *testing.T) {
|
func TestSlicesFloat32Set128(t *testing.T) {
|
||||||
|
|
@ -344,8 +289,8 @@ func TestSlicesFloat32Set128(t *testing.T) {
|
||||||
b := make([]float32, 8, 8)
|
b := make([]float32, 8, 8)
|
||||||
w.StoreSlice(b)
|
w.StoreSlice(b)
|
||||||
|
|
||||||
checkFloat32Slices(t, a, b[:4])
|
checkSlices(t, a, b[:4])
|
||||||
checkFloat32Slices(t, a, b[4:])
|
checkSlices(t, a, b[4:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesFloat32Get128(t *testing.T) {
|
func TestSlicesFloat32Get128(t *testing.T) {
|
||||||
|
|
@ -359,7 +304,7 @@ func TestSlicesFloat32Get128(t *testing.T) {
|
||||||
v.StoreSlice(b[:4])
|
v.StoreSlice(b[:4])
|
||||||
w.StoreSlice(b[4:])
|
w.StoreSlice(b[4:])
|
||||||
|
|
||||||
checkFloat32Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesFloat64Set128(t *testing.T) {
|
func TestSlicesFloat64Set128(t *testing.T) {
|
||||||
|
|
@ -373,8 +318,8 @@ func TestSlicesFloat64Set128(t *testing.T) {
|
||||||
b := make([]float64, 4, 4)
|
b := make([]float64, 4, 4)
|
||||||
w.StoreSlice(b)
|
w.StoreSlice(b)
|
||||||
|
|
||||||
checkFloat64Slices(t, a, b[:2])
|
checkSlices(t, a, b[:2])
|
||||||
checkFloat64Slices(t, a, b[2:])
|
checkSlices(t, a, b[2:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesFloat64Get128(t *testing.T) {
|
func TestSlicesFloat64Get128(t *testing.T) {
|
||||||
|
|
@ -388,7 +333,7 @@ func TestSlicesFloat64Get128(t *testing.T) {
|
||||||
v.StoreSlice(b[:2])
|
v.StoreSlice(b[:2])
|
||||||
w.StoreSlice(b[2:])
|
w.StoreSlice(b[2:])
|
||||||
|
|
||||||
checkFloat64Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesInt8TooShortLoad(t *testing.T) {
|
func TestSlicesInt8TooShortLoad(t *testing.T) {
|
||||||
|
|
@ -404,7 +349,7 @@ func TestSlicesInt8TooShortLoad(t *testing.T) {
|
||||||
v := simd.LoadInt8x32Slice(a)
|
v := simd.LoadInt8x32Slice(a)
|
||||||
b := make([]int8, 32, 32)
|
b := make([]int8, 32, 32)
|
||||||
v.StoreSlice(b)
|
v.StoreSlice(b)
|
||||||
checkInt8Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesInt8TooShortStore(t *testing.T) {
|
func TestSlicesInt8TooShortStore(t *testing.T) {
|
||||||
|
|
@ -420,7 +365,7 @@ func TestSlicesInt8TooShortStore(t *testing.T) {
|
||||||
v := simd.LoadInt8x32Slice(a)
|
v := simd.LoadInt8x32Slice(a)
|
||||||
b := make([]int8, 31) // TOO SHORT, should panic
|
b := make([]int8, 31) // TOO SHORT, should panic
|
||||||
v.StoreSlice(b)
|
v.StoreSlice(b)
|
||||||
checkInt8Slices(t, a, b)
|
checkSlices(t, a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicesFloat64(t *testing.T) {
|
func TestSlicesFloat64(t *testing.T) {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
204
src/simd/simulation_helpers_test.go
Normal file
204
src/simd/simulation_helpers_test.go
Normal file
|
|
@ -0,0 +1,204 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd && amd64
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import "math"
|
||||||
|
|
||||||
|
func less[T number](x, y T) bool {
|
||||||
|
return x < y
|
||||||
|
}
|
||||||
|
func lessEqual[T number](x, y T) bool {
|
||||||
|
return x <= y
|
||||||
|
}
|
||||||
|
func greater[T number](x, y T) bool {
|
||||||
|
return x > y
|
||||||
|
}
|
||||||
|
func greaterEqual[T number](x, y T) bool {
|
||||||
|
return x >= y
|
||||||
|
}
|
||||||
|
func equal[T number](x, y T) bool {
|
||||||
|
return x == y
|
||||||
|
}
|
||||||
|
func notEqual[T number](x, y T) bool {
|
||||||
|
return x != y
|
||||||
|
}
|
||||||
|
|
||||||
|
func abs[T number](x T) T {
|
||||||
|
// TODO this will need a non-standard FP-equality test.
|
||||||
|
if x == 0 { // true if x is -0.
|
||||||
|
return x // this is not a negative zero
|
||||||
|
}
|
||||||
|
if x < 0 {
|
||||||
|
return -x
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func ceil[T float](x T) T {
|
||||||
|
return T(math.Ceil(float64(x)))
|
||||||
|
}
|
||||||
|
func floor[T float](x T) T {
|
||||||
|
return T(math.Floor(float64(x)))
|
||||||
|
}
|
||||||
|
func not[T integer](x T) T {
|
||||||
|
return ^x
|
||||||
|
}
|
||||||
|
func round[T float](x T) T {
|
||||||
|
return T(math.RoundToEven(float64(x)))
|
||||||
|
}
|
||||||
|
func sqrt[T float](x T) T {
|
||||||
|
return T(math.Sqrt(float64(x)))
|
||||||
|
}
|
||||||
|
func trunc[T float](x T) T {
|
||||||
|
return T(math.Trunc(float64(x)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func add[T number](x, y T) T {
|
||||||
|
return x + y
|
||||||
|
}
|
||||||
|
|
||||||
|
func sub[T number](x, y T) T {
|
||||||
|
return x - y
|
||||||
|
}
|
||||||
|
|
||||||
|
func max_[T number](x, y T) T { // "max" lands in infinite recursion
|
||||||
|
return max(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func min_[T number](x, y T) T { // "min" lands in infinite recursion
|
||||||
|
return min(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also mulLow for integers
|
||||||
|
func mul[T number](x, y T) T {
|
||||||
|
return x * y
|
||||||
|
}
|
||||||
|
|
||||||
|
func div[T number](x, y T) T {
|
||||||
|
return x / y
|
||||||
|
}
|
||||||
|
|
||||||
|
func and[T integer](x, y T) T {
|
||||||
|
return x & y
|
||||||
|
}
|
||||||
|
|
||||||
|
func andNotI[T integer](x, y T) T {
|
||||||
|
return x & ^y // order corrected to match expectations
|
||||||
|
}
|
||||||
|
|
||||||
|
func orI[T integer](x, y T) T {
|
||||||
|
return x | y
|
||||||
|
}
|
||||||
|
|
||||||
|
func xorI[T integer](x, y T) T {
|
||||||
|
return x ^ y
|
||||||
|
}
|
||||||
|
|
||||||
|
func ima[T integer](x, y, z T) T {
|
||||||
|
return x*y + z
|
||||||
|
}
|
||||||
|
|
||||||
|
func fma[T float](x, y, z T) T {
|
||||||
|
return T(math.FMA(float64(x), float64(y), float64(z)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSlice[T number](x, y []T) []T {
|
||||||
|
return map2[T](add)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func subSlice[T number](x, y []T) []T {
|
||||||
|
return map2[T](sub)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func maxSlice[T number](x, y []T) []T {
|
||||||
|
return map2[T](max_)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func minSlice[T number](x, y []T) []T {
|
||||||
|
return map2[T](min_)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mulLow for integers
|
||||||
|
func mulSlice[T number](x, y []T) []T {
|
||||||
|
return map2[T](mul)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func divSlice[T number](x, y []T) []T {
|
||||||
|
return map2[T](div)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func andSlice[T integer](x, y []T) []T {
|
||||||
|
return map2[T](and)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func andNotSlice[T integer](x, y []T) []T {
|
||||||
|
return map2[T](andNotI)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func orSlice[T integer](x, y []T) []T {
|
||||||
|
return map2[T](orI)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func xorSlice[T integer](x, y []T) []T {
|
||||||
|
return map2[T](xorI)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lessSlice[T number](x, y []T) []int64 {
|
||||||
|
return mapCompare[T](less)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func lessEqualSlice[T number](x, y []T) []int64 {
|
||||||
|
return mapCompare[T](lessEqual)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func greaterSlice[T number](x, y []T) []int64 {
|
||||||
|
return mapCompare[T](greater)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func greaterEqualSlice[T number](x, y []T) []int64 {
|
||||||
|
return mapCompare[T](greaterEqual)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func equalSlice[T number](x, y []T) []int64 {
|
||||||
|
return mapCompare[T](equal)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func notEqualSlice[T number](x, y []T) []int64 {
|
||||||
|
return mapCompare[T](notEqual)(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ceilSlice[T float](x []T) []T {
|
||||||
|
return map1[T](ceil)(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func floorSlice[T float](x []T) []T {
|
||||||
|
return map1[T](floor)(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func notSlice[T integer](x []T) []T {
|
||||||
|
return map1[T](not)(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func roundSlice[T float](x []T) []T {
|
||||||
|
return map1[T](round)(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sqrtSlice[T float](x []T) []T {
|
||||||
|
return map1[T](sqrt)(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func truncSlice[T float](x []T) []T {
|
||||||
|
return map1[T](trunc)(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func imaSlice[T integer](x, y, z []T) []T {
|
||||||
|
return map3[T](ima)(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fmaSlice[T float](x, y, z []T) []T {
|
||||||
|
return map3[T](fma)(x, y, z)
|
||||||
|
}
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
// Code generated by 'go run genslice.go -o slice_amd64.go'; DO NOT EDIT.
|
// Code generated by 'go run genfiles.go'; DO NOT EDIT.
|
||||||
|
|
||||||
//go:build goexperiment.simd
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
// The build condition == if the experiment is not on, cmd/api TestCheck will see this and complain
|
|
||||||
// see also go/doc/comment, where "simd" is inserted to the package list of the experiment is not on.
|
|
||||||
|
|
||||||
package simd
|
package simd
|
||||||
|
|
||||||
// LoadInt8x16Slice loads an Int8x16 from a slice of at least 16 int8s
|
// LoadInt8x16Slice loads an Int8x16 from a slice of at least 16 int8s
|
||||||
|
|
|
||||||
|
|
@ -12,17 +12,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSlicePartInt8x16(t *testing.T) {
|
func TestSlicePartInt8x16(t *testing.T) {
|
||||||
a := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
Do(t, 16, func(a, c []int8) {
|
||||||
b := []int8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
|
u := simd.LoadInt8x16SlicePart(a)
|
||||||
for i := 16; i >= 0; i-- {
|
|
||||||
u := simd.LoadInt8x16SlicePart(a[:i])
|
|
||||||
c := make([]int8, 32, 32)
|
|
||||||
u.StoreSlice(c)
|
u.StoreSlice(c)
|
||||||
checkInt8Slices(t, c, b)
|
})
|
||||||
if i > 0 {
|
|
||||||
b[i-1] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSlicePartInt8x32(t *testing.T) {
|
func TestSlicePartInt8x32(t *testing.T) {
|
||||||
|
|
@ -34,7 +27,7 @@ func TestSlicePartInt8x32(t *testing.T) {
|
||||||
u := simd.LoadInt8x32SlicePart(a[:i])
|
u := simd.LoadInt8x32SlicePart(a[:i])
|
||||||
c := make([]int8, 32, 32)
|
c := make([]int8, 32, 32)
|
||||||
u.StoreSlice(c)
|
u.StoreSlice(c)
|
||||||
checkInt8Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +41,7 @@ func TestSlicePartUint8x16(t *testing.T) {
|
||||||
u := simd.LoadUint8x16SlicePart(a[:i])
|
u := simd.LoadUint8x16SlicePart(a[:i])
|
||||||
c := make([]uint8, 32, 32)
|
c := make([]uint8, 32, 32)
|
||||||
u.StoreSlice(c)
|
u.StoreSlice(c)
|
||||||
checkUint8Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +57,7 @@ func TestSlicePartUint8x32(t *testing.T) {
|
||||||
u := simd.LoadUint8x32SlicePart(a[:i])
|
u := simd.LoadUint8x32SlicePart(a[:i])
|
||||||
c := make([]uint8, 32, 32)
|
c := make([]uint8, 32, 32)
|
||||||
u.StoreSlice(c)
|
u.StoreSlice(c)
|
||||||
checkUint8Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +71,7 @@ func TestSlicePartInt16x8(t *testing.T) {
|
||||||
u := simd.LoadInt16x8SlicePart(a[:i])
|
u := simd.LoadInt16x8SlicePart(a[:i])
|
||||||
c := make([]int16, 16, 16)
|
c := make([]int16, 16, 16)
|
||||||
u.StoreSlice(c)
|
u.StoreSlice(c)
|
||||||
checkInt16Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +85,7 @@ func TestSlicePartInt16x16(t *testing.T) {
|
||||||
u := simd.LoadInt16x16SlicePart(a[:i])
|
u := simd.LoadInt16x16SlicePart(a[:i])
|
||||||
c := make([]int16, 16, 16)
|
c := make([]int16, 16, 16)
|
||||||
u.StoreSlice(c)
|
u.StoreSlice(c)
|
||||||
checkInt16Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +99,7 @@ func TestSlicesPartStoreInt8x16(t *testing.T) {
|
||||||
v := simd.LoadInt8x16Slice(a)
|
v := simd.LoadInt8x16Slice(a)
|
||||||
c := make([]int8, 32, 32)
|
c := make([]int8, 32, 32)
|
||||||
v.StoreSlicePart(c[:i])
|
v.StoreSlicePart(c[:i])
|
||||||
checkInt8Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -120,7 +113,7 @@ func TestSlicesPartStoreInt16x8(t *testing.T) {
|
||||||
v := simd.LoadInt16x8Slice(a)
|
v := simd.LoadInt16x8Slice(a)
|
||||||
c := make([]int16, 32, 32)
|
c := make([]int16, 32, 32)
|
||||||
v.StoreSlicePart(c[:i])
|
v.StoreSlicePart(c[:i])
|
||||||
checkInt16Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +127,7 @@ func TestSlicesPartStoreInt16x16(t *testing.T) {
|
||||||
v := simd.LoadInt16x16Slice(a)
|
v := simd.LoadInt16x16Slice(a)
|
||||||
c := make([]int16, 32, 32)
|
c := make([]int16, 32, 32)
|
||||||
v.StoreSlicePart(c[:i])
|
v.StoreSlicePart(c[:i])
|
||||||
checkInt16Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -148,7 +141,7 @@ func TestSlicesPartStoreUint8x16(t *testing.T) {
|
||||||
v := simd.LoadUint8x16Slice(a)
|
v := simd.LoadUint8x16Slice(a)
|
||||||
c := make([]uint8, 32, 32)
|
c := make([]uint8, 32, 32)
|
||||||
v.StoreSlicePart(c[:i])
|
v.StoreSlicePart(c[:i])
|
||||||
checkUint8Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +155,7 @@ func TestSlicesPartStoreUint16x16(t *testing.T) {
|
||||||
v := simd.LoadUint16x16Slice(a)
|
v := simd.LoadUint16x16Slice(a)
|
||||||
c := make([]uint16, 32, 32)
|
c := make([]uint16, 32, 32)
|
||||||
v.StoreSlicePart(c[:i])
|
v.StoreSlicePart(c[:i])
|
||||||
checkUint16Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
@ -178,7 +171,7 @@ func TestSlicesPartStoreUint8x32(t *testing.T) {
|
||||||
v := simd.LoadUint8x32Slice(a)
|
v := simd.LoadUint8x32Slice(a)
|
||||||
c := make([]uint8, 32, 32)
|
c := make([]uint8, 32, 32)
|
||||||
v.StoreSlicePart(c[:i])
|
v.StoreSlicePart(c[:i])
|
||||||
checkUint8Slices(t, c, b)
|
checkSlices(t, c, b)
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
b[i-1] = 0
|
b[i-1] = 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
494
src/simd/ternary_helpers_test.go
Normal file
494
src/simd/ternary_helpers_test.go
Normal file
|
|
@ -0,0 +1,494 @@
|
||||||
|
// Code generated by 'go run genfiles.go'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
// This file contains functions testing ternary simd methods.
|
||||||
|
// Each function in this file is specialized for a
|
||||||
|
// particular simd type <BaseType><Width>x<Count>.
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testInt8x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt8x16Ternary(t *testing.T, f func(_, _, _ simd.Int8x16) simd.Int8x16, want func(_, _, _ []int8) []int8) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int8s, n, func(x, y, z []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x16Slice(x)
|
||||||
|
b := simd.LoadInt8x16Slice(y)
|
||||||
|
c := simd.LoadInt8x16Slice(z)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint8x16Ternary(t *testing.T, f func(_, _, _ simd.Uint8x16) simd.Uint8x16, want func(_, _, _ []uint8) []uint8) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x16Slice(x)
|
||||||
|
b := simd.LoadUint8x16Slice(y)
|
||||||
|
c := simd.LoadUint8x16Slice(z)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt16x8Ternary(t *testing.T, f func(_, _, _ simd.Int16x8) simd.Int16x8, want func(_, _, _ []int16) []int16) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int16s, n, func(x, y, z []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x8Slice(x)
|
||||||
|
b := simd.LoadInt16x8Slice(y)
|
||||||
|
c := simd.LoadInt16x8Slice(z)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint16x8Ternary(t *testing.T, f func(_, _, _ simd.Uint16x8) simd.Uint16x8, want func(_, _, _ []uint16) []uint16) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x8Slice(x)
|
||||||
|
b := simd.LoadUint16x8Slice(y)
|
||||||
|
c := simd.LoadUint16x8Slice(z)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x4Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt32x4Ternary(t *testing.T, f func(_, _, _ simd.Int32x4) simd.Int32x4, want func(_, _, _ []int32) []int32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int32s, n, func(x, y, z []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x4Slice(x)
|
||||||
|
b := simd.LoadInt32x4Slice(y)
|
||||||
|
c := simd.LoadInt32x4Slice(z)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x4Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint32x4Ternary(t *testing.T, f func(_, _, _ simd.Uint32x4) simd.Uint32x4, want func(_, _, _ []uint32) []uint32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x4Slice(x)
|
||||||
|
b := simd.LoadUint32x4Slice(y)
|
||||||
|
c := simd.LoadUint32x4Slice(z)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x2Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt64x2Ternary(t *testing.T, f func(_, _, _ simd.Int64x2) simd.Int64x2, want func(_, _, _ []int64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int64s, n, func(x, y, z []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x2Slice(x)
|
||||||
|
b := simd.LoadInt64x2Slice(y)
|
||||||
|
c := simd.LoadInt64x2Slice(z)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x2Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint64x2Ternary(t *testing.T, f func(_, _, _ simd.Uint64x2) simd.Uint64x2, want func(_, _, _ []uint64) []uint64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x2Slice(x)
|
||||||
|
b := simd.LoadUint64x2Slice(y)
|
||||||
|
c := simd.LoadUint64x2Slice(z)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x4Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x4Ternary(t *testing.T, f func(_, _, _ simd.Float32x4) simd.Float32x4, want func(_, _, _ []float32) []float32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x4Slice(x)
|
||||||
|
b := simd.LoadFloat32x4Slice(y)
|
||||||
|
c := simd.LoadFloat32x4Slice(z)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x2Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x2Ternary(t *testing.T, f func(_, _, _ simd.Float64x2) simd.Float64x2, want func(_, _, _ []float64) []float64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, float64s, n, func(x, y, z []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x2Slice(x)
|
||||||
|
b := simd.LoadFloat64x2Slice(y)
|
||||||
|
c := simd.LoadFloat64x2Slice(z)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x32Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt8x32Ternary(t *testing.T, f func(_, _, _ simd.Int8x32) simd.Int8x32, want func(_, _, _ []int8) []int8) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int8s, n, func(x, y, z []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x32Slice(x)
|
||||||
|
b := simd.LoadInt8x32Slice(y)
|
||||||
|
c := simd.LoadInt8x32Slice(z)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x32Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint8x32Ternary(t *testing.T, f func(_, _, _ simd.Uint8x32) simd.Uint8x32, want func(_, _, _ []uint8) []uint8) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x32Slice(x)
|
||||||
|
b := simd.LoadUint8x32Slice(y)
|
||||||
|
c := simd.LoadUint8x32Slice(z)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt16x16Ternary(t *testing.T, f func(_, _, _ simd.Int16x16) simd.Int16x16, want func(_, _, _ []int16) []int16) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int16s, n, func(x, y, z []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x16Slice(x)
|
||||||
|
b := simd.LoadInt16x16Slice(y)
|
||||||
|
c := simd.LoadInt16x16Slice(z)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint16x16Ternary(t *testing.T, f func(_, _, _ simd.Uint16x16) simd.Uint16x16, want func(_, _, _ []uint16) []uint16) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x16Slice(x)
|
||||||
|
b := simd.LoadUint16x16Slice(y)
|
||||||
|
c := simd.LoadUint16x16Slice(z)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt32x8Ternary(t *testing.T, f func(_, _, _ simd.Int32x8) simd.Int32x8, want func(_, _, _ []int32) []int32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int32s, n, func(x, y, z []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x8Slice(x)
|
||||||
|
b := simd.LoadInt32x8Slice(y)
|
||||||
|
c := simd.LoadInt32x8Slice(z)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint32x8Ternary(t *testing.T, f func(_, _, _ simd.Uint32x8) simd.Uint32x8, want func(_, _, _ []uint32) []uint32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x8Slice(x)
|
||||||
|
b := simd.LoadUint32x8Slice(y)
|
||||||
|
c := simd.LoadUint32x8Slice(z)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x4Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt64x4Ternary(t *testing.T, f func(_, _, _ simd.Int64x4) simd.Int64x4, want func(_, _, _ []int64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int64s, n, func(x, y, z []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x4Slice(x)
|
||||||
|
b := simd.LoadInt64x4Slice(y)
|
||||||
|
c := simd.LoadInt64x4Slice(z)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x4Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint64x4Ternary(t *testing.T, f func(_, _, _ simd.Uint64x4) simd.Uint64x4, want func(_, _, _ []uint64) []uint64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x4Slice(x)
|
||||||
|
b := simd.LoadUint64x4Slice(y)
|
||||||
|
c := simd.LoadUint64x4Slice(z)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x8Ternary(t *testing.T, f func(_, _, _ simd.Float32x8) simd.Float32x8, want func(_, _, _ []float32) []float32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x8Slice(x)
|
||||||
|
b := simd.LoadFloat32x8Slice(y)
|
||||||
|
c := simd.LoadFloat32x8Slice(z)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x4Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x4Ternary(t *testing.T, f func(_, _, _ simd.Float64x4) simd.Float64x4, want func(_, _, _ []float64) []float64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, float64s, n, func(x, y, z []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x4Slice(x)
|
||||||
|
b := simd.LoadFloat64x4Slice(y)
|
||||||
|
c := simd.LoadFloat64x4Slice(z)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x64Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt8x64Ternary(t *testing.T, f func(_, _, _ simd.Int8x64) simd.Int8x64, want func(_, _, _ []int8) []int8) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int8s, n, func(x, y, z []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x64Slice(x)
|
||||||
|
b := simd.LoadInt8x64Slice(y)
|
||||||
|
c := simd.LoadInt8x64Slice(z)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x64Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint8x64Ternary(t *testing.T, f func(_, _, _ simd.Uint8x64) simd.Uint8x64, want func(_, _, _ []uint8) []uint8) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint8s, n, func(x, y, z []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x64Slice(x)
|
||||||
|
b := simd.LoadUint8x64Slice(y)
|
||||||
|
c := simd.LoadUint8x64Slice(z)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x32Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt16x32Ternary(t *testing.T, f func(_, _, _ simd.Int16x32) simd.Int16x32, want func(_, _, _ []int16) []int16) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int16s, n, func(x, y, z []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x32Slice(x)
|
||||||
|
b := simd.LoadInt16x32Slice(y)
|
||||||
|
c := simd.LoadInt16x32Slice(z)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x32Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint16x32Ternary(t *testing.T, f func(_, _, _ simd.Uint16x32) simd.Uint16x32, want func(_, _, _ []uint16) []uint16) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint16s, n, func(x, y, z []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x32Slice(x)
|
||||||
|
b := simd.LoadUint16x32Slice(y)
|
||||||
|
c := simd.LoadUint16x32Slice(z)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt32x16Ternary(t *testing.T, f func(_, _, _ simd.Int32x16) simd.Int32x16, want func(_, _, _ []int32) []int32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int32s, n, func(x, y, z []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x16Slice(x)
|
||||||
|
b := simd.LoadInt32x16Slice(y)
|
||||||
|
c := simd.LoadInt32x16Slice(z)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint32x16Ternary(t *testing.T, f func(_, _, _ simd.Uint32x16) simd.Uint32x16, want func(_, _, _ []uint32) []uint32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint32s, n, func(x, y, z []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x16Slice(x)
|
||||||
|
b := simd.LoadUint32x16Slice(y)
|
||||||
|
c := simd.LoadUint32x16Slice(z)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testInt64x8Ternary(t *testing.T, f func(_, _, _ simd.Int64x8) simd.Int64x8, want func(_, _, _ []int64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, int64s, n, func(x, y, z []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x8Slice(x)
|
||||||
|
b := simd.LoadInt64x8Slice(y)
|
||||||
|
c := simd.LoadInt64x8Slice(z)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testUint64x8Ternary(t *testing.T, f func(_, _, _ simd.Uint64x8) simd.Uint64x8, want func(_, _, _ []uint64) []uint64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, uint64s, n, func(x, y, z []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x8Slice(x)
|
||||||
|
b := simd.LoadUint64x8Slice(y)
|
||||||
|
c := simd.LoadUint64x8Slice(z)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x16Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x16Ternary(t *testing.T, f func(_, _, _ simd.Float32x16) simd.Float32x16, want func(_, _, _ []float32) []float32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x16Slice(x)
|
||||||
|
b := simd.LoadFloat32x16Slice(y)
|
||||||
|
c := simd.LoadFloat32x16Slice(z)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x8Ternary tests the simd ternary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x8Ternary(t *testing.T, f func(_, _, _ simd.Float64x8) simd.Float64x8, want func(_, _, _ []float64) []float64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSliceTriple(t, float64s, n, func(x, y, z []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x8Slice(x)
|
||||||
|
b := simd.LoadFloat64x8Slice(y)
|
||||||
|
c := simd.LoadFloat64x8Slice(z)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a, b, c).StoreSlice(g)
|
||||||
|
w := want(x, y, z)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
|
||||||
|
})
|
||||||
|
}
|
||||||
23
src/simd/ternary_test.go
Normal file
23
src/simd/ternary_test.go
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd && amd64
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFMA(t *testing.T) {
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x4Ternary(t, simd.Float32x4.FusedMultiplyAdd, fmaSlice[float32])
|
||||||
|
testFloat32x8Ternary(t, simd.Float32x8.FusedMultiplyAdd, fmaSlice[float32])
|
||||||
|
testFloat32x16Ternary(t, simd.Float32x16.FusedMultiplyAdd, fmaSlice[float32])
|
||||||
|
testFloat64x2Ternary(t, simd.Float64x2.FusedMultiplyAdd, fmaSlice[float64])
|
||||||
|
testFloat64x4Ternary(t, simd.Float64x4.FusedMultiplyAdd, fmaSlice[float64])
|
||||||
|
testFloat64x8Ternary(t, simd.Float64x8.FusedMultiplyAdd, fmaSlice[float64])
|
||||||
|
}
|
||||||
|
}
|
||||||
434
src/simd/unary_helpers_test.go
Normal file
434
src/simd/unary_helpers_test.go
Normal file
|
|
@ -0,0 +1,434 @@
|
||||||
|
// Code generated by 'go run genfiles.go'; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd
|
||||||
|
|
||||||
|
// This file contains functions testing unary simd methods.
|
||||||
|
// Each function in this file is specialized for a
|
||||||
|
// particular simd type <BaseType><Width>x<Count>.
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testInt8x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt8x16Unary(t *testing.T, f func(_ simd.Int8x16) simd.Int8x16, want func(_ []int8) []int8) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int8s, n, func(x []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x16Slice(x)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint8x16Unary(t *testing.T, f func(_ simd.Uint8x16) simd.Uint8x16, want func(_ []uint8) []uint8) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint8s, n, func(x []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x16Slice(x)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt16x8Unary(t *testing.T, f func(_ simd.Int16x8) simd.Int16x8, want func(_ []int16) []int16) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int16s, n, func(x []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x8Slice(x)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint16x8Unary(t *testing.T, f func(_ simd.Uint16x8) simd.Uint16x8, want func(_ []uint16) []uint16) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint16s, n, func(x []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x8Slice(x)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x4Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt32x4Unary(t *testing.T, f func(_ simd.Int32x4) simd.Int32x4, want func(_ []int32) []int32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int32s, n, func(x []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x4Slice(x)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x4Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint32x4Unary(t *testing.T, f func(_ simd.Uint32x4) simd.Uint32x4, want func(_ []uint32) []uint32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint32s, n, func(x []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x4Slice(x)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x2Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt64x2Unary(t *testing.T, f func(_ simd.Int64x2) simd.Int64x2, want func(_ []int64) []int64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int64s, n, func(x []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x2Slice(x)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x2Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint64x2Unary(t *testing.T, f func(_ simd.Uint64x2) simd.Uint64x2, want func(_ []uint64) []uint64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint64s, n, func(x []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x2Slice(x)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x4Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x4Unary(t *testing.T, f func(_ simd.Float32x4) simd.Float32x4, want func(_ []float32) []float32) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, float32s, n, func(x []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x4Slice(x)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x2Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x2Unary(t *testing.T, f func(_ simd.Float64x2) simd.Float64x2, want func(_ []float64) []float64) {
|
||||||
|
n := 2
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, float64s, n, func(x []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x2Slice(x)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x32Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt8x32Unary(t *testing.T, f func(_ simd.Int8x32) simd.Int8x32, want func(_ []int8) []int8) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int8s, n, func(x []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x32Slice(x)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x32Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint8x32Unary(t *testing.T, f func(_ simd.Uint8x32) simd.Uint8x32, want func(_ []uint8) []uint8) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint8s, n, func(x []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x32Slice(x)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt16x16Unary(t *testing.T, f func(_ simd.Int16x16) simd.Int16x16, want func(_ []int16) []int16) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int16s, n, func(x []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x16Slice(x)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint16x16Unary(t *testing.T, f func(_ simd.Uint16x16) simd.Uint16x16, want func(_ []uint16) []uint16) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint16s, n, func(x []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x16Slice(x)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt32x8Unary(t *testing.T, f func(_ simd.Int32x8) simd.Int32x8, want func(_ []int32) []int32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int32s, n, func(x []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x8Slice(x)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint32x8Unary(t *testing.T, f func(_ simd.Uint32x8) simd.Uint32x8, want func(_ []uint32) []uint32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint32s, n, func(x []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x8Slice(x)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x4Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt64x4Unary(t *testing.T, f func(_ simd.Int64x4) simd.Int64x4, want func(_ []int64) []int64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int64s, n, func(x []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x4Slice(x)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x4Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint64x4Unary(t *testing.T, f func(_ simd.Uint64x4) simd.Uint64x4, want func(_ []uint64) []uint64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint64s, n, func(x []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x4Slice(x)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x8Unary(t *testing.T, f func(_ simd.Float32x8) simd.Float32x8, want func(_ []float32) []float32) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, float32s, n, func(x []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x8Slice(x)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x4Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x4Unary(t *testing.T, f func(_ simd.Float64x4) simd.Float64x4, want func(_ []float64) []float64) {
|
||||||
|
n := 4
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, float64s, n, func(x []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x4Slice(x)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt8x64Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt8x64Unary(t *testing.T, f func(_ simd.Int8x64) simd.Int8x64, want func(_ []int8) []int8) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int8s, n, func(x []int8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt8x64Slice(x)
|
||||||
|
g := make([]int8, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint8x64Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint8x64Unary(t *testing.T, f func(_ simd.Uint8x64) simd.Uint8x64, want func(_ []uint8) []uint8) {
|
||||||
|
n := 64
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint8s, n, func(x []uint8) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint8x64Slice(x)
|
||||||
|
g := make([]uint8, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt16x32Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt16x32Unary(t *testing.T, f func(_ simd.Int16x32) simd.Int16x32, want func(_ []int16) []int16) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int16s, n, func(x []int16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt16x32Slice(x)
|
||||||
|
g := make([]int16, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint16x32Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint16x32Unary(t *testing.T, f func(_ simd.Uint16x32) simd.Uint16x32, want func(_ []uint16) []uint16) {
|
||||||
|
n := 32
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint16s, n, func(x []uint16) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint16x32Slice(x)
|
||||||
|
g := make([]uint16, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt32x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt32x16Unary(t *testing.T, f func(_ simd.Int32x16) simd.Int32x16, want func(_ []int32) []int32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int32s, n, func(x []int32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt32x16Slice(x)
|
||||||
|
g := make([]int32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint32x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint32x16Unary(t *testing.T, f func(_ simd.Uint32x16) simd.Uint32x16, want func(_ []uint32) []uint32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint32s, n, func(x []uint32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint32x16Slice(x)
|
||||||
|
g := make([]uint32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testInt64x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testInt64x8Unary(t *testing.T, f func(_ simd.Int64x8) simd.Int64x8, want func(_ []int64) []int64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, int64s, n, func(x []int64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadInt64x8Slice(x)
|
||||||
|
g := make([]int64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testUint64x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testUint64x8Unary(t *testing.T, f func(_ simd.Uint64x8) simd.Uint64x8, want func(_ []uint64) []uint64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, uint64s, n, func(x []uint64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadUint64x8Slice(x)
|
||||||
|
g := make([]uint64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat32x16Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testFloat32x16Unary(t *testing.T, f func(_ simd.Float32x16) simd.Float32x16, want func(_ []float32) []float32) {
|
||||||
|
n := 16
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, float32s, n, func(x []float32) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat32x16Slice(x)
|
||||||
|
g := make([]float32, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// testFloat64x8Unary tests the simd unary method f against the expected behavior generated by want
|
||||||
|
func testFloat64x8Unary(t *testing.T, f func(_ simd.Float64x8) simd.Float64x8, want func(_ []float64) []float64) {
|
||||||
|
n := 8
|
||||||
|
t.Helper()
|
||||||
|
forSlice(t, float64s, n, func(x []float64) bool {
|
||||||
|
t.Helper()
|
||||||
|
a := simd.LoadFloat64x8Slice(x)
|
||||||
|
g := make([]float64, n)
|
||||||
|
f(a).StoreSlice(g)
|
||||||
|
w := want(x)
|
||||||
|
return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
|
||||||
|
})
|
||||||
|
}
|
||||||
84
src/simd/unary_test.go
Normal file
84
src/simd/unary_test.go
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build goexperiment.simd && amd64
|
||||||
|
|
||||||
|
package simd_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"simd"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCeil(t *testing.T) {
|
||||||
|
testFloat32x4Unary(t, simd.Float32x4.Ceil, ceilSlice[float32])
|
||||||
|
testFloat32x8Unary(t, simd.Float32x8.Ceil, ceilSlice[float32])
|
||||||
|
testFloat64x2Unary(t, simd.Float64x2.Ceil, ceilSlice[float64])
|
||||||
|
testFloat64x4Unary(t, simd.Float64x4.Ceil, ceilSlice[float64])
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testFloat32x16Unary(t, simd.Float32x16.Ceil, ceilSlice[float32]) // missing
|
||||||
|
// testFloat64x8Unary(t, simd.Float64x8.Ceil, ceilSlice[float64]) // missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFloor(t *testing.T) {
|
||||||
|
testFloat32x4Unary(t, simd.Float32x4.Floor, floorSlice[float32])
|
||||||
|
testFloat32x8Unary(t, simd.Float32x8.Floor, floorSlice[float32])
|
||||||
|
testFloat64x2Unary(t, simd.Float64x2.Floor, floorSlice[float64])
|
||||||
|
testFloat64x4Unary(t, simd.Float64x4.Floor, floorSlice[float64])
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testFloat32x16Unary(t, simd.Float32x16.Floor, floorSlice[float32]) // missing
|
||||||
|
// testFloat64x8Unary(t, simd.Float64x8.Floor, floorSlice[float64]) // missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTrunc(t *testing.T) {
|
||||||
|
testFloat32x4Unary(t, simd.Float32x4.Trunc, truncSlice[float32])
|
||||||
|
testFloat32x8Unary(t, simd.Float32x8.Trunc, truncSlice[float32])
|
||||||
|
testFloat64x2Unary(t, simd.Float64x2.Trunc, truncSlice[float64])
|
||||||
|
testFloat64x4Unary(t, simd.Float64x4.Trunc, truncSlice[float64])
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testFloat32x16Unary(t, simd.Float32x16.Trunc, truncSlice[float32]) // missing
|
||||||
|
// testFloat64x8Unary(t, simd.Float64x8.Trunc, truncSlice[float64]) // missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRound(t *testing.T) {
|
||||||
|
testFloat32x4Unary(t, simd.Float32x4.Round, roundSlice[float32])
|
||||||
|
testFloat32x8Unary(t, simd.Float32x8.Round, roundSlice[float32])
|
||||||
|
testFloat64x2Unary(t, simd.Float64x2.Round, roundSlice[float64])
|
||||||
|
testFloat64x4Unary(t, simd.Float64x4.Round, roundSlice[float64])
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
// testFloat32x16Unary(t, simd.Float32x16.Round, roundSlice[float32]) // missing
|
||||||
|
// testFloat64x8Unary(t, simd.Float64x8.Round, roundSlice[float64]) // missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSqrt(t *testing.T) {
|
||||||
|
testFloat32x4Unary(t, simd.Float32x4.Sqrt, sqrtSlice[float32])
|
||||||
|
testFloat32x8Unary(t, simd.Float32x8.Sqrt, sqrtSlice[float32])
|
||||||
|
testFloat64x2Unary(t, simd.Float64x2.Sqrt, sqrtSlice[float64])
|
||||||
|
testFloat64x4Unary(t, simd.Float64x4.Sqrt, sqrtSlice[float64])
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testFloat32x16Unary(t, simd.Float32x16.Sqrt, sqrtSlice[float32])
|
||||||
|
testFloat64x8Unary(t, simd.Float64x8.Sqrt, sqrtSlice[float64])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAbsolute(t *testing.T) {
|
||||||
|
testInt8x16Unary(t, simd.Int8x16.Absolute, map1[int8](abs))
|
||||||
|
testInt8x32Unary(t, simd.Int8x32.Absolute, map1[int8](abs))
|
||||||
|
testInt16x8Unary(t, simd.Int16x8.Absolute, map1[int16](abs))
|
||||||
|
testInt16x16Unary(t, simd.Int16x16.Absolute, map1[int16](abs))
|
||||||
|
testInt32x4Unary(t, simd.Int32x4.Absolute, map1[int32](abs))
|
||||||
|
testInt32x8Unary(t, simd.Int32x8.Absolute, map1[int32](abs))
|
||||||
|
if simd.HasAVX512() {
|
||||||
|
testInt8x64Unary(t, simd.Int8x64.Absolute, map1[int8](abs))
|
||||||
|
testInt16x32Unary(t, simd.Int16x32.Absolute, map1[int16](abs))
|
||||||
|
testInt32x16Unary(t, simd.Int32x16.Absolute, map1[int32](abs))
|
||||||
|
testInt64x2Unary(t, simd.Int64x2.Absolute, map1[int64](abs))
|
||||||
|
testInt64x4Unary(t, simd.Int64x4.Absolute, map1[int64](abs))
|
||||||
|
testInt64x8Unary(t, simd.Int64x8.Absolute, map1[int64](abs))
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue