[dev.simd] simd: add testing hooks for size-changing conversions

and adds some tests of size-changing conversions.

IMO the template naming conventions in genfiles
are getting grubby, and I plan to change them in
an immediately following CL.

Change-Id: I4a72e8a8c9e9806fab60570dff4c87a754e427c5
Reviewed-on: https://go-review.googlesource.com/c/go/+/697456
Commit-Queue: David Chase <drchase@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
TryBot-Bypass: David Chase <drchase@google.com>
This commit is contained in:
David Chase 2025-08-19 15:26:19 -04:00
parent ede64cf0d8
commit af6475df73
4 changed files with 963 additions and 66 deletions

View file

@ -21,12 +21,15 @@ import (
"text/template"
)
type resultTypeFunc func(t string, w, c int) (ot string, ow int, oc int)
// shapes describes a combination of vector widths and various element types
type shapes struct {
vecs []int // Vector bit width for this shape.
ints []int // Int element bit width(s) for this shape
uints []int // Unsigned int element bit width(s) for this shape
floats []int // Float element bit width(s) for this shape
output resultTypeFunc
}
// shapeAndTemplate is a template and the set of shapes on which it will be expanded
@ -35,6 +38,26 @@ type shapeAndTemplate struct {
t *template.Template
}
func (sat shapeAndTemplate) target(outType string, width int) shapeAndTemplate {
newSat := sat
newShape := *sat.s
newShape.output = func(t string, w, c int) (ot string, ow int, oc int) {
return outType, width, c
}
newSat.s = &newShape
return newSat
}
func (sat shapeAndTemplate) shrinkTo(outType string, by int) shapeAndTemplate {
newSat := sat
newShape := *sat.s
newShape.output = func(t string, w, c int) (ot string, ow int, oc int) {
return outType, w / by, c * by
}
newSat.s = &newShape
return newSat
}
var allShapes = &shapes{
vecs: []int{128, 256, 512},
ints: []int{8, 16, 32, 64},
@ -42,14 +65,6 @@ var allShapes = &shapes{
floats: []int{32, 64},
}
// these are the shapes that are currently converted to int32
// (not all conversions are available, yet)
var convert32Shapes = &shapes{
vecs: []int{128, 256, 512},
floats: []int{32},
}
var avx512Shapes = &shapes{
vecs: []int{512},
ints: []int{8, 16, 32, 64},
@ -108,22 +123,44 @@ type templateData struct {
Base string // the capitalized Base Type of the vector, e.g., "Float"
Type string // the element type, e.g. "float32"
OxFF string // a mask for the lowest 'count' bits
Ovec string
Otype string
OType string
Ocount int
}
func (t templateData) As128BitVec() string {
return fmt.Sprintf("%s%dx%d", t.Base, t.Width, 128/t.Width)
}
func oneTemplate(t *template.Template, baseType string, width, count int, out io.Writer) {
func oneTemplate(t *template.Template, baseType string, width, count int, out io.Writer, rtf resultTypeFunc) {
b := width * count
if b < 128 || b > 512 {
return
}
BaseType := strings.ToUpper(baseType[:1]) + baseType[1:]
eType := fmt.Sprintf("%s%d", baseType, width)
ot, ow, oc := baseType, width, count
if rtf != nil {
ot, ow, oc = rtf(ot, ow, oc)
if ow*oc > 512 || ow*oc < 128 || ow < 8 || ow > 64 {
return
}
// TODO someday we will support conversions to 16-bit floats
if ot == "float" && ow < 32 {
return
}
}
ovType := fmt.Sprintf("%s%dx%d", strings.ToUpper(ot[:1])+ot[1:], ow, oc)
oeType := fmt.Sprintf("%s%d", ot, ow)
oEType := fmt.Sprintf("%s%d", strings.ToUpper(ot[:1])+ot[1:], ow)
wxc := fmt.Sprintf("%dx%d", width, count)
bxc := fmt.Sprintf("%dx%d", 8, count*(width/8))
BaseType := strings.ToUpper(baseType[:1]) + baseType[1:]
vType := fmt.Sprintf("%s%s", BaseType, wxc)
eType := fmt.Sprintf("%s%d", baseType, width)
bxc := fmt.Sprintf("%dx%d", 8, count*(width/8))
aOrAn := "a"
if strings.Contains("aeiou", baseType[:1]) {
aOrAn = "an"
@ -140,6 +177,10 @@ func oneTemplate(t *template.Template, baseType string, width, count int, out io
Base: BaseType,
Type: eType,
OxFF: oxFF,
Ovec: ovType,
Otype: oeType,
Ocount: oc,
OType: oEType,
})
}
@ -154,15 +195,15 @@ func (sat shapeAndTemplate) forTemplates(out io.Writer) {
for _, v := range vecs {
for _, w := range ints {
c := v / w
oneTemplate(t, "int", w, c, out)
oneTemplate(t, "int", w, c, out, sat.s.output)
}
for _, w := range uints {
c := v / w
oneTemplate(t, "uint", w, c, out)
oneTemplate(t, "uint", w, c, out, sat.s.output)
}
for _, w := range floats {
c := v / w
oneTemplate(t, "float", w, c, out)
oneTemplate(t, "float", w, c, out, sat.s.output)
}
}
}
@ -271,15 +312,16 @@ func test{{.Vec}}UnaryFlaky(t *testing.T, f func(x simd.{{.Vec}}) simd.{{.Vec}},
}
`)
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) {
var convertTemplate = templateOf("convert_helpers", `
// test{{.Vec}}ConvertTo{{.OType}} tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func test{{.Vec}}ConvertTo{{.OType}}(t *testing.T, f func(x simd.{{.Vec}}) simd.{{.Ovec}}, want func(x []{{.Type}}) []{{.Otype}}) {
n := {{.Count}}
t.Helper()
forSlice(t, {{.Type}}s, n, func(x []{{.Type}}) bool {
t.Helper()
a := simd.Load{{.Vec}}Slice(x)
g := make([]int32, n)
g := make([]{{.Otype}}, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
@ -287,21 +329,9 @@ func test{{.Vec}}UnaryToInt32(t *testing.T, f func(x simd.{{.Vec}}) simd.Int32x{
}
`)
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, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
})
}
`)
var unaryToInt32 = convertTemplate.target("int", 32)
var unaryToUint32 = convertTemplate.target("uint", 32)
var unaryToUint16 = convertTemplate.target("uint", 16)
var binaryTemplate = templateOf("binary_helpers", `
// test{{.Vec}}Binary tests the simd binary method f against the expected behavior generated by want
@ -755,7 +785,7 @@ func main() {
one(*ush, unsafePrologue, unsafePATemplate)
}
if *uh != "" {
one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryTemplateToInt32, unaryTemplateToUint32, unaryFlakyTemplate)
one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryToInt32, unaryToUint32, unaryToUint16, unaryFlakyTemplate)
}
if *bh != "" {
one(*bh, curryTestPrologue("binary simd methods"), binaryTemplate)

View file

@ -32,7 +32,7 @@ func notEqual[T number](x, y T) bool {
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
return 0 // this is not a negative zero
}
if x < 0 {
return -x
@ -108,8 +108,16 @@ func fma[T float](x, y, z T) T {
return T(math.FMA(float64(x), float64(y), float64(z)))
}
func toInt32[T number](x T) int32 {
return int32(x)
func toUint8[T number](x T) uint8 {
return uint8(x)
}
func toUint16[T number](x T) uint16 {
return uint16(x)
}
func toUint64[T number](x T) uint64 {
return uint64(x)
}
func toUint32[T number](x T) uint32 {
@ -126,6 +134,30 @@ func toUint32[T number](x T) uint32 {
return uint32(x)
}
func toInt8[T number](x T) int8 {
return int8(x)
}
func toInt16[T number](x T) int16 {
return int16(x)
}
func toInt32[T number](x T) int32 {
return int32(x)
}
func toInt64[T number](x T) int64 {
return int64(x)
}
func toFloat32[T number](x T) float32 {
return float32(x)
}
func toFloat64[T number](x T) float64 {
return float64(x)
}
func ceilResidueForPrecision[T float](i int) func(T) T {
f := 1.0
for i > 0 {
@ -240,11 +272,3 @@ func imaSlice[T integer](x, y, z []T) []T {
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)
}

View file

@ -433,8 +433,99 @@ func testFloat64x8Unary(t *testing.T, f func(_ simd.Float64x8) simd.Float64x8, w
})
}
// 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) {
// testInt8x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt8x16ConvertToInt32(t *testing.T, f func(x simd.Int8x16) simd.Int32x16, want func(x []int8) []int32) {
n := 16
t.Helper()
forSlice(t, int8s, n, func(x []int8) bool {
t.Helper()
a := simd.LoadInt8x16Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt16x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x8ConvertToInt32(t *testing.T, f func(x simd.Int16x8) simd.Int32x8, want func(x []int16) []int32) {
n := 8
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x8Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x4ConvertToInt32(t *testing.T, f func(x simd.Int32x4) simd.Int32x4, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint8x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint8x16ConvertToInt32(t *testing.T, f func(x simd.Uint8x16) simd.Int32x16, want func(x []uint8) []int32) {
n := 16
t.Helper()
forSlice(t, uint8s, n, func(x []uint8) bool {
t.Helper()
a := simd.LoadUint8x16Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x8ConvertToInt32(t *testing.T, f func(x simd.Uint16x8) simd.Int32x8, want func(x []uint16) []int32) {
n := 8
t.Helper()
forSlice(t, uint16s, n, func(x []uint16) bool {
t.Helper()
a := simd.LoadUint16x8Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x4ConvertToInt32(t *testing.T, f func(x simd.Uint32x4) simd.Int32x4, want func(x []uint32) []int32) {
n := 4
t.Helper()
forSlice(t, uint32s, n, func(x []uint32) bool {
t.Helper()
a := simd.LoadUint32x4Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x4ConvertToInt32(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 {
@ -447,8 +538,99 @@ func testFloat32x4UnaryToInt32(t *testing.T, f func(x simd.Float32x4) simd.Int32
})
}
// 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) {
// testInt16x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x16ConvertToInt32(t *testing.T, f func(x simd.Int16x16) simd.Int32x16, want func(x []int16) []int32) {
n := 16
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x16Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x8ConvertToInt32(t *testing.T, f func(x simd.Int32x8) simd.Int32x8, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt64x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt64x4ConvertToInt32(t *testing.T, f func(x simd.Int64x4) simd.Int32x4, want func(x []int64) []int32) {
n := 4
t.Helper()
forSlice(t, int64s, n, func(x []int64) bool {
t.Helper()
a := simd.LoadInt64x4Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x16ConvertToInt32(t *testing.T, f func(x simd.Uint16x16) simd.Int32x16, want func(x []uint16) []int32) {
n := 16
t.Helper()
forSlice(t, uint16s, n, func(x []uint16) bool {
t.Helper()
a := simd.LoadUint16x16Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x8ConvertToInt32(t *testing.T, f func(x simd.Uint32x8) simd.Int32x8, want func(x []uint32) []int32) {
n := 8
t.Helper()
forSlice(t, uint32s, n, func(x []uint32) bool {
t.Helper()
a := simd.LoadUint32x8Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint64x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint64x4ConvertToInt32(t *testing.T, f func(x simd.Uint64x4) simd.Int32x4, want func(x []uint64) []int32) {
n := 4
t.Helper()
forSlice(t, uint64s, n, func(x []uint64) bool {
t.Helper()
a := simd.LoadUint64x4Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x8ConvertToInt32(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 {
@ -461,8 +643,84 @@ func testFloat32x8UnaryToInt32(t *testing.T, f func(x simd.Float32x8) simd.Int32
})
}
// 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) {
// testFloat64x4ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat64x4ConvertToInt32(t *testing.T, f func(x simd.Float64x4) simd.Int32x4, want func(x []float64) []int32) {
n := 4
t.Helper()
forSlice(t, float64s, n, func(x []float64) bool {
t.Helper()
a := simd.LoadFloat64x4Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x16ConvertToInt32(t *testing.T, f func(x simd.Int32x16) simd.Int32x16, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt64x8ConvertToInt32(t *testing.T, f func(x simd.Int64x8) simd.Int32x8, want func(x []int64) []int32) {
n := 8
t.Helper()
forSlice(t, int64s, n, func(x []int64) bool {
t.Helper()
a := simd.LoadInt64x8Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x16ConvertToInt32(t *testing.T, f func(x simd.Uint32x16) simd.Int32x16, want func(x []uint32) []int32) {
n := 16
t.Helper()
forSlice(t, uint32s, n, func(x []uint32) bool {
t.Helper()
a := simd.LoadUint32x16Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint64x8ConvertToInt32(t *testing.T, f func(x simd.Uint64x8) simd.Int32x8, want func(x []uint64) []int32) {
n := 8
t.Helper()
forSlice(t, uint64s, n, func(x []uint64) bool {
t.Helper()
a := simd.LoadUint64x8Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x16ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x16ConvertToInt32(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 {
@ -475,8 +733,114 @@ func testFloat32x16UnaryToInt32(t *testing.T, f func(x simd.Float32x16) simd.Int
})
}
// 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) {
// testFloat64x8ConvertToInt32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat64x8ConvertToInt32(t *testing.T, f func(x simd.Float64x8) simd.Int32x8, want func(x []float64) []int32) {
n := 8
t.Helper()
forSlice(t, float64s, n, func(x []float64) bool {
t.Helper()
a := simd.LoadFloat64x8Slice(x)
g := make([]int32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt8x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt8x16ConvertToUint32(t *testing.T, f func(x simd.Int8x16) simd.Uint32x16, want func(x []int8) []uint32) {
n := 16
t.Helper()
forSlice(t, int8s, n, func(x []int8) bool {
t.Helper()
a := simd.LoadInt8x16Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt16x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x8ConvertToUint32(t *testing.T, f func(x simd.Int16x8) simd.Uint32x8, want func(x []int16) []uint32) {
n := 8
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x8Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x4ConvertToUint32(t *testing.T, f func(x simd.Int32x4) simd.Uint32x4, want func(x []int32) []uint32) {
n := 4
t.Helper()
forSlice(t, int32s, n, func(x []int32) bool {
t.Helper()
a := simd.LoadInt32x4Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint8x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint8x16ConvertToUint32(t *testing.T, f func(x simd.Uint8x16) simd.Uint32x16, want func(x []uint8) []uint32) {
n := 16
t.Helper()
forSlice(t, uint8s, n, func(x []uint8) bool {
t.Helper()
a := simd.LoadUint8x16Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x8ConvertToUint32(t *testing.T, f func(x simd.Uint16x8) simd.Uint32x8, want func(x []uint16) []uint32) {
n := 8
t.Helper()
forSlice(t, uint16s, n, func(x []uint16) bool {
t.Helper()
a := simd.LoadUint16x8Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x4ConvertToUint32(t *testing.T, f func(x simd.Uint32x4) simd.Uint32x4, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x4ConvertToUint32(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 {
@ -489,8 +853,99 @@ func testFloat32x4UnaryToUint32(t *testing.T, f func(x simd.Float32x4) simd.Uint
})
}
// 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) {
// testInt16x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x16ConvertToUint32(t *testing.T, f func(x simd.Int16x16) simd.Uint32x16, want func(x []int16) []uint32) {
n := 16
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x16Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x8ConvertToUint32(t *testing.T, f func(x simd.Int32x8) simd.Uint32x8, want func(x []int32) []uint32) {
n := 8
t.Helper()
forSlice(t, int32s, n, func(x []int32) bool {
t.Helper()
a := simd.LoadInt32x8Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt64x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt64x4ConvertToUint32(t *testing.T, f func(x simd.Int64x4) simd.Uint32x4, want func(x []int64) []uint32) {
n := 4
t.Helper()
forSlice(t, int64s, n, func(x []int64) bool {
t.Helper()
a := simd.LoadInt64x4Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x16ConvertToUint32(t *testing.T, f func(x simd.Uint16x16) simd.Uint32x16, want func(x []uint16) []uint32) {
n := 16
t.Helper()
forSlice(t, uint16s, n, func(x []uint16) bool {
t.Helper()
a := simd.LoadUint16x16Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x8ConvertToUint32(t *testing.T, f func(x simd.Uint32x8) simd.Uint32x8, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint64x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint64x4ConvertToUint32(t *testing.T, f func(x simd.Uint64x4) simd.Uint32x4, want func(x []uint64) []uint32) {
n := 4
t.Helper()
forSlice(t, uint64s, n, func(x []uint64) bool {
t.Helper()
a := simd.LoadUint64x4Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x8ConvertToUint32(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 {
@ -503,8 +958,84 @@ func testFloat32x8UnaryToUint32(t *testing.T, f func(x simd.Float32x8) simd.Uint
})
}
// 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) {
// testFloat64x4ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat64x4ConvertToUint32(t *testing.T, f func(x simd.Float64x4) simd.Uint32x4, want func(x []float64) []uint32) {
n := 4
t.Helper()
forSlice(t, float64s, n, func(x []float64) bool {
t.Helper()
a := simd.LoadFloat64x4Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x16ConvertToUint32(t *testing.T, f func(x simd.Int32x16) simd.Uint32x16, want func(x []int32) []uint32) {
n := 16
t.Helper()
forSlice(t, int32s, n, func(x []int32) bool {
t.Helper()
a := simd.LoadInt32x16Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt64x8ConvertToUint32(t *testing.T, f func(x simd.Int64x8) simd.Uint32x8, want func(x []int64) []uint32) {
n := 8
t.Helper()
forSlice(t, int64s, n, func(x []int64) bool {
t.Helper()
a := simd.LoadInt64x8Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x16ConvertToUint32(t *testing.T, f func(x simd.Uint32x16) simd.Uint32x16, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint64x8ConvertToUint32(t *testing.T, f func(x simd.Uint64x8) simd.Uint32x8, want func(x []uint64) []uint32) {
n := 8
t.Helper()
forSlice(t, uint64s, n, func(x []uint64) bool {
t.Helper()
a := simd.LoadUint64x8Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x16ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x16ConvertToUint32(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 {
@ -517,6 +1048,306 @@ func testFloat32x16UnaryToUint32(t *testing.T, f func(x simd.Float32x16) simd.Ui
})
}
// testFloat64x8ConvertToUint32 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat64x8ConvertToUint32(t *testing.T, f func(x simd.Float64x8) simd.Uint32x8, want func(x []float64) []uint32) {
n := 8
t.Helper()
forSlice(t, float64s, n, func(x []float64) bool {
t.Helper()
a := simd.LoadFloat64x8Slice(x)
g := make([]uint32, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt8x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt8x16ConvertToUint16(t *testing.T, f func(x simd.Int8x16) simd.Uint16x16, want func(x []int8) []uint16) {
n := 16
t.Helper()
forSlice(t, int8s, n, func(x []int8) bool {
t.Helper()
a := simd.LoadInt8x16Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x8ConvertToUint16(t *testing.T, f func(x simd.Int16x8) simd.Uint16x8, want func(x []int16) []uint16) {
n := 8
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint8x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint8x16ConvertToUint16(t *testing.T, f func(x simd.Uint8x16) simd.Uint16x16, want func(x []uint8) []uint16) {
n := 16
t.Helper()
forSlice(t, uint8s, n, func(x []uint8) bool {
t.Helper()
a := simd.LoadUint8x16Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x8ConvertToUint16(t *testing.T, f func(x simd.Uint16x8) simd.Uint16x8, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt8x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt8x32ConvertToUint16(t *testing.T, f func(x simd.Int8x32) simd.Uint16x32, want func(x []int8) []uint16) {
n := 32
t.Helper()
forSlice(t, int8s, n, func(x []int8) bool {
t.Helper()
a := simd.LoadInt8x32Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt16x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x16ConvertToUint16(t *testing.T, f func(x simd.Int16x16) simd.Uint16x16, want func(x []int16) []uint16) {
n := 16
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x16Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x8ConvertToUint16(t *testing.T, f func(x simd.Int32x8) simd.Uint16x8, want func(x []int32) []uint16) {
n := 8
t.Helper()
forSlice(t, int32s, n, func(x []int32) bool {
t.Helper()
a := simd.LoadInt32x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint8x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint8x32ConvertToUint16(t *testing.T, f func(x simd.Uint8x32) simd.Uint16x32, want func(x []uint8) []uint16) {
n := 32
t.Helper()
forSlice(t, uint8s, n, func(x []uint8) bool {
t.Helper()
a := simd.LoadUint8x32Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x16ConvertToUint16(t *testing.T, f func(x simd.Uint16x16) simd.Uint16x16, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x8ConvertToUint16(t *testing.T, f func(x simd.Uint32x8) simd.Uint16x8, want func(x []uint32) []uint16) {
n := 8
t.Helper()
forSlice(t, uint32s, n, func(x []uint32) bool {
t.Helper()
a := simd.LoadUint32x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x8ConvertToUint16(t *testing.T, f func(x simd.Float32x8) simd.Uint16x8, want func(x []float32) []uint16) {
n := 8
t.Helper()
forSlice(t, float32s, n, func(x []float32) bool {
t.Helper()
a := simd.LoadFloat32x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt16x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt16x32ConvertToUint16(t *testing.T, f func(x simd.Int16x32) simd.Uint16x32, want func(x []int16) []uint16) {
n := 32
t.Helper()
forSlice(t, int16s, n, func(x []int16) bool {
t.Helper()
a := simd.LoadInt16x32Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt32x16ConvertToUint16(t *testing.T, f func(x simd.Int32x16) simd.Uint16x16, want func(x []int32) []uint16) {
n := 16
t.Helper()
forSlice(t, int32s, n, func(x []int32) bool {
t.Helper()
a := simd.LoadInt32x16Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testInt64x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testInt64x8ConvertToUint16(t *testing.T, f func(x simd.Int64x8) simd.Uint16x8, want func(x []int64) []uint16) {
n := 8
t.Helper()
forSlice(t, int64s, n, func(x []int64) bool {
t.Helper()
a := simd.LoadInt64x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint16x32ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint16x32ConvertToUint16(t *testing.T, f func(x simd.Uint16x32) simd.Uint16x32, want func(x []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, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint32x16ConvertToUint16(t *testing.T, f func(x simd.Uint32x16) simd.Uint16x16, want func(x []uint32) []uint16) {
n := 16
t.Helper()
forSlice(t, uint32s, n, func(x []uint32) bool {
t.Helper()
a := simd.LoadUint32x16Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testUint64x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testUint64x8ConvertToUint16(t *testing.T, f func(x simd.Uint64x8) simd.Uint16x8, want func(x []uint64) []uint16) {
n := 8
t.Helper()
forSlice(t, uint64s, n, func(x []uint64) bool {
t.Helper()
a := simd.LoadUint64x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x16ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat32x16ConvertToUint16(t *testing.T, f func(x simd.Float32x16) simd.Uint16x16, want func(x []float32) []uint16) {
n := 16
t.Helper()
forSlice(t, float32s, n, func(x []float32) bool {
t.Helper()
a := simd.LoadFloat32x16Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat64x8ConvertToUint16 tests the simd conversion method f against the expected behavior generated by want
// This is for count-preserving conversions, so if there is a change in size, then there is a change in vector width.
func testFloat64x8ConvertToUint16(t *testing.T, f func(x simd.Float64x8) simd.Uint16x8, want func(x []float64) []uint16) {
n := 8
t.Helper()
forSlice(t, float64s, n, func(x []float64) bool {
t.Helper()
a := simd.LoadFloat64x8Slice(x)
g := make([]uint16, n)
f(a).StoreSlice(g)
w := want(x)
return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
})
}
// testFloat32x4UnaryFlaky tests the simd unary method f against the expected behavior generated by want,
// but using a flakiness parameter because we haven't exactly figured out how simd floating point works
func testFloat32x4UnaryFlaky(t *testing.T, f func(x simd.Float32x4) simd.Float32x4, want func(x []float32) []float32, flakiness float64) {

View file

@ -84,11 +84,6 @@ func TestAbsolute(t *testing.T) {
}
}
func TestToInt32(t *testing.T) {
testFloat32x4UnaryToInt32(t, simd.Float32x4.ConvertToInt32, toInt32Slice[float32])
testFloat32x8UnaryToInt32(t, simd.Float32x8.ConvertToInt32, toInt32Slice[float32])
}
func TestCeilScaledResidue(t *testing.T) {
if !simd.HasAVX512() {
t.Skip("Needs AVX512")
@ -110,7 +105,24 @@ 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])
testFloat32x4ConvertToUint32(t, simd.Float32x4.ConvertToUint32, map1[float32](toUint32))
testFloat32x8ConvertToUint32(t, simd.Float32x8.ConvertToUint32, map1[float32](toUint32))
testFloat32x16ConvertToUint32(t, simd.Float32x16.ConvertToUint32, map1[float32](toUint32))
}
func TestToInt32(t *testing.T) {
testFloat32x4ConvertToInt32(t, simd.Float32x4.ConvertToInt32, map1[float32](toInt32))
testFloat32x8ConvertToInt32(t, simd.Float32x8.ConvertToInt32, map1[float32](toInt32))
}
func TestConverts(t *testing.T) {
testUint8x16ConvertToUint16(t, simd.Uint8x16.ConvertToUint16, map1[uint8](toUint16))
testUint16x8ConvertToUint32(t, simd.Uint16x8.ConvertToUint32, map1[uint16](toUint32))
}
func TestConvertsAVX512(t *testing.T) {
if !simd.HasAVX512() {
t.Skip("Needs AVX512")
}
testUint8x32ConvertToUint16(t, simd.Uint8x32.ConvertToUint16, map1[uint8](toUint16))
}