]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.simd] simd: move lots of slice functions and methods to generated code
authorDavid Chase <drchase@google.com>
Fri, 25 Jul 2025 19:18:11 +0000 (15:18 -0400)
committerDavid Chase <drchase@google.com>
Mon, 4 Aug 2025 18:52:48 +0000 (11:52 -0700)
Lots of handwritten/stenciled code is now untouched by human hands

For certain combinations of operation-arity and type, there
is an option to use a flaky version of a test helper, that only
requires "close enough".  For example:

testFloat32x4TernaryFlaky(t, simd.Float32x4.FusedMultiplyAdd, fmaSlice[float32], 0.001)

Some of the quirkier operations have their behavior captured
in their test-simulation, for example, ceilResidue regards
infinities as integers (therefore their residue is zero).

Change-Id: I8242914e5ab399edbe226da8586988441cffa83f
Reviewed-on: https://go-review.googlesource.com/c/go/+/690575
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
14 files changed:
src/simd/binary_helpers_test.go
src/simd/compare_helpers_test.go
src/simd/comparemasked_helpers_test.go
src/simd/genfiles.go
src/simd/helpers_test.go
src/simd/simulation_helpers_test.go
src/simd/slice_amd64.go
src/simd/slicepart_amd64.go
src/simd/slicepart_test.go
src/simd/ternary_helpers_test.go
src/simd/ternary_test.go
src/simd/unary_helpers_test.go
src/simd/unary_test.go
src/simd/unsafe_helpers.go [new file with mode: 0644]

index fbf31beb7c8e6b26595e8775d7c8301307e0cc06..82cf784bcac72e137fd78d17de13ad991917ddeb 100644 (file)
@@ -24,7 +24,7 @@ func testInt8x16Binary(t *testing.T, f func(_, _ simd.Int8x16) simd.Int8x16, wan
                g := make([]int8, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -39,7 +39,7 @@ func testInt16x8Binary(t *testing.T, f func(_, _ simd.Int16x8) simd.Int16x8, wan
                g := make([]int16, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -54,7 +54,7 @@ func testInt32x4Binary(t *testing.T, f func(_, _ simd.Int32x4) simd.Int32x4, wan
                g := make([]int32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -69,7 +69,7 @@ func testInt64x2Binary(t *testing.T, f func(_, _ simd.Int64x2) simd.Int64x2, wan
                g := make([]int64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -84,7 +84,7 @@ func testUint8x16Binary(t *testing.T, f func(_, _ simd.Uint8x16) simd.Uint8x16,
                g := make([]uint8, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -99,7 +99,7 @@ func testUint16x8Binary(t *testing.T, f func(_, _ simd.Uint16x8) simd.Uint16x8,
                g := make([]uint16, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -114,7 +114,7 @@ func testUint32x4Binary(t *testing.T, f func(_, _ simd.Uint32x4) simd.Uint32x4,
                g := make([]uint32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -129,7 +129,7 @@ func testUint64x2Binary(t *testing.T, f func(_, _ simd.Uint64x2) simd.Uint64x2,
                g := make([]uint64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -144,7 +144,7 @@ func testFloat32x4Binary(t *testing.T, f func(_, _ simd.Float32x4) simd.Float32x
                g := make([]float32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -159,7 +159,7 @@ func testFloat64x2Binary(t *testing.T, f func(_, _ simd.Float64x2) simd.Float64x
                g := make([]float64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -174,7 +174,7 @@ func testInt8x32Binary(t *testing.T, f func(_, _ simd.Int8x32) simd.Int8x32, wan
                g := make([]int8, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -189,7 +189,7 @@ func testInt16x16Binary(t *testing.T, f func(_, _ simd.Int16x16) simd.Int16x16,
                g := make([]int16, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -204,7 +204,7 @@ func testInt32x8Binary(t *testing.T, f func(_, _ simd.Int32x8) simd.Int32x8, wan
                g := make([]int32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -219,7 +219,7 @@ func testInt64x4Binary(t *testing.T, f func(_, _ simd.Int64x4) simd.Int64x4, wan
                g := make([]int64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -234,7 +234,7 @@ func testUint8x32Binary(t *testing.T, f func(_, _ simd.Uint8x32) simd.Uint8x32,
                g := make([]uint8, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -249,7 +249,7 @@ func testUint16x16Binary(t *testing.T, f func(_, _ simd.Uint16x16) simd.Uint16x1
                g := make([]uint16, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -264,7 +264,7 @@ func testUint32x8Binary(t *testing.T, f func(_, _ simd.Uint32x8) simd.Uint32x8,
                g := make([]uint32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -279,7 +279,7 @@ func testUint64x4Binary(t *testing.T, f func(_, _ simd.Uint64x4) simd.Uint64x4,
                g := make([]uint64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -294,7 +294,7 @@ func testFloat32x8Binary(t *testing.T, f func(_, _ simd.Float32x8) simd.Float32x
                g := make([]float32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -309,7 +309,7 @@ func testFloat64x4Binary(t *testing.T, f func(_, _ simd.Float64x4) simd.Float64x
                g := make([]float64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -324,7 +324,7 @@ func testInt8x64Binary(t *testing.T, f func(_, _ simd.Int8x64) simd.Int8x64, wan
                g := make([]int8, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -339,7 +339,7 @@ func testInt16x32Binary(t *testing.T, f func(_, _ simd.Int16x32) simd.Int16x32,
                g := make([]int16, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -354,7 +354,7 @@ func testInt32x16Binary(t *testing.T, f func(_, _ simd.Int32x16) simd.Int32x16,
                g := make([]int32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -369,7 +369,7 @@ func testInt64x8Binary(t *testing.T, f func(_, _ simd.Int64x8) simd.Int64x8, wan
                g := make([]int64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -384,7 +384,7 @@ func testUint8x64Binary(t *testing.T, f func(_, _ simd.Uint8x64) simd.Uint8x64,
                g := make([]uint8, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -399,7 +399,7 @@ func testUint16x32Binary(t *testing.T, f func(_, _ simd.Uint16x32) simd.Uint16x3
                g := make([]uint16, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -414,7 +414,7 @@ func testUint32x16Binary(t *testing.T, f func(_, _ simd.Uint32x16) simd.Uint32x1
                g := make([]uint32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -429,7 +429,7 @@ func testUint64x8Binary(t *testing.T, f func(_, _ simd.Uint64x8) simd.Uint64x8,
                g := make([]uint64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -444,7 +444,7 @@ func testFloat32x16Binary(t *testing.T, f func(_, _ simd.Float32x16) simd.Float3
                g := make([]float32, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -459,6 +459,6 @@ func testFloat64x8Binary(t *testing.T, f func(_, _ simd.Float64x8) simd.Float64x
                g := make([]float64, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
index e6d7c82c8fe69fceddd3d3a76bbc587b3b5acf93..aef703c66a06d198888ddbc26634624632fae27e 100644 (file)
@@ -24,7 +24,7 @@ func testInt8x16Compare(t *testing.T, f func(_, _ simd.Int8x16) simd.Mask8x16, w
                g := make([]int8, n)
                f(a, b).AsInt8x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -39,7 +39,7 @@ func testInt16x8Compare(t *testing.T, f func(_, _ simd.Int16x8) simd.Mask16x8, w
                g := make([]int16, n)
                f(a, b).AsInt16x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -54,7 +54,7 @@ func testInt32x4Compare(t *testing.T, f func(_, _ simd.Int32x4) simd.Mask32x4, w
                g := make([]int32, n)
                f(a, b).AsInt32x4().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -69,7 +69,7 @@ func testInt64x2Compare(t *testing.T, f func(_, _ simd.Int64x2) simd.Mask64x2, w
                g := make([]int64, n)
                f(a, b).AsInt64x2().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -84,7 +84,7 @@ func testUint8x16Compare(t *testing.T, f func(_, _ simd.Uint8x16) simd.Mask8x16,
                g := make([]int8, n)
                f(a, b).AsInt8x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -99,7 +99,7 @@ func testUint16x8Compare(t *testing.T, f func(_, _ simd.Uint16x8) simd.Mask16x8,
                g := make([]int16, n)
                f(a, b).AsInt16x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -114,7 +114,7 @@ func testUint32x4Compare(t *testing.T, f func(_, _ simd.Uint32x4) simd.Mask32x4,
                g := make([]int32, n)
                f(a, b).AsInt32x4().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -129,7 +129,7 @@ func testUint64x2Compare(t *testing.T, f func(_, _ simd.Uint64x2) simd.Mask64x2,
                g := make([]int64, n)
                f(a, b).AsInt64x2().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -144,7 +144,7 @@ func testFloat32x4Compare(t *testing.T, f func(_, _ simd.Float32x4) simd.Mask32x
                g := make([]int32, n)
                f(a, b).AsInt32x4().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -159,7 +159,7 @@ func testFloat64x2Compare(t *testing.T, f func(_, _ simd.Float64x2) simd.Mask64x
                g := make([]int64, n)
                f(a, b).AsInt64x2().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -174,7 +174,7 @@ func testInt8x32Compare(t *testing.T, f func(_, _ simd.Int8x32) simd.Mask8x32, w
                g := make([]int8, n)
                f(a, b).AsInt8x32().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -189,7 +189,7 @@ func testInt16x16Compare(t *testing.T, f func(_, _ simd.Int16x16) simd.Mask16x16
                g := make([]int16, n)
                f(a, b).AsInt16x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -204,7 +204,7 @@ func testInt32x8Compare(t *testing.T, f func(_, _ simd.Int32x8) simd.Mask32x8, w
                g := make([]int32, n)
                f(a, b).AsInt32x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -219,7 +219,7 @@ func testInt64x4Compare(t *testing.T, f func(_, _ simd.Int64x4) simd.Mask64x4, w
                g := make([]int64, n)
                f(a, b).AsInt64x4().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -234,7 +234,7 @@ func testUint8x32Compare(t *testing.T, f func(_, _ simd.Uint8x32) simd.Mask8x32,
                g := make([]int8, n)
                f(a, b).AsInt8x32().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -249,7 +249,7 @@ func testUint16x16Compare(t *testing.T, f func(_, _ simd.Uint16x16) simd.Mask16x
                g := make([]int16, n)
                f(a, b).AsInt16x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -264,7 +264,7 @@ func testUint32x8Compare(t *testing.T, f func(_, _ simd.Uint32x8) simd.Mask32x8,
                g := make([]int32, n)
                f(a, b).AsInt32x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -279,7 +279,7 @@ func testUint64x4Compare(t *testing.T, f func(_, _ simd.Uint64x4) simd.Mask64x4,
                g := make([]int64, n)
                f(a, b).AsInt64x4().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -294,7 +294,7 @@ func testFloat32x8Compare(t *testing.T, f func(_, _ simd.Float32x8) simd.Mask32x
                g := make([]int32, n)
                f(a, b).AsInt32x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -309,7 +309,7 @@ func testFloat64x4Compare(t *testing.T, f func(_, _ simd.Float64x4) simd.Mask64x
                g := make([]int64, n)
                f(a, b).AsInt64x4().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -324,7 +324,7 @@ func testInt8x64Compare(t *testing.T, f func(_, _ simd.Int8x64) simd.Mask8x64, w
                g := make([]int8, n)
                f(a, b).AsInt8x64().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -339,7 +339,7 @@ func testInt16x32Compare(t *testing.T, f func(_, _ simd.Int16x32) simd.Mask16x32
                g := make([]int16, n)
                f(a, b).AsInt16x32().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -354,7 +354,7 @@ func testInt32x16Compare(t *testing.T, f func(_, _ simd.Int32x16) simd.Mask32x16
                g := make([]int32, n)
                f(a, b).AsInt32x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -369,7 +369,7 @@ func testInt64x8Compare(t *testing.T, f func(_, _ simd.Int64x8) simd.Mask64x8, w
                g := make([]int64, n)
                f(a, b).AsInt64x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -384,7 +384,7 @@ func testUint8x64Compare(t *testing.T, f func(_, _ simd.Uint8x64) simd.Mask8x64,
                g := make([]int8, n)
                f(a, b).AsInt8x64().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -399,7 +399,7 @@ func testUint16x32Compare(t *testing.T, f func(_, _ simd.Uint16x32) simd.Mask16x
                g := make([]int16, n)
                f(a, b).AsInt16x32().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -414,7 +414,7 @@ func testUint32x16Compare(t *testing.T, f func(_, _ simd.Uint32x16) simd.Mask32x
                g := make([]int32, n)
                f(a, b).AsInt32x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -429,7 +429,7 @@ func testUint64x8Compare(t *testing.T, f func(_, _ simd.Uint64x8) simd.Mask64x8,
                g := make([]int64, n)
                f(a, b).AsInt64x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -444,7 +444,7 @@ func testFloat32x16Compare(t *testing.T, f func(_, _ simd.Float32x16) simd.Mask3
                g := make([]int32, n)
                f(a, b).AsInt32x16().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
 
@@ -459,6 +459,6 @@ func testFloat64x8Compare(t *testing.T, f func(_, _ simd.Float64x8) simd.Mask64x
                g := make([]int64, n)
                f(a, b).AsInt64x8().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
index 0baba27e5442781d438b0335cc733110364e9fe1..542145c11e173df58cf56392028398d8694fbf64 100644 (file)
@@ -33,7 +33,7 @@ func testInt8x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -57,7 +57,7 @@ func testInt16x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -81,7 +81,7 @@ func testInt32x4CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -105,7 +105,7 @@ func testInt64x2CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -129,7 +129,7 @@ func testUint8x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -153,7 +153,7 @@ func testUint16x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -177,7 +177,7 @@ func testUint32x4CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -201,7 +201,7 @@ func testUint64x2CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -225,7 +225,7 @@ func testFloat32x4CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -249,7 +249,7 @@ func testFloat64x2CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -273,7 +273,7 @@ func testInt8x32CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -297,7 +297,7 @@ func testInt16x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -321,7 +321,7 @@ func testInt32x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -345,7 +345,7 @@ func testInt64x4CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -369,7 +369,7 @@ func testUint8x32CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -393,7 +393,7 @@ func testUint16x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -417,7 +417,7 @@ func testUint32x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -441,7 +441,7 @@ func testUint64x4CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -465,7 +465,7 @@ func testFloat32x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -489,7 +489,7 @@ func testFloat64x4CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -513,7 +513,7 @@ func testInt8x64CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -537,7 +537,7 @@ func testInt16x32CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -561,7 +561,7 @@ func testInt32x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -585,7 +585,7 @@ func testInt64x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -609,7 +609,7 @@ func testUint8x64CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -633,7 +633,7 @@ func testUint16x32CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -657,7 +657,7 @@ func testUint32x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -681,7 +681,7 @@ func testUint64x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -705,7 +705,7 @@ func testFloat32x16CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
 
@@ -729,6 +729,6 @@ func testFloat64x8CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m) })
        })
 }
index 76f16392e67103a07d025350166ef006526b08d9..269659a65350e529428c66625c52ad2db73b15bc 100644 (file)
@@ -10,6 +10,7 @@ package main
 // slice operations and tests
 
 import (
+       "bufio"
        "bytes"
        "flag"
        "fmt"
@@ -44,6 +45,37 @@ var allShapes = &shapes{
 // 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 avx512MaskedLoadShapes = &shapes{
+       vecs:   []int{512},
+       ints:   []int{8, 16, 32, 64},
+       uints:  []int{8, 16, 32, 64},
+       floats: []int{32, 64},
+}
+
+var avx2MaskedLoadShapes = &shapes{
+       vecs:   []int{128, 256},
+       ints:   []int{32, 64},
+       uints:  []int{32, 64},
+       floats: []int{32, 64},
+}
+
+var avx2SmallLoadPunShapes = &shapes{
+       // ints are done by hand, these are type-punned to int.
+       vecs:  []int{128, 256},
+       uints: []int{8, 16},
+}
+
+var unaryFlaky = &shapes{
+       vecs:   []int{128, 256, 512},
+       floats: []int{32, 64},
+}
+
+var ternaryFlaky = &shapes{
        vecs:   []int{128, 256, 512},
        floats: []int{32},
 }
@@ -61,6 +93,7 @@ func oneTemplate(t *template.Template, baseType string, width, count int, out io
        if strings.Contains("aeiou", baseType[:1]) {
                aOrAn = "an"
        }
+       oxFF := fmt.Sprintf("0x%x", uint64((1<<count)-1))
        t.Execute(out, struct {
                Vec   string // the type of the vector, e.g. Float32x4
                AOrAn string // for documentation, the article "a" or "an"
@@ -68,6 +101,7 @@ func oneTemplate(t *template.Template, baseType string, width, count int, out io
                Count int    // the number of elements, e.g. 4
                WxC   string // the width-by-type string, e.g., "32x4"
                Type  string // the element type, e.g. "float32"
+               OxFF  string // a mask for the lowest 'count' bits
        }{
                Vec:   vType,
                AOrAn: aOrAn,
@@ -75,6 +109,7 @@ func oneTemplate(t *template.Template, baseType string, width, count int, out io
                Count: count,
                WxC:   wxc,
                Type:  eType,
+               OxFF:  oxFF,
        })
 }
 
@@ -110,6 +145,20 @@ func prologue(s string, out io.Writer) {
 
 package simd
 
+import "unsafe"
+
+`, s)
+}
+
+func unsafePrologue(s string, out io.Writer) {
+       fmt.Fprintf(out,
+               `// Code generated by '%s'; DO NOT EDIT.
+
+//go:build goexperiment.simd
+
+package simd
+
+import "unsafe"
 `, s)
 }
 
@@ -139,16 +188,6 @@ func curryTestPrologue(t string) func(s string, out io.Writer) {
        }
 }
 
-// //go:noescape
-// func LoadUint8x16Slice(s []uint8) Uint8x16 {
-//     return LoadUint8x16((*[16]uint8)(s[:16]))
-// }
-
-// //go:noescape
-// func (x Uint8x16) StoreSlice(s []uint8) {
-//    x.Store((*[16]uint8)(s[:16]))
-// }
-
 func templateOf(name, temp string) shapeAndTemplate {
        return shapeAndTemplate{s: allShapes,
                t: template.Must(template.New(name).Parse(temp))}
@@ -182,7 +221,24 @@ func test{{.Vec}}Unary(t *testing.T, f func(_ simd.{{.Vec}}) simd.{{.Vec}}, want
                g := make([]{{.Type}}, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
+               return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
+       })
+}
+`)
+
+var unaryFlakyTemplate = shapedTemplateOf(unaryFlaky, "unary_flaky_helpers", `
+// test{{.Vec}}UnaryFlaky 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 test{{.Vec}}UnaryFlaky(t *testing.T, f func(x simd.{{.Vec}}) simd.{{.Vec}}, want func(x []{{.Type}}) []{{.Type}}, flakiness float64) {
+       n := {{.Count}}
+       t.Helper()
+       forSlice(t, {{.Type}}s, n, func(x []{{.Type}}) bool {
+               t.Helper()
+               a := simd.Load{{.Vec}}Slice(x)
+               g := make([]{{.Type}}, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() {t.Helper(); t.Logf("x=%v", x)})
        })
 }
 `)
@@ -198,7 +254,7 @@ func test{{.Vec}}UnaryToInt32(t *testing.T, f func(x simd.{{.Vec}}) simd.Int32x{
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
+               return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
        })
 }
 `)
@@ -214,7 +270,7 @@ func test{{.Vec}}UnaryToUint32(t *testing.T, f func(x simd.{{.Vec}}) simd.Uint32
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x)})
+               return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
        })
 }
 `)
@@ -231,7 +287,7 @@ func test{{.Vec}}Binary(t *testing.T, f func(_, _ simd.{{.Vec}}) simd.{{.Vec}},
                g := make([]{{.Type}}, n)
                f(a, b).StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
+               return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
        })
 }
 `)
@@ -249,7 +305,26 @@ func test{{.Vec}}Ternary(t *testing.T, f func(_, _, _ simd.{{.Vec}}) simd.{{.Vec
                g := make([]{{.Type}}, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z); })
+               return checkSlicesLogInput(t, g, w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z); })
+       })
+}
+`)
+
+var ternaryFlakyTemplate = shapedTemplateOf(ternaryFlaky, "ternary_helpers", `
+// test{{.Vec}}TernaryFlaky tests the simd ternary 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 test{{.Vec}}TernaryFlaky(t *testing.T, f func(x, y, z simd.{{.Vec}}) simd.{{.Vec}}, want func(x, y, z []{{.Type}}) []{{.Type}}, flakiness float64) {
+       n := {{.Count}}
+       t.Helper()
+       forSliceTriple(t, {{.Type}}s, n, func(x, y, z []{{.Type}}) bool {
+               t.Helper()
+               a := simd.Load{{.Vec}}Slice(x)
+               b := simd.Load{{.Vec}}Slice(y)
+               c := simd.Load{{.Vec}}Slice(z)
+               g := make([]{{.Type}}, n)
+               f(a, b, c).StoreSlice(g)
+               w := want(x, y, z)
+               return checkSlicesLogInput(t, g, w, flakiness, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z); })
        })
 }
 `)
@@ -266,7 +341,7 @@ func test{{.Vec}}Compare(t *testing.T, f func(_, _ simd.{{.Vec}}) simd.Mask{{.Wx
                g := make([]int{{.Width}}, n)
                f(a, b).AsInt{{.WxC}}().StoreSlice(g)
                w := want(x, y)
-               return checkSlicesLogInput(t, s64(g), w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); })
        })
 }
 `)
@@ -293,13 +368,117 @@ func test{{.Vec}}CompareMasked(t *testing.T,
                                w[i] = 0
                        }
                }
-               return checkSlicesLogInput(t, s64(g), w, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m); })
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() {t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("m=%v", m); })
        })
 }
 `)
 
+var avx512MaskedLoadSlicePartTemplate = shapedTemplateOf(avx512MaskedLoadShapes, "avx 512 load slice part", `
+// Load{{.Vec}}SlicePart loads a {{.Vec}} from the slice s.
+// If s has fewer than {{.Count}} elements, the remaining elements of the vector are filled with zeroes.
+// If s has {{.Count}} or more elements, the function is equivalent to Load{{.Vec}}Slice.
+func Load{{.Vec}}SlicePart(s []{{.Type}}) {{.Vec}} {
+       l := len(s)
+       if l >= {{.Count}} {
+               return Load{{.Vec}}Slice(s)
+       }
+       if l == 0 {
+               var x {{.Vec}}
+               return x
+       }
+
+       mask := Mask{{.WxC}}FromBits({{.OxFF}} >> ({{.Count}} - l))
+       return LoadMasked{{.Vec}}(pa{{.Vec}}(s), mask)
+}
+
+// StoreSlicePart stores the {{.Count}} elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has {{.Count}} or more elements, the method is equivalent to x.StoreSlice.
+func (x {{.Vec}}) StoreSlicePart(s []{{.Type}}) {
+       l := len(s)
+       if l >= {{.Count}} {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask{{.WxC}}FromBits({{.OxFF}} >> ({{.Count}} - l))
+       x.StoreMasked(pa{{.Vec}}(s), mask)
+}
+`)
+
+var avx2MaskedLoadSlicePartTemplate = shapedTemplateOf(avx2MaskedLoadShapes, "avx 2 load slice part", `
+// Load{{.Vec}}SlicePart loads a {{.Vec}} from the slice s.
+// If s has fewer than {{.Count}} elements, the remaining elements of the vector are filled with zeroes.
+// If s has {{.Count}} or more elements, the function is equivalent to Load{{.Vec}}Slice.
+func Load{{.Vec}}SlicePart(s []{{.Type}}) {{.Vec}} {
+       l := len(s)
+       if l >= {{.Count}} {
+               return Load{{.Vec}}Slice(s)
+       }
+       if l == 0 {
+               var x {{.Vec}}
+               return x
+       }
+       mask := vecMask{{.Width}}[len(vecMask{{.Width}})/2-l:]
+       return LoadMasked{{.Vec}}(pa{{.Vec}}(s), LoadInt{{.WxC}}Slice(mask).AsMask{{.WxC}}())
+}
+
+// StoreSlicePart stores the {{.Count}} elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has {{.Count}} or more elements, the method is equivalent to x.StoreSlice.
+func (x {{.Vec}}) StoreSlicePart(s []{{.Type}}) {
+       l := len(s)
+       if l >= {{.Count}} {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask{{.Width}}[len(vecMask{{.Width}})/2-l:]
+       x.StoreMasked(pa{{.Vec}}(s), LoadInt{{.WxC}}Slice(mask).AsMask{{.WxC}}())
+}
+`)
+
+var avx2SmallLoadSlicePartTemplate = shapedTemplateOf(avx2SmallLoadPunShapes, "avx 2 small load slice part", `
+// Load{{.Vec}}SlicePart loads a {{.Vec}} from the slice s.
+// If s has fewer than {{.Count}} elements, the remaining elements of the vector are filled with zeroes.
+// If s has {{.Count}} or more elements, the function is equivalent to Load{{.Vec}}Slice.
+func Load{{.Vec}}SlicePart(s []{{.Type}}) {{.Vec}} {
+       if len(s) == 0 {
+               var zero {{.Vec}}
+               return zero
+       }
+       t := unsafe.Slice((*int{{.Width}})(unsafe.Pointer(&s[0])), len(s))
+       return LoadInt{{.WxC}}SlicePart(t).As{{.Vec}}()
+}
+
+// StoreSlicePart stores the {{.Count}} elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has {{.Count}} or more elements, the method is equivalent to x.StoreSlice.
+func (x {{.Vec}}) StoreSlicePart(s []{{.Type}}) {
+       if len(s) == 0 {
+               return
+       }
+       t := unsafe.Slice((*int{{.Width}})(unsafe.Pointer(&s[0])), len(s))
+       x.AsInt{{.WxC}}().StoreSlicePart(t)
+}
+`)
+
+var unsafePATemplate = templateOf("unsafe PA helper", `
+// pa{{.Vec}} returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only 
+// access the known-safe portions of the array.
+func pa{{.Vec}}(s []{{.Type}}) *[{{.Count}}]{{.Type}} {
+       return (*[{{.Count}}]{{.Type}})(unsafe.Pointer(&s[0]))
+}
+`)
+
 func main() {
        sl := flag.String("sl", "slice_amd64.go", "file name for slice operations")
+       ush := flag.String("ush", "unsafe_helpers.go", "file name for unsafe helpers")
        bh := flag.String("bh", "binary_helpers_test.go", "file name for binary test helpers")
        uh := flag.String("uh", "unary_helpers_test.go", "file name for unary test helpers")
        th := flag.String("th", "ternary_helpers_test.go", "file name for ternary test helpers")
@@ -308,16 +487,19 @@ func main() {
        flag.Parse()
 
        if *sl != "" {
-               one(*sl, prologue, sliceTemplate)
+               one(*sl, prologue, sliceTemplate, avx512MaskedLoadSlicePartTemplate, avx2MaskedLoadSlicePartTemplate, avx2SmallLoadSlicePartTemplate)
+       }
+       if *ush != "" {
+               one(*ush, unsafePrologue, unsafePATemplate)
        }
        if *uh != "" {
-               one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryTemplateToInt32, unaryTemplateToUint32)
+               one(*uh, curryTestPrologue("unary simd methods"), unaryTemplate, unaryTemplateToInt32, unaryTemplateToUint32, unaryFlakyTemplate)
        }
        if *bh != "" {
                one(*bh, curryTestPrologue("binary simd methods"), binaryTemplate)
        }
        if *th != "" {
-               one(*th, curryTestPrologue("ternary simd methods"), ternaryTemplate)
+               one(*th, curryTestPrologue("ternary simd methods"), ternaryTemplate, ternaryFlakyTemplate)
        }
        if *ch != "" {
                one(*ch, curryTestPrologue("simd methods that compare two operands"), compareTemplate)
@@ -327,6 +509,18 @@ func main() {
        }
 }
 
+// numberLines takes a slice of bytes, and returns a string where each line
+// is numbered, starting from 1.
+func numberLines(data []byte) string {
+       var buf bytes.Buffer
+       r := bytes.NewReader(data)
+       s := bufio.NewScanner(r)
+       for i := 1; s.Scan(); i++ {
+               fmt.Fprintf(&buf, "%d: %s\n", i, s.Text())
+       }
+       return buf.String()
+}
+
 func one(filename string, prologue func(s string, out io.Writer), sats ...shapeAndTemplate) {
        if filename == "" {
                return
@@ -352,7 +546,9 @@ func one(filename string, prologue func(s string, out io.Writer), sats ...shapeA
 
        b, err := format.Source(out.Bytes())
        if err != nil {
-               fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v", filename, err)
+               fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v\n", filename, err)
+               fmt.Fprintf(os.Stderr, "%s\n", numberLines(out.Bytes()))
+               fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v\n", filename, err)
                os.Exit(1)
        } else {
                ofile.Write(b)
index 14490a84b2a9e085c20e977348e3fd52c294ad4c..6c681abe98c6d70db7a15150ad004641b3f7296b 100644 (file)
@@ -29,14 +29,14 @@ type number interface {
 
 func checkSlices[T number](t *testing.T, got, want []T) bool {
        t.Helper()
-       return checkSlicesLogInput[T](t, got, want, nil)
+       return checkSlicesLogInput[T](t, got, want, 0.0, nil)
 }
 
 // checkSlices compares two slices for equality,
 // reporting a test error if there is a problem,
 // and also consumes the two slices so that a
 // test/benchmark won't be dead-code eliminated.
-func checkSlicesLogInput[T number](t *testing.T, got, want []T, logInput func()) bool {
+func checkSlicesLogInput[T number](t *testing.T, got, want []T, flakiness float64, logInput func()) bool {
        t.Helper()
        var z T
        for i := range want {
@@ -49,11 +49,32 @@ func checkSlicesLogInput[T number](t *testing.T, got, want []T, logInput func())
                                if math.IsNaN(float64(x)) && math.IsNaN(float64(y)) {
                                        continue
                                }
+                               if flakiness > 0 {
+                                       if y == 0 {
+                                               if math.Abs(float64(x)) < flakiness {
+                                                       continue
+                                               }
+                                       } else {
+                                               if math.Abs(float64((x-y)/y)) < flakiness {
+                                                       continue
+                                               }
+                                       }
+                               }
                        case float64:
                                y := ib.(float64)
                                if math.IsNaN(x) && math.IsNaN(y) {
                                        continue
                                }
+                               if flakiness > 0 {
+                                       if y == 0 {
+                                               if math.Abs(x) < flakiness {
+                                                       continue
+                                               }
+                                       } else if math.Abs((x-y)/y) < flakiness {
+                                               continue
+                                       }
+                               }
+
                        default:
                        }
 
@@ -227,13 +248,16 @@ const (
 )
 
 var zero = 0.0
+var nzero = -zero
+var inf = 1 / zero
+var ninf = -1 / zero
 var nan = math.NaN()
 
 // N controls how large the test vectors are
 const N = 144
 
-var float32s = nOf(N, []float32{1, float32(nan), float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1 / zero), float32(-1 / zero), 1 / 2, 1 / 4, 1 / 8, 1 / 1000, 1 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
-var float64s = nOf(N, []float64{nan, zero, -zero, 1 / zero, -1 / zero, 1 / 1000, 1 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
+var float32s = nOf(N, []float32{float32(inf), float32(ninf), 1, float32(nan), float32(zero), 2, float32(nan), float32(zero), 3, float32(-zero), float32(1.0 / zero), float32(-1.0 / zero), 1.0 / 2, 1.0 / 4, 1.0 / 8, 1.0 / 1000, 1.0 / 1000000, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat32, 1 / math.MaxFloat32, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -160, -3200, -64, -4, -8, -16, -32, -64})
+var float64s = nOf(N, []float64{inf, ninf, nan, zero, -zero, 1 / zero, -1 / zero, 0.0001, 0.0000001, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1.0 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
 
 var int32s = nOf(N, []int32{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
 var uint32s = nOf(N, []uint32{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint32(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint32(0x55555), ^uint32(0x77777), ^uint32(0xccccc)})
index ec3d7952490de020f833e4824f9a591ba5d4abf1..8677216d9fa2c4c0da35b27a8f4941de1ca8df27 100644 (file)
@@ -6,7 +6,9 @@
 
 package simd_test
 
-import "math"
+import (
+       "math"
+)
 
 func less[T number](x, y T) bool {
        return x < y
@@ -124,6 +126,22 @@ func toUint32[T number](x T) uint32 {
        return uint32(x)
 }
 
+func ceilResidueForPrecision[T float](i int) func(T) T {
+       f := 1.0
+       for i > 0 {
+               f *= 2
+               i--
+       }
+       return func(x T) T {
+               y := float64(x)
+               if math.IsInf(float64(x*T(f)), 0) {
+                       return 0
+               }
+               // TODO sort out the rounding issues when T === float32
+               return T(y - math.Ceil(y*f)/f)
+       }
+}
+
 // Slice versions of all these elementwise operations
 
 func addSlice[T number](x, y []T) []T {
index ad7bce8964ddcd22096d703842a6ab169b998e2d..bd1d4f153089de270a99cfc93f043111d72d7032 100644 (file)
@@ -4,6 +4,8 @@
 
 package simd
 
+import "unsafe"
+
 // LoadInt8x16Slice loads an Int8x16 from a slice of at least 16 int8s
 func LoadInt8x16Slice(s []int8) Int8x16 {
        return LoadInt8x16((*[16]int8)(s))
@@ -303,3 +305,809 @@ func LoadFloat64x8Slice(s []float64) Float64x8 {
 func (x Float64x8) StoreSlice(s []float64) {
        x.Store((*[8]float64)(s))
 }
+
+// LoadInt8x64SlicePart loads a Int8x64 from the slice s.
+// If s has fewer than 64 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 64 or more elements, the function is equivalent to LoadInt8x64Slice.
+func LoadInt8x64SlicePart(s []int8) Int8x64 {
+       l := len(s)
+       if l >= 64 {
+               return LoadInt8x64Slice(s)
+       }
+       if l == 0 {
+               var x Int8x64
+               return x
+       }
+
+       mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+       return LoadMaskedInt8x64(paInt8x64(s), mask)
+}
+
+// StoreSlicePart stores the 64 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 64 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int8x64) StoreSlicePart(s []int8) {
+       l := len(s)
+       if l >= 64 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+       x.StoreMasked(paInt8x64(s), mask)
+}
+
+// LoadInt16x32SlicePart loads a Int16x32 from the slice s.
+// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 32 or more elements, the function is equivalent to LoadInt16x32Slice.
+func LoadInt16x32SlicePart(s []int16) Int16x32 {
+       l := len(s)
+       if l >= 32 {
+               return LoadInt16x32Slice(s)
+       }
+       if l == 0 {
+               var x Int16x32
+               return x
+       }
+
+       mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+       return LoadMaskedInt16x32(paInt16x32(s), mask)
+}
+
+// StoreSlicePart stores the 32 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 32 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int16x32) StoreSlicePart(s []int16) {
+       l := len(s)
+       if l >= 32 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+       x.StoreMasked(paInt16x32(s), mask)
+}
+
+// LoadInt32x16SlicePart loads a Int32x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadInt32x16Slice.
+func LoadInt32x16SlicePart(s []int32) Int32x16 {
+       l := len(s)
+       if l >= 16 {
+               return LoadInt32x16Slice(s)
+       }
+       if l == 0 {
+               var x Int32x16
+               return x
+       }
+
+       mask := Mask32x16FromBits(0xffff >> (16 - l))
+       return LoadMaskedInt32x16(paInt32x16(s), mask)
+}
+
+// StoreSlicePart stores the 16 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int32x16) StoreSlicePart(s []int32) {
+       l := len(s)
+       if l >= 16 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask32x16FromBits(0xffff >> (16 - l))
+       x.StoreMasked(paInt32x16(s), mask)
+}
+
+// LoadInt64x8SlicePart loads a Int64x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadInt64x8Slice.
+func LoadInt64x8SlicePart(s []int64) Int64x8 {
+       l := len(s)
+       if l >= 8 {
+               return LoadInt64x8Slice(s)
+       }
+       if l == 0 {
+               var x Int64x8
+               return x
+       }
+
+       mask := Mask64x8FromBits(0xff >> (8 - l))
+       return LoadMaskedInt64x8(paInt64x8(s), mask)
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int64x8) StoreSlicePart(s []int64) {
+       l := len(s)
+       if l >= 8 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask64x8FromBits(0xff >> (8 - l))
+       x.StoreMasked(paInt64x8(s), mask)
+}
+
+// LoadUint8x64SlicePart loads a Uint8x64 from the slice s.
+// If s has fewer than 64 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 64 or more elements, the function is equivalent to LoadUint8x64Slice.
+func LoadUint8x64SlicePart(s []uint8) Uint8x64 {
+       l := len(s)
+       if l >= 64 {
+               return LoadUint8x64Slice(s)
+       }
+       if l == 0 {
+               var x Uint8x64
+               return x
+       }
+
+       mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+       return LoadMaskedUint8x64(paUint8x64(s), mask)
+}
+
+// StoreSlicePart stores the 64 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 64 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint8x64) StoreSlicePart(s []uint8) {
+       l := len(s)
+       if l >= 64 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask8x64FromBits(0xffffffffffffffff >> (64 - l))
+       x.StoreMasked(paUint8x64(s), mask)
+}
+
+// LoadUint16x32SlicePart loads a Uint16x32 from the slice s.
+// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 32 or more elements, the function is equivalent to LoadUint16x32Slice.
+func LoadUint16x32SlicePart(s []uint16) Uint16x32 {
+       l := len(s)
+       if l >= 32 {
+               return LoadUint16x32Slice(s)
+       }
+       if l == 0 {
+               var x Uint16x32
+               return x
+       }
+
+       mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+       return LoadMaskedUint16x32(paUint16x32(s), mask)
+}
+
+// StoreSlicePart stores the 32 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 32 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint16x32) StoreSlicePart(s []uint16) {
+       l := len(s)
+       if l >= 32 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask16x32FromBits(0xffffffff >> (32 - l))
+       x.StoreMasked(paUint16x32(s), mask)
+}
+
+// LoadUint32x16SlicePart loads a Uint32x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadUint32x16Slice.
+func LoadUint32x16SlicePart(s []uint32) Uint32x16 {
+       l := len(s)
+       if l >= 16 {
+               return LoadUint32x16Slice(s)
+       }
+       if l == 0 {
+               var x Uint32x16
+               return x
+       }
+
+       mask := Mask32x16FromBits(0xffff >> (16 - l))
+       return LoadMaskedUint32x16(paUint32x16(s), mask)
+}
+
+// StoreSlicePart stores the 16 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint32x16) StoreSlicePart(s []uint32) {
+       l := len(s)
+       if l >= 16 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask32x16FromBits(0xffff >> (16 - l))
+       x.StoreMasked(paUint32x16(s), mask)
+}
+
+// LoadUint64x8SlicePart loads a Uint64x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadUint64x8Slice.
+func LoadUint64x8SlicePart(s []uint64) Uint64x8 {
+       l := len(s)
+       if l >= 8 {
+               return LoadUint64x8Slice(s)
+       }
+       if l == 0 {
+               var x Uint64x8
+               return x
+       }
+
+       mask := Mask64x8FromBits(0xff >> (8 - l))
+       return LoadMaskedUint64x8(paUint64x8(s), mask)
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint64x8) StoreSlicePart(s []uint64) {
+       l := len(s)
+       if l >= 8 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask64x8FromBits(0xff >> (8 - l))
+       x.StoreMasked(paUint64x8(s), mask)
+}
+
+// LoadFloat32x16SlicePart loads a Float32x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadFloat32x16Slice.
+func LoadFloat32x16SlicePart(s []float32) Float32x16 {
+       l := len(s)
+       if l >= 16 {
+               return LoadFloat32x16Slice(s)
+       }
+       if l == 0 {
+               var x Float32x16
+               return x
+       }
+
+       mask := Mask32x16FromBits(0xffff >> (16 - l))
+       return LoadMaskedFloat32x16(paFloat32x16(s), mask)
+}
+
+// StoreSlicePart stores the 16 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
+func (x Float32x16) StoreSlicePart(s []float32) {
+       l := len(s)
+       if l >= 16 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask32x16FromBits(0xffff >> (16 - l))
+       x.StoreMasked(paFloat32x16(s), mask)
+}
+
+// LoadFloat64x8SlicePart loads a Float64x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadFloat64x8Slice.
+func LoadFloat64x8SlicePart(s []float64) Float64x8 {
+       l := len(s)
+       if l >= 8 {
+               return LoadFloat64x8Slice(s)
+       }
+       if l == 0 {
+               var x Float64x8
+               return x
+       }
+
+       mask := Mask64x8FromBits(0xff >> (8 - l))
+       return LoadMaskedFloat64x8(paFloat64x8(s), mask)
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Float64x8) StoreSlicePart(s []float64) {
+       l := len(s)
+       if l >= 8 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := Mask64x8FromBits(0xff >> (8 - l))
+       x.StoreMasked(paFloat64x8(s), mask)
+}
+
+// LoadInt32x4SlicePart loads a Int32x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadInt32x4Slice.
+func LoadInt32x4SlicePart(s []int32) Int32x4 {
+       l := len(s)
+       if l >= 4 {
+               return LoadInt32x4Slice(s)
+       }
+       if l == 0 {
+               var x Int32x4
+               return x
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       return LoadMaskedInt32x4(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// StoreSlicePart stores the 4 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int32x4) StoreSlicePart(s []int32) {
+       l := len(s)
+       if l >= 4 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       x.StoreMasked(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// LoadInt64x2SlicePart loads a Int64x2 from the slice s.
+// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 2 or more elements, the function is equivalent to LoadInt64x2Slice.
+func LoadInt64x2SlicePart(s []int64) Int64x2 {
+       l := len(s)
+       if l >= 2 {
+               return LoadInt64x2Slice(s)
+       }
+       if l == 0 {
+               var x Int64x2
+               return x
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       return LoadMaskedInt64x2(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// StoreSlicePart stores the 2 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 2 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int64x2) StoreSlicePart(s []int64) {
+       l := len(s)
+       if l >= 2 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       x.StoreMasked(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// LoadUint32x4SlicePart loads a Uint32x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadUint32x4Slice.
+func LoadUint32x4SlicePart(s []uint32) Uint32x4 {
+       l := len(s)
+       if l >= 4 {
+               return LoadUint32x4Slice(s)
+       }
+       if l == 0 {
+               var x Uint32x4
+               return x
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       return LoadMaskedUint32x4(paUint32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// StoreSlicePart stores the 4 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint32x4) StoreSlicePart(s []uint32) {
+       l := len(s)
+       if l >= 4 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       x.StoreMasked(paUint32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// LoadUint64x2SlicePart loads a Uint64x2 from the slice s.
+// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 2 or more elements, the function is equivalent to LoadUint64x2Slice.
+func LoadUint64x2SlicePart(s []uint64) Uint64x2 {
+       l := len(s)
+       if l >= 2 {
+               return LoadUint64x2Slice(s)
+       }
+       if l == 0 {
+               var x Uint64x2
+               return x
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       return LoadMaskedUint64x2(paUint64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// StoreSlicePart stores the 2 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 2 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint64x2) StoreSlicePart(s []uint64) {
+       l := len(s)
+       if l >= 2 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       x.StoreMasked(paUint64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// LoadFloat32x4SlicePart loads a Float32x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadFloat32x4Slice.
+func LoadFloat32x4SlicePart(s []float32) Float32x4 {
+       l := len(s)
+       if l >= 4 {
+               return LoadFloat32x4Slice(s)
+       }
+       if l == 0 {
+               var x Float32x4
+               return x
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       return LoadMaskedFloat32x4(paFloat32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// StoreSlicePart stores the 4 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
+func (x Float32x4) StoreSlicePart(s []float32) {
+       l := len(s)
+       if l >= 4 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       x.StoreMasked(paFloat32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
+}
+
+// LoadFloat64x2SlicePart loads a Float64x2 from the slice s.
+// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 2 or more elements, the function is equivalent to LoadFloat64x2Slice.
+func LoadFloat64x2SlicePart(s []float64) Float64x2 {
+       l := len(s)
+       if l >= 2 {
+               return LoadFloat64x2Slice(s)
+       }
+       if l == 0 {
+               var x Float64x2
+               return x
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       return LoadMaskedFloat64x2(paFloat64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// StoreSlicePart stores the 2 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 2 or more elements, the method is equivalent to x.StoreSlice.
+func (x Float64x2) StoreSlicePart(s []float64) {
+       l := len(s)
+       if l >= 2 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       x.StoreMasked(paFloat64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
+}
+
+// LoadInt32x8SlicePart loads a Int32x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadInt32x8Slice.
+func LoadInt32x8SlicePart(s []int32) Int32x8 {
+       l := len(s)
+       if l >= 8 {
+               return LoadInt32x8Slice(s)
+       }
+       if l == 0 {
+               var x Int32x8
+               return x
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       return LoadMaskedInt32x8(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int32x8) StoreSlicePart(s []int32) {
+       l := len(s)
+       if l >= 8 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       x.StoreMasked(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// LoadInt64x4SlicePart loads a Int64x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadInt64x4Slice.
+func LoadInt64x4SlicePart(s []int64) Int64x4 {
+       l := len(s)
+       if l >= 4 {
+               return LoadInt64x4Slice(s)
+       }
+       if l == 0 {
+               var x Int64x4
+               return x
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       return LoadMaskedInt64x4(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// StoreSlicePart stores the 4 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
+func (x Int64x4) StoreSlicePart(s []int64) {
+       l := len(s)
+       if l >= 4 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       x.StoreMasked(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// LoadUint32x8SlicePart loads a Uint32x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadUint32x8Slice.
+func LoadUint32x8SlicePart(s []uint32) Uint32x8 {
+       l := len(s)
+       if l >= 8 {
+               return LoadUint32x8Slice(s)
+       }
+       if l == 0 {
+               var x Uint32x8
+               return x
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       return LoadMaskedUint32x8(paUint32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint32x8) StoreSlicePart(s []uint32) {
+       l := len(s)
+       if l >= 8 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       x.StoreMasked(paUint32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// LoadUint64x4SlicePart loads a Uint64x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadUint64x4Slice.
+func LoadUint64x4SlicePart(s []uint64) Uint64x4 {
+       l := len(s)
+       if l >= 4 {
+               return LoadUint64x4Slice(s)
+       }
+       if l == 0 {
+               var x Uint64x4
+               return x
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       return LoadMaskedUint64x4(paUint64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// StoreSlicePart stores the 4 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint64x4) StoreSlicePart(s []uint64) {
+       l := len(s)
+       if l >= 4 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       x.StoreMasked(paUint64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// LoadFloat32x8SlicePart loads a Float32x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadFloat32x8Slice.
+func LoadFloat32x8SlicePart(s []float32) Float32x8 {
+       l := len(s)
+       if l >= 8 {
+               return LoadFloat32x8Slice(s)
+       }
+       if l == 0 {
+               var x Float32x8
+               return x
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       return LoadMaskedFloat32x8(paFloat32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Float32x8) StoreSlicePart(s []float32) {
+       l := len(s)
+       if l >= 8 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask32[len(vecMask32)/2-l:]
+       x.StoreMasked(paFloat32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
+}
+
+// LoadFloat64x4SlicePart loads a Float64x4 from the slice s.
+// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 4 or more elements, the function is equivalent to LoadFloat64x4Slice.
+func LoadFloat64x4SlicePart(s []float64) Float64x4 {
+       l := len(s)
+       if l >= 4 {
+               return LoadFloat64x4Slice(s)
+       }
+       if l == 0 {
+               var x Float64x4
+               return x
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       return LoadMaskedFloat64x4(paFloat64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// StoreSlicePart stores the 4 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
+func (x Float64x4) StoreSlicePart(s []float64) {
+       l := len(s)
+       if l >= 4 {
+               x.StoreSlice(s)
+               return
+       }
+       if l == 0 {
+               return
+       }
+       mask := vecMask64[len(vecMask64)/2-l:]
+       x.StoreMasked(paFloat64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
+}
+
+// LoadUint8x16SlicePart loads a Uint8x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadUint8x16Slice.
+func LoadUint8x16SlicePart(s []uint8) Uint8x16 {
+       if len(s) == 0 {
+               var zero Uint8x16
+               return zero
+       }
+       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+       return LoadInt8x16SlicePart(t).AsUint8x16()
+}
+
+// StoreSlicePart stores the 16 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint8x16) StoreSlicePart(s []uint8) {
+       if len(s) == 0 {
+               return
+       }
+       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+       x.AsInt8x16().StoreSlicePart(t)
+}
+
+// LoadUint16x8SlicePart loads a Uint16x8 from the slice s.
+// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 8 or more elements, the function is equivalent to LoadUint16x8Slice.
+func LoadUint16x8SlicePart(s []uint16) Uint16x8 {
+       if len(s) == 0 {
+               var zero Uint16x8
+               return zero
+       }
+       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+       return LoadInt16x8SlicePart(t).AsUint16x8()
+}
+
+// StoreSlicePart stores the 8 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint16x8) StoreSlicePart(s []uint16) {
+       if len(s) == 0 {
+               return
+       }
+       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+       x.AsInt16x8().StoreSlicePart(t)
+}
+
+// LoadUint8x32SlicePart loads a Uint8x32 from the slice s.
+// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 32 or more elements, the function is equivalent to LoadUint8x32Slice.
+func LoadUint8x32SlicePart(s []uint8) Uint8x32 {
+       if len(s) == 0 {
+               var zero Uint8x32
+               return zero
+       }
+       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+       return LoadInt8x32SlicePart(t).AsUint8x32()
+}
+
+// StoreSlicePart stores the 32 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 32 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint8x32) StoreSlicePart(s []uint8) {
+       if len(s) == 0 {
+               return
+       }
+       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
+       x.AsInt8x32().StoreSlicePart(t)
+}
+
+// LoadUint16x16SlicePart loads a Uint16x16 from the slice s.
+// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
+// If s has 16 or more elements, the function is equivalent to LoadUint16x16Slice.
+func LoadUint16x16SlicePart(s []uint16) Uint16x16 {
+       if len(s) == 0 {
+               var zero Uint16x16
+               return zero
+       }
+       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+       return LoadInt16x16SlicePart(t).AsUint16x16()
+}
+
+// StoreSlicePart stores the 16 elements of x into the slice s.
+// It stores as many elements as will fit in s.
+// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
+func (x Uint16x16) StoreSlicePart(s []uint16) {
+       if len(s) == 0 {
+               return
+       }
+       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
+       x.AsInt16x16().StoreSlicePart(t)
+}
index 3fcfc6255ba4ffd67705eef27d51f20690237f54..6d0b5a41f298bcaa563fce915106c0a88776ddf2 100644 (file)
@@ -11,7 +11,7 @@ import "unsafe"
 // Implementation of all the {Int,Uint}{8,16} load and store slice part
 // functions and methods for 128-bit and 256-bit vectors.
 
-/* pointer-punning functions. */
+/* pointer-punning functions for chunked slice part loads. */
 
 func int16atP8(p *int8) *int16 {
        return (*int16)(unsafe.Pointer(p))
@@ -41,100 +41,24 @@ func int32atP64(p *int64) *int32 {
        return (*int32)(unsafe.Pointer(p))
 }
 
-/* unsigned versions of integer slice part loads */
+/* These two masks are used by generated code */
 
-// LoadUint8x16SlicePart loads a Uint8x16 from the slice s.
-// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 16 or more elements, the function is equivalent to LoadUint8x16Slice.
-func LoadUint8x16SlicePart(s []uint8) Uint8x16 {
-       if len(s) == 0 {
-               var zero Uint8x16
-               return zero
-       }
-       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt8x16SlicePart(t).AsUint8x16()
-}
-
-// LoadUint16x8SlicePart loads a Uint16x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadUint16x8Slice.
-func LoadUint16x8SlicePart(s []uint16) Uint16x8 {
-       if len(s) == 0 {
-               var zero Uint16x8
-               return zero
-       }
-       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt16x8SlicePart(t).AsUint16x8()
-}
-
-// LoadUint8x32SlicePart loads a Uint8x32 from the slice s.
-// If s has fewer than 32 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 32 or more elements, the function is equivalent to LoadUint8x32Slice.
-func LoadUint8x32SlicePart(s []uint8) Uint8x32 {
-       if len(s) == 0 {
-               var zero Uint8x32
-               return zero
-       }
-       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt8x32SlicePart(t).AsUint8x32()
-}
-
-// LoadUint16x16SlicePart loads a Uint16x16 from the slice s.
-// If s has fewer than 16 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 16 or more elements, the function is equivalent to LoadUint16x16Slice.
-func LoadUint16x16SlicePart(s []uint16) Uint16x16 {
-       if len(s) == 0 {
-               var zero Uint16x16
-               return zero
-       }
-       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt16x16SlicePart(t).AsUint16x16()
-}
-
-/* unsigned versions of integer slice part stores*/
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint8x16) StoreSlicePart(s []uint8) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt8x16().StoreSlicePart(t)
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint16x8) StoreSlicePart(s []uint16) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt16x8().StoreSlicePart(t)
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 32 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint8x32) StoreSlicePart(s []uint8) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int8)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt8x32().StoreSlicePart(t)
+var vecMask64 = [16]int64{
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       0, 0, 0, 0,
+       0, 0, 0, 0,
 }
 
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 16 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint16x16) StoreSlicePart(s []uint16) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int16)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt16x16().StoreSlicePart(t)
+var vecMask32 = [32]int32{
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       -1, -1, -1, -1,
+       0, 0, 0, 0,
+       0, 0, 0, 0,
+       0, 0, 0, 0,
+       0, 0, 0, 0,
 }
 
 /* 256-bit int vector loads and stores made from 128-bit parts */
@@ -389,401 +313,3 @@ func (x Int16x8) StoreSlicePart(s []int16) {
        }
        return
 }
-
-var vecMask64 = [16]int64{
-       -1, -1, -1, -1,
-       -1, -1, -1, -1,
-       0, 0, 0, 0,
-       0, 0, 0, 0,
-}
-
-// paInt32x4 is an unchecked cast from a slice to an
-// pointer-to-array type, for used in a masked
-// load/store.  In practice, the slice will be too
-// short, so this has to be unsafe, and its only
-// use must be with an instruction with masked
-// load/store effect (including faults).
-func paInt32x4(s []int32) *[4]int32 {
-       return (*[4]int32)(unsafe.Pointer(&s[0]))
-}
-
-func paInt32x8(s []int32) *[8]int32 {
-       return (*[8]int32)(unsafe.Pointer(&s[0]))
-}
-
-func paInt64x2(s []int64) *[2]int64 {
-       return (*[2]int64)(unsafe.Pointer(&s[0]))
-}
-
-func paInt64x4(s []int64) *[4]int64 {
-       return (*[4]int64)(unsafe.Pointer(&s[0]))
-}
-
-// For 512-bit masked loads/stores
-
-func paInt64x8(s []int64) *[8]int64 {
-       return (*[8]int64)(unsafe.Pointer(&s[0]))
-}
-
-func paInt32x16(s []int32) *[16]int32 {
-       return (*[16]int32)(unsafe.Pointer(&s[0]))
-}
-
-func paInt16x32(s []int16) *[32]int16 {
-       return (*[32]int16)(unsafe.Pointer(&s[0]))
-}
-
-func paInt8x64(s []int8) *[64]int8 {
-       return (*[64]int8)(unsafe.Pointer(&s[0]))
-}
-
-/* 32 and 64-bit slice-part loads for AVX2 (128 and 256 bit) */
-
-// LoadInt32x4SlicePart loads a Int32x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadInt32x4Slice.
-func LoadInt32x4SlicePart(s []int32) Int32x4 {
-       l := len(s)
-       if l >= 4 {
-               return LoadInt32x4Slice(s)
-       }
-       if l == 0 {
-               var x Int32x4
-               return x
-       }
-       p := int32atP64(&vecMask64[0])
-       mask := unsafe.Slice(p, 32)[16-l:]
-       return LoadMaskedInt32x4(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
-func (x Int32x4) StoreSlicePart(s []int32) {
-       l := len(s)
-       if l >= 4 {
-               x.StoreSlice(s)
-               return
-       }
-       if l == 0 {
-               return
-       }
-       p := int32atP64(&vecMask64[0])
-       mask := unsafe.Slice(p, 32)[16-l:]
-       x.StoreMasked(paInt32x4(s), LoadInt32x4Slice(mask).AsMask32x4())
-}
-
-// LoadInt32x8SlicePart loads a Int32x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadInt32x8Slice.
-func LoadInt32x8SlicePart(s []int32) Int32x8 {
-       l := len(s)
-       if l >= 8 {
-               return LoadInt32x8Slice(s)
-       }
-       if l == 0 {
-               var x Int32x8
-               return x
-       }
-       p := int32atP64(&vecMask64[0])
-       mask := unsafe.Slice(p, 32)[16-l:]
-       return LoadMaskedInt32x8(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
-}
-
-// LoadInt64x2SlicePart loads a Int64x2 from the slice s.
-// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 2 or more elements, the function is equivalent to LoadInt64x2Slice.
-func LoadInt64x2SlicePart(s []int64) Int64x2 {
-       l := len(s)
-       if l >= 2 {
-               return LoadInt64x2Slice(s)
-       }
-       if l == 0 {
-               var x Int64x2
-               return x
-       }
-
-       mask := vecMask64[8-l:]
-       return LoadMaskedInt64x2(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
-}
-
-// LoadInt64x4SlicePart loads a Int64x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadInt64x4Slice.
-func LoadInt64x4SlicePart(s []int64) Int64x4 {
-       l := len(s)
-       if l >= 4 {
-               return LoadInt64x4Slice(s)
-       }
-       if l == 0 {
-               var x Int64x4
-               return x
-       }
-
-       mask := vecMask64[8-l:]
-       return LoadMaskedInt64x4(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
-func (x Int32x8) StoreSlicePart(s []int32) {
-       l := len(s)
-       if l >= 8 {
-               x.StoreSlice(s)
-               return
-       }
-       if l == 0 {
-               return
-       }
-       p := int32atP64(&vecMask64[0])
-       mask := unsafe.Slice(p, 32)[16-l:]
-       x.StoreMasked(paInt32x8(s), LoadInt32x8Slice(mask).AsMask32x8())
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 2 or more elements, the method is equivalent to x.StoreSlice.
-func (x Int64x2) StoreSlicePart(s []int64) {
-       l := len(s)
-       if l >= 2 {
-               x.StoreSlice(s)
-               return
-       }
-       if l == 0 {
-               return
-       }
-       mask := vecMask64[8-l:]
-       x.StoreMasked(paInt64x2(s), LoadInt64x2Slice(mask).AsMask64x2())
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
-func (x Int64x4) StoreSlicePart(s []int64) {
-       l := len(s)
-       if l >= 4 {
-               x.StoreSlice(s)
-               return
-       }
-       if l == 0 {
-               return
-       }
-       mask := vecMask64[8-l:]
-       x.StoreMasked(paInt64x4(s), LoadInt64x4Slice(mask).AsMask64x4())
-}
-
-// Handle float32, float64, uint32, and uint64 with ugly casts.
-
-// LoadUint32x4SlicePart loads a Uint32x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadUint32x4Slice.
-func LoadUint32x4SlicePart(s []uint32) Uint32x4 {
-       if len(s) == 0 {
-               var zero Uint32x4
-               return zero
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt32x4SlicePart(t).AsUint32x4()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint32x4) StoreSlicePart(s []uint32) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt32x4().StoreSlicePart(t)
-}
-
-// LoadUint32x8SlicePart loads a Uint32x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadUint32x8Slice.
-func LoadUint32x8SlicePart(s []uint32) Uint32x8 {
-       if len(s) == 0 {
-               var zero Uint32x8
-               return zero
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt32x8SlicePart(t).AsUint32x8()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint32x8) StoreSlicePart(s []uint32) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt32x8().StoreSlicePart(t)
-}
-
-// LoadUint64x2SlicePart loads a Uint64x2 from the slice s.
-// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 2 or more elements, the function is equivalent to LoadUint64x2Slice.
-func LoadUint64x2SlicePart(s []uint64) Uint64x2 {
-       if len(s) == 0 {
-               var zero Uint64x2
-               return zero
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt64x2SlicePart(t).AsUint64x2()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 2 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint64x2) StoreSlicePart(s []uint64) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt64x2().StoreSlicePart(t)
-}
-
-// LoadUint64x4SlicePart loads a Uint64x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadUint64x4Slice.
-func LoadUint64x4SlicePart(s []uint64) Uint64x4 {
-       if len(s) == 0 {
-               var zero Uint64x4
-               return zero
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt64x4SlicePart(t).AsUint64x4()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
-func (x Uint64x4) StoreSlicePart(s []uint64) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt64x4().StoreSlicePart(t)
-}
-
-// Float32xK and Float64xK
-
-// LoadFloat32x4SlicePart loads a Float32x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadFloat32x4Slice.
-func LoadFloat32x4SlicePart(s []float32) Float32x4 {
-       if len(s) == 0 {
-               var zero Float32x4
-               return zero
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt32x4SlicePart(t).AsFloat32x4()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
-func (x Float32x4) StoreSlicePart(s []float32) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt32x4().StoreSlicePart(t)
-}
-
-// LoadFloat32x8SlicePart loads a Float32x8 from the slice s.
-// If s has fewer than 8 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 8 or more elements, the function is equivalent to LoadFloat32x8Slice.
-func LoadFloat32x8SlicePart(s []float32) Float32x8 {
-       if len(s) == 0 {
-               var zero Float32x8
-               return zero
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt32x8SlicePart(t).AsFloat32x8()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 8 or more elements, the method is equivalent to x.StoreSlice.
-func (x Float32x8) StoreSlicePart(s []float32) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int32)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt32x8().StoreSlicePart(t)
-}
-
-// LoadFloat64x2SlicePart loads a Float64x2 from the slice s.
-// If s has fewer than 2 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 2 or more elements, the function is equivalent to LoadFloat64x2Slice.
-func LoadFloat64x2SlicePart(s []float64) Float64x2 {
-       if len(s) == 0 {
-               var zero Float64x2
-               return zero
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt64x2SlicePart(t).AsFloat64x2()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 2 or more elements, the method is equivalent to x.StoreSlice.
-func (x Float64x2) StoreSlicePart(s []float64) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt64x2().StoreSlicePart(t)
-}
-
-// LoadFloat64x4SlicePart loads a Float64x4 from the slice s.
-// If s has fewer than 4 elements, the remaining elements of the vector are filled with zeroes.
-// If s has 4 or more elements, the function is equivalent to LoadFloat64x4Slice.
-func LoadFloat64x4SlicePart(s []float64) Float64x4 {
-       if len(s) == 0 {
-               var zero Float64x4
-               return zero
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       return LoadInt64x4SlicePart(t).AsFloat64x4()
-}
-
-// StoreSlicePart stores the elements of x into the slice s.
-// It stores as many elements as will fit in s.
-// If s has 4 or more elements, the method is equivalent to x.StoreSlice.
-func (x Float64x4) StoreSlicePart(s []float64) {
-       if len(s) == 0 {
-               return
-       }
-       t := unsafe.Slice((*int64)(unsafe.Pointer(&s[0])), len(s))
-       x.AsInt64x4().StoreSlicePart(t)
-}
-
-func LoadInt64x8SlicePart(s []int64) Int64x8 {
-       l := len(s)
-       if l >= 8 {
-               return LoadInt64x8Slice(s)
-       }
-       if l == 0 {
-               var x Int64x8
-               return x
-       }
-
-       mask := Mask64x8FromBits(0xff >> (8 - l))
-       return LoadMaskedInt64x8(paInt64x8(s), mask)
-}
-
-func (x Int64x8) StoreSlicePart(s []int64) {
-       l := len(s)
-       if l >= 8 {
-               x.StoreSlice(s)
-               return
-       }
-       if l == 0 {
-               return
-       }
-       mask := Mask64x8FromBits(0xff >> (8 - l))
-       x.StoreMasked(paInt64x8(s), mask)
-}
index c9492bea1ba2dc69a244a9d3b8bf1c388043128a..07869e954b3e5b3f4cfec8317a245936240f42b0 100644 (file)
@@ -367,7 +367,7 @@ func TestSlicePartInt64(t *testing.T) {
                b := make([]int64, L)
                v.StoreSlice(b)
                // test the load
-               checkSlicesLogInput(t, b, d, func() { t.Helper(); t.Logf("Len(e)=%d", len(e)) })
+               checkSlicesLogInput(t, b, d, 0.0, func() { t.Helper(); t.Logf("Len(e)=%d", len(e)) })
 
                // Test the store
                f := make([]int64, L+1)
index e48ec2409c133c77a9bd54117c8b3f051438d8f5..401270c7bdcc8d271edee96075310a6c25d9c76a 100644 (file)
@@ -25,7 +25,7 @@ func testInt8x16Ternary(t *testing.T, f func(_, _, _ simd.Int8x16) simd.Int8x16,
                g := make([]int8, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -41,7 +41,7 @@ func testInt16x8Ternary(t *testing.T, f func(_, _, _ simd.Int16x8) simd.Int16x8,
                g := make([]int16, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -57,7 +57,7 @@ func testInt32x4Ternary(t *testing.T, f func(_, _, _ simd.Int32x4) simd.Int32x4,
                g := make([]int32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -73,7 +73,7 @@ func testInt64x2Ternary(t *testing.T, f func(_, _, _ simd.Int64x2) simd.Int64x2,
                g := make([]int64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -89,7 +89,7 @@ func testUint8x16Ternary(t *testing.T, f func(_, _, _ simd.Uint8x16) simd.Uint8x
                g := make([]uint8, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -105,7 +105,7 @@ func testUint16x8Ternary(t *testing.T, f func(_, _, _ simd.Uint16x8) simd.Uint16
                g := make([]uint16, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -121,7 +121,7 @@ func testUint32x4Ternary(t *testing.T, f func(_, _, _ simd.Uint32x4) simd.Uint32
                g := make([]uint32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -137,7 +137,7 @@ func testUint64x2Ternary(t *testing.T, f func(_, _, _ simd.Uint64x2) simd.Uint64
                g := make([]uint64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -153,7 +153,7 @@ func testFloat32x4Ternary(t *testing.T, f func(_, _, _ simd.Float32x4) simd.Floa
                g := make([]float32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -169,7 +169,7 @@ func testFloat64x2Ternary(t *testing.T, f func(_, _, _ simd.Float64x2) simd.Floa
                g := make([]float64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -185,7 +185,7 @@ func testInt8x32Ternary(t *testing.T, f func(_, _, _ simd.Int8x32) simd.Int8x32,
                g := make([]int8, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -201,7 +201,7 @@ func testInt16x16Ternary(t *testing.T, f func(_, _, _ simd.Int16x16) simd.Int16x
                g := make([]int16, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -217,7 +217,7 @@ func testInt32x8Ternary(t *testing.T, f func(_, _, _ simd.Int32x8) simd.Int32x8,
                g := make([]int32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -233,7 +233,7 @@ func testInt64x4Ternary(t *testing.T, f func(_, _, _ simd.Int64x4) simd.Int64x4,
                g := make([]int64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -249,7 +249,7 @@ func testUint8x32Ternary(t *testing.T, f func(_, _, _ simd.Uint8x32) simd.Uint8x
                g := make([]uint8, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -265,7 +265,7 @@ func testUint16x16Ternary(t *testing.T, f func(_, _, _ simd.Uint16x16) simd.Uint
                g := make([]uint16, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -281,7 +281,7 @@ func testUint32x8Ternary(t *testing.T, f func(_, _, _ simd.Uint32x8) simd.Uint32
                g := make([]uint32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -297,7 +297,7 @@ func testUint64x4Ternary(t *testing.T, f func(_, _, _ simd.Uint64x4) simd.Uint64
                g := make([]uint64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -313,7 +313,7 @@ func testFloat32x8Ternary(t *testing.T, f func(_, _, _ simd.Float32x8) simd.Floa
                g := make([]float32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -329,7 +329,7 @@ func testFloat64x4Ternary(t *testing.T, f func(_, _, _ simd.Float64x4) simd.Floa
                g := make([]float64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -345,7 +345,7 @@ func testInt8x64Ternary(t *testing.T, f func(_, _, _ simd.Int8x64) simd.Int8x64,
                g := make([]int8, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -361,7 +361,7 @@ func testInt16x32Ternary(t *testing.T, f func(_, _, _ simd.Int16x32) simd.Int16x
                g := make([]int16, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -377,7 +377,7 @@ func testInt32x16Ternary(t *testing.T, f func(_, _, _ simd.Int32x16) simd.Int32x
                g := make([]int32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -393,7 +393,7 @@ func testInt64x8Ternary(t *testing.T, f func(_, _, _ simd.Int64x8) simd.Int64x8,
                g := make([]int64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -409,7 +409,7 @@ func testUint8x64Ternary(t *testing.T, f func(_, _, _ simd.Uint8x64) simd.Uint8x
                g := make([]uint8, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -425,7 +425,7 @@ func testUint16x32Ternary(t *testing.T, f func(_, _, _ simd.Uint16x32) simd.Uint
                g := make([]uint16, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -441,7 +441,7 @@ func testUint32x16Ternary(t *testing.T, f func(_, _, _ simd.Uint32x16) simd.Uint
                g := make([]uint32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -457,7 +457,7 @@ func testUint64x8Ternary(t *testing.T, f func(_, _, _ simd.Uint64x8) simd.Uint64
                g := make([]uint64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -473,7 +473,7 @@ func testFloat32x16Ternary(t *testing.T, f func(_, _, _ simd.Float32x16) simd.Fl
                g := make([]float32, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
 
@@ -489,6 +489,57 @@ func testFloat64x8Ternary(t *testing.T, f func(_, _, _ simd.Float64x8) simd.Floa
                g := make([]float64, n)
                f(a, b, c).StoreSlice(g)
                w := want(x, y, z)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+       })
+}
+
+// testFloat32x4TernaryFlaky tests the simd ternary 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 testFloat32x4TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x4) simd.Float32x4, want func(x, y, z []float32) []float32, flakiness float64) {
+       n := 4
+       t.Helper()
+       forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
+               t.Helper()
+               a := simd.LoadFloat32x4Slice(x)
+               b := simd.LoadFloat32x4Slice(y)
+               c := simd.LoadFloat32x4Slice(z)
+               g := make([]float32, n)
+               f(a, b, c).StoreSlice(g)
+               w := want(x, y, z)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+       })
+}
+
+// testFloat32x8TernaryFlaky tests the simd ternary 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 testFloat32x8TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x8) simd.Float32x8, want func(x, y, z []float32) []float32, flakiness float64) {
+       n := 8
+       t.Helper()
+       forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
+               t.Helper()
+               a := simd.LoadFloat32x8Slice(x)
+               b := simd.LoadFloat32x8Slice(y)
+               c := simd.LoadFloat32x8Slice(z)
+               g := make([]float32, n)
+               f(a, b, c).StoreSlice(g)
+               w := want(x, y, z)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
+       })
+}
+
+// testFloat32x16TernaryFlaky tests the simd ternary 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 testFloat32x16TernaryFlaky(t *testing.T, f func(x, y, z simd.Float32x16) simd.Float32x16, want func(x, y, z []float32) []float32, flakiness float64) {
+       n := 16
+       t.Helper()
+       forSliceTriple(t, float32s, n, func(x, y, z []float32) bool {
+               t.Helper()
+               a := simd.LoadFloat32x16Slice(x)
+               b := simd.LoadFloat32x16Slice(y)
+               c := simd.LoadFloat32x16Slice(z)
+               g := make([]float32, n)
+               f(a, b, c).StoreSlice(g)
+               w := want(x, y, z)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y); t.Logf("z=%v", z) })
        })
 }
index afca850d6147e8844c30eb1d5755017e956d236e..9ce0ff7676eaa3b6ba3b1e2c2fb207a4411629db 100644 (file)
@@ -13,9 +13,9 @@ import (
 
 func TestFMA(t *testing.T) {
        if simd.HasAVX512() {
-               testFloat32x4Ternary(t, simd.Float32x4.FusedMultiplyAdd, fmaSlice[float32])
-               testFloat32x8Ternary(t, simd.Float32x8.FusedMultiplyAdd, fmaSlice[float32])
-               testFloat32x16Ternary(t, simd.Float32x16.FusedMultiplyAdd, fmaSlice[float32])
+               testFloat32x4TernaryFlaky(t, simd.Float32x4.FusedMultiplyAdd, fmaSlice[float32], 0.001)
+               testFloat32x8TernaryFlaky(t, simd.Float32x8.FusedMultiplyAdd, fmaSlice[float32], 0.001)
+               testFloat32x16TernaryFlaky(t, simd.Float32x16.FusedMultiplyAdd, fmaSlice[float32], 0.001)
                testFloat64x2Ternary(t, simd.Float64x2.FusedMultiplyAdd, fmaSlice[float64])
                testFloat64x4Ternary(t, simd.Float64x4.FusedMultiplyAdd, fmaSlice[float64])
                testFloat64x8Ternary(t, simd.Float64x8.FusedMultiplyAdd, fmaSlice[float64])
index 4e0f09428e76bb73d2716c89fea6f37cc12a865a..f5b9e3b676b21efc9d7f57a54cfdb29267a26f72 100644 (file)
@@ -23,7 +23,7 @@ func testInt8x16Unary(t *testing.T, f func(_ simd.Int8x16) simd.Int8x16, want fu
                g := make([]int8, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -37,7 +37,7 @@ func testInt16x8Unary(t *testing.T, f func(_ simd.Int16x8) simd.Int16x8, want fu
                g := make([]int16, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -51,7 +51,7 @@ func testInt32x4Unary(t *testing.T, f func(_ simd.Int32x4) simd.Int32x4, want fu
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -65,7 +65,7 @@ func testInt64x2Unary(t *testing.T, f func(_ simd.Int64x2) simd.Int64x2, want fu
                g := make([]int64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -79,7 +79,7 @@ func testUint8x16Unary(t *testing.T, f func(_ simd.Uint8x16) simd.Uint8x16, want
                g := make([]uint8, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -93,7 +93,7 @@ func testUint16x8Unary(t *testing.T, f func(_ simd.Uint16x8) simd.Uint16x8, want
                g := make([]uint16, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -107,7 +107,7 @@ func testUint32x4Unary(t *testing.T, f func(_ simd.Uint32x4) simd.Uint32x4, want
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -121,7 +121,7 @@ func testUint64x2Unary(t *testing.T, f func(_ simd.Uint64x2) simd.Uint64x2, want
                g := make([]uint64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -135,7 +135,7 @@ func testFloat32x4Unary(t *testing.T, f func(_ simd.Float32x4) simd.Float32x4, w
                g := make([]float32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -149,7 +149,7 @@ func testFloat64x2Unary(t *testing.T, f func(_ simd.Float64x2) simd.Float64x2, w
                g := make([]float64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -163,7 +163,7 @@ func testInt8x32Unary(t *testing.T, f func(_ simd.Int8x32) simd.Int8x32, want fu
                g := make([]int8, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -177,7 +177,7 @@ func testInt16x16Unary(t *testing.T, f func(_ simd.Int16x16) simd.Int16x16, want
                g := make([]int16, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -191,7 +191,7 @@ func testInt32x8Unary(t *testing.T, f func(_ simd.Int32x8) simd.Int32x8, want fu
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -205,7 +205,7 @@ func testInt64x4Unary(t *testing.T, f func(_ simd.Int64x4) simd.Int64x4, want fu
                g := make([]int64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -219,7 +219,7 @@ func testUint8x32Unary(t *testing.T, f func(_ simd.Uint8x32) simd.Uint8x32, want
                g := make([]uint8, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -233,7 +233,7 @@ func testUint16x16Unary(t *testing.T, f func(_ simd.Uint16x16) simd.Uint16x16, w
                g := make([]uint16, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -247,7 +247,7 @@ func testUint32x8Unary(t *testing.T, f func(_ simd.Uint32x8) simd.Uint32x8, want
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -261,7 +261,7 @@ func testUint64x4Unary(t *testing.T, f func(_ simd.Uint64x4) simd.Uint64x4, want
                g := make([]uint64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -275,7 +275,7 @@ func testFloat32x8Unary(t *testing.T, f func(_ simd.Float32x8) simd.Float32x8, w
                g := make([]float32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -289,7 +289,7 @@ func testFloat64x4Unary(t *testing.T, f func(_ simd.Float64x4) simd.Float64x4, w
                g := make([]float64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -303,7 +303,7 @@ func testInt8x64Unary(t *testing.T, f func(_ simd.Int8x64) simd.Int8x64, want fu
                g := make([]int8, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -317,7 +317,7 @@ func testInt16x32Unary(t *testing.T, f func(_ simd.Int16x32) simd.Int16x32, want
                g := make([]int16, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -331,7 +331,7 @@ func testInt32x16Unary(t *testing.T, f func(_ simd.Int32x16) simd.Int32x16, want
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -345,7 +345,7 @@ func testInt64x8Unary(t *testing.T, f func(_ simd.Int64x8) simd.Int64x8, want fu
                g := make([]int64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -359,7 +359,7 @@ func testUint8x64Unary(t *testing.T, f func(_ simd.Uint8x64) simd.Uint8x64, want
                g := make([]uint8, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -373,7 +373,7 @@ func testUint16x32Unary(t *testing.T, f func(_ simd.Uint16x32) simd.Uint16x32, w
                g := make([]uint16, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -387,7 +387,7 @@ func testUint32x16Unary(t *testing.T, f func(_ simd.Uint32x16) simd.Uint32x16, w
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -401,7 +401,7 @@ func testUint64x8Unary(t *testing.T, f func(_ simd.Uint64x8) simd.Uint64x8, want
                g := make([]uint64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -415,7 +415,7 @@ func testFloat32x16Unary(t *testing.T, f func(_ simd.Float32x16) simd.Float32x16
                g := make([]float32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -429,7 +429,7 @@ func testFloat64x8Unary(t *testing.T, f func(_ simd.Float64x8) simd.Float64x8, w
                g := make([]float64, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -443,7 +443,7 @@ func testFloat32x4UnaryToInt32(t *testing.T, f func(x simd.Float32x4) simd.Int32
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -457,7 +457,7 @@ func testFloat32x8UnaryToInt32(t *testing.T, f func(x simd.Float32x8) simd.Int32
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -471,7 +471,7 @@ func testFloat32x16UnaryToInt32(t *testing.T, f func(x simd.Float32x16) simd.Int
                g := make([]int32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -485,7 +485,7 @@ func testFloat32x4UnaryToUint32(t *testing.T, f func(x simd.Float32x4) simd.Uint
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -499,7 +499,7 @@ func testFloat32x8UnaryToUint32(t *testing.T, f func(x simd.Float32x8) simd.Uint
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", x) })
+               return checkSlicesLogInput(t, g, w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
 
@@ -513,6 +513,96 @@ func testFloat32x16UnaryToUint32(t *testing.T, f func(x simd.Float32x16) simd.Ui
                g := make([]uint32, n)
                f(a).StoreSlice(g)
                w := want(x)
-               return checkSlicesLogInput(t, g, w, func() { t.Helper(); t.Logf("x=%v", 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) {
+       n := 4
+       t.Helper()
+       forSlice(t, float32s, n, func(x []float32) bool {
+               t.Helper()
+               a := simd.LoadFloat32x4Slice(x)
+               g := make([]float32, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat64x2UnaryFlaky 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 testFloat64x2UnaryFlaky(t *testing.T, f func(x simd.Float64x2) simd.Float64x2, want func(x []float64) []float64, flakiness float64) {
+       n := 2
+       t.Helper()
+       forSlice(t, float64s, n, func(x []float64) bool {
+               t.Helper()
+               a := simd.LoadFloat64x2Slice(x)
+               g := make([]float64, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat32x8UnaryFlaky 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 testFloat32x8UnaryFlaky(t *testing.T, f func(x simd.Float32x8) simd.Float32x8, want func(x []float32) []float32, flakiness float64) {
+       n := 8
+       t.Helper()
+       forSlice(t, float32s, n, func(x []float32) bool {
+               t.Helper()
+               a := simd.LoadFloat32x8Slice(x)
+               g := make([]float32, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat64x4UnaryFlaky 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 testFloat64x4UnaryFlaky(t *testing.T, f func(x simd.Float64x4) simd.Float64x4, want func(x []float64) []float64, flakiness float64) {
+       n := 4
+       t.Helper()
+       forSlice(t, float64s, n, func(x []float64) bool {
+               t.Helper()
+               a := simd.LoadFloat64x4Slice(x)
+               g := make([]float64, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat32x16UnaryFlaky 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 testFloat32x16UnaryFlaky(t *testing.T, f func(x simd.Float32x16) simd.Float32x16, want func(x []float32) []float32, flakiness float64) {
+       n := 16
+       t.Helper()
+       forSlice(t, float32s, n, func(x []float32) bool {
+               t.Helper()
+               a := simd.LoadFloat32x16Slice(x)
+               g := make([]float32, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat64x8UnaryFlaky 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 testFloat64x8UnaryFlaky(t *testing.T, f func(x simd.Float64x8) simd.Float64x8, want func(x []float64) []float64, flakiness float64) {
+       n := 8
+       t.Helper()
+       forSlice(t, float64s, n, func(x []float64) bool {
+               t.Helper()
+               a := simd.LoadFloat64x8Slice(x)
+               g := make([]float64, n)
+               f(a).StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, g, w, flakiness, func() { t.Helper(); t.Logf("x=%v", x) })
        })
 }
index 6565df30965742354d585ee50f1db5fb296e12e7..4263b81cd734ab9bac164d42354e40a7b25d644e 100644 (file)
@@ -7,6 +7,7 @@
 package simd_test
 
 import (
+       "math"
        "simd"
        "testing"
 )
@@ -88,6 +89,23 @@ func TestToInt32(t *testing.T) {
        testFloat32x8UnaryToInt32(t, simd.Float32x8.ConvertToInt32, toInt32Slice[float32])
 }
 
+func TestDiffWithCeilWithPrecision(t *testing.T) {
+       if !simd.HasAVX512() {
+               t.Skip("Needs AVX512")
+       }
+       testFloat64x8UnaryFlaky(t,
+               func(x simd.Float64x8) simd.Float64x8 { return x.DiffWithCeilWithPrecision(0) },
+               map1(ceilResidueForPrecision[float64](0)),
+               0.001)
+       testFloat64x8UnaryFlaky(t,
+               func(x simd.Float64x8) simd.Float64x8 { return x.DiffWithCeilWithPrecision(1) },
+               map1(ceilResidueForPrecision[float64](1)),
+               0.001)
+       testFloat64x8Unary(t,
+               func(x simd.Float64x8) simd.Float64x8 { return x.Sub(x.CeilWithPrecision(0)) },
+               map1[float64](func(x float64) float64 { return x - math.Ceil(x) }))
+}
+
 func TestToUint32(t *testing.T) {
        if !simd.HasAVX512() {
                t.Skip("Needs AVX512")
diff --git a/src/simd/unsafe_helpers.go b/src/simd/unsafe_helpers.go
new file mode 100644 (file)
index 0000000..c6ea50d
--- /dev/null
@@ -0,0 +1,217 @@
+// Code generated by 'go run genfiles.go'; DO NOT EDIT.
+
+//go:build goexperiment.simd
+
+package simd
+
+import "unsafe"
+
+// paInt8x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt8x16(s []int8) *[16]int8 {
+       return (*[16]int8)(unsafe.Pointer(&s[0]))
+}
+
+// paInt16x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt16x8(s []int16) *[8]int16 {
+       return (*[8]int16)(unsafe.Pointer(&s[0]))
+}
+
+// paInt32x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt32x4(s []int32) *[4]int32 {
+       return (*[4]int32)(unsafe.Pointer(&s[0]))
+}
+
+// paInt64x2 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt64x2(s []int64) *[2]int64 {
+       return (*[2]int64)(unsafe.Pointer(&s[0]))
+}
+
+// paUint8x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint8x16(s []uint8) *[16]uint8 {
+       return (*[16]uint8)(unsafe.Pointer(&s[0]))
+}
+
+// paUint16x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint16x8(s []uint16) *[8]uint16 {
+       return (*[8]uint16)(unsafe.Pointer(&s[0]))
+}
+
+// paUint32x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint32x4(s []uint32) *[4]uint32 {
+       return (*[4]uint32)(unsafe.Pointer(&s[0]))
+}
+
+// paUint64x2 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint64x2(s []uint64) *[2]uint64 {
+       return (*[2]uint64)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat32x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat32x4(s []float32) *[4]float32 {
+       return (*[4]float32)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat64x2 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat64x2(s []float64) *[2]float64 {
+       return (*[2]float64)(unsafe.Pointer(&s[0]))
+}
+
+// paInt8x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt8x32(s []int8) *[32]int8 {
+       return (*[32]int8)(unsafe.Pointer(&s[0]))
+}
+
+// paInt16x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt16x16(s []int16) *[16]int16 {
+       return (*[16]int16)(unsafe.Pointer(&s[0]))
+}
+
+// paInt32x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt32x8(s []int32) *[8]int32 {
+       return (*[8]int32)(unsafe.Pointer(&s[0]))
+}
+
+// paInt64x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt64x4(s []int64) *[4]int64 {
+       return (*[4]int64)(unsafe.Pointer(&s[0]))
+}
+
+// paUint8x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint8x32(s []uint8) *[32]uint8 {
+       return (*[32]uint8)(unsafe.Pointer(&s[0]))
+}
+
+// paUint16x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint16x16(s []uint16) *[16]uint16 {
+       return (*[16]uint16)(unsafe.Pointer(&s[0]))
+}
+
+// paUint32x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint32x8(s []uint32) *[8]uint32 {
+       return (*[8]uint32)(unsafe.Pointer(&s[0]))
+}
+
+// paUint64x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint64x4(s []uint64) *[4]uint64 {
+       return (*[4]uint64)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat32x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat32x8(s []float32) *[8]float32 {
+       return (*[8]float32)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat64x4 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat64x4(s []float64) *[4]float64 {
+       return (*[4]float64)(unsafe.Pointer(&s[0]))
+}
+
+// paInt8x64 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt8x64(s []int8) *[64]int8 {
+       return (*[64]int8)(unsafe.Pointer(&s[0]))
+}
+
+// paInt16x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt16x32(s []int16) *[32]int16 {
+       return (*[32]int16)(unsafe.Pointer(&s[0]))
+}
+
+// paInt32x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt32x16(s []int32) *[16]int32 {
+       return (*[16]int32)(unsafe.Pointer(&s[0]))
+}
+
+// paInt64x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paInt64x8(s []int64) *[8]int64 {
+       return (*[8]int64)(unsafe.Pointer(&s[0]))
+}
+
+// paUint8x64 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint8x64(s []uint8) *[64]uint8 {
+       return (*[64]uint8)(unsafe.Pointer(&s[0]))
+}
+
+// paUint16x32 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint16x32(s []uint16) *[32]uint16 {
+       return (*[32]uint16)(unsafe.Pointer(&s[0]))
+}
+
+// paUint32x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint32x16(s []uint32) *[16]uint32 {
+       return (*[16]uint32)(unsafe.Pointer(&s[0]))
+}
+
+// paUint64x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paUint64x8(s []uint64) *[8]uint64 {
+       return (*[8]uint64)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat32x16 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat32x16(s []float32) *[16]float32 {
+       return (*[16]float32)(unsafe.Pointer(&s[0]))
+}
+
+// paFloat64x8 returns a type-unsafe pointer to array that can
+// only be used with partial load/store operations that only
+// access the known-safe portions of the array.
+func paFloat64x8(s []float64) *[8]float64 {
+       return (*[8]float64)(unsafe.Pointer(&s[0]))
+}