mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[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:
parent
ede64cf0d8
commit
af6475df73
4 changed files with 963 additions and 66 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue