// these are the shapes that are currently converted to int32
// (not all conversions are available, yet)
-var toInt32Shapes = &shapes{
+var convert32Shapes = &shapes{
vecs: []int{128, 256, 512},
floats: []int{32},
}
}
`)
-var unaryTemplateToInt32 = shapedTemplateOf(toInt32Shapes, "unary_int32_helpers", `
+var unaryTemplateToInt32 = shapedTemplateOf(convert32Shapes, "unary_int32_helpers", `
// test{{.Vec}}Unary tests the simd unary method f against the expected behavior generated by want
func test{{.Vec}}UnaryToInt32(t *testing.T, f func(x simd.{{.Vec}}) simd.Int32x{{.Count}}, want func(x []{{.Type}}) []int32) {
n := {{.Count}}
}
`)
+var unaryTemplateToUint32 = shapedTemplateOf(convert32Shapes, "unary_uint32_helpers", `
+// test{{.Vec}}Unary tests the simd unary method f against the expected behavior generated by want
+func test{{.Vec}}UnaryToUint32(t *testing.T, f func(x simd.{{.Vec}}) simd.Uint32x{{.Count}}, want func(x []{{.Type}}) []uint32) {
+ n := {{.Count}}
+ t.Helper()
+ forSlice(t, {{.Type}}s, n, func(x []{{.Type}}) bool {
+ t.Helper()
+ a := simd.Load{{.Vec}}Slice(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)})
+ })
+}
+`)
+
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}}) {
one(*sl, prologue, sliceTemplate)
}
if *uh != "" {
- one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate)
+ one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryTemplateToInt32, unaryTemplateToUint32)
}
if *bh != "" {
one(*bh, curryTestPrologue("binary simd methods"), binaryTemplate)
return T(math.FMA(float64(x), float64(y), float64(z)))
}
+func toInt32[T number](x T) int32 {
+ return int32(x)
+}
+
+func toUint32[T number](x T) uint32 {
+ switch y := (any(x)).(type) {
+ case float32:
+ if y < 0 || y > float32(math.MaxUint32) || y != y {
+ return math.MaxUint32
+ }
+ case float64:
+ if y < 0 || y > float64(math.MaxUint32) || y != y {
+ return math.MaxUint32
+ }
+ }
+ return uint32(x)
+}
+
+// Slice versions of all these elementwise operations
+
func addSlice[T number](x, y []T) []T {
return map2[T](add)(x, y)
}
func fmaSlice[T float](x, y, z []T) []T {
return map3[T](fma)(x, y, z)
}
+
+func toInt32Slice[T number](x []T) []int32 {
+ return map1[T](toInt32)(x)
+}
+
+func toUint32Slice[T number](x []T) []uint32 {
+ return map1[T](toUint32)(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 testFloat32x4UnaryToInt32(t *testing.T, f func(x simd.Float32x4) simd.Int32x4, want func(x []float32) []int32) {
+ n := 4
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x4Slice(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) })
+ })
+}
+
+// testFloat32x8Unary tests the simd unary method f against the expected behavior generated by want
+func testFloat32x8UnaryToInt32(t *testing.T, f func(x simd.Float32x8) simd.Int32x8, want func(x []float32) []int32) {
+ n := 8
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x8Slice(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) })
+ })
+}
+
+// testFloat32x16Unary tests the simd unary method f against the expected behavior generated by want
+func testFloat32x16UnaryToInt32(t *testing.T, f func(x simd.Float32x16) simd.Int32x16, want func(x []float32) []int32) {
+ n := 16
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x16Slice(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) })
+ })
+}
+
+// testFloat32x4Unary tests the simd unary method f against the expected behavior generated by want
+func testFloat32x4UnaryToUint32(t *testing.T, f func(x simd.Float32x4) simd.Uint32x4, want func(x []float32) []uint32) {
+ n := 4
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x4Slice(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) })
+ })
+}
+
+// testFloat32x8Unary tests the simd unary method f against the expected behavior generated by want
+func testFloat32x8UnaryToUint32(t *testing.T, f func(x simd.Float32x8) simd.Uint32x8, want func(x []float32) []uint32) {
+ n := 8
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x8Slice(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) })
+ })
+}
+
+// testFloat32x16Unary tests the simd unary method f against the expected behavior generated by want
+func testFloat32x16UnaryToUint32(t *testing.T, f func(x simd.Float32x16) simd.Uint32x16, want func(x []float32) []uint32) {
+ n := 16
+ t.Helper()
+ forSlice(t, float32s, n, func(x []float32) bool {
+ t.Helper()
+ a := simd.LoadFloat32x16Slice(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(t, simd.Int64x8.Absolute, map1[int64](abs))
}
}
+
+func TestToInt32(t *testing.T) {
+ testFloat32x4UnaryToInt32(t, simd.Float32x4.ConvertToInt32, toInt32Slice[float32])
+ testFloat32x8UnaryToInt32(t, simd.Float32x8.ConvertToInt32, toInt32Slice[float32])
+}
+
+func TestToUint32(t *testing.T) {
+ if !simd.HasAVX512() {
+ t.Skip("Needs AVX512")
+ }
+ testFloat32x4UnaryToUint32(t, simd.Float32x4.ConvertToUint32, toUint32Slice[float32])
+ testFloat32x8UnaryToUint32(t, simd.Float32x8.ConvertToUint32, toUint32Slice[float32])
+ testFloat32x16UnaryToUint32(t, simd.Float32x16.ConvertToUint32, toUint32Slice[float32])
+}