From d375b95357fdf8cdfec722b3672dcc425acf10ad Mon Sep 17 00:00:00 2001 From: David Chase Date: Fri, 25 Jul 2025 15:18:11 -0400 Subject: [PATCH] [dev.simd] simd: move lots of slice functions and methods to generated code 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 Reviewed-by: Cherry Mui --- src/simd/binary_helpers_test.go | 60 +- src/simd/compare_helpers_test.go | 60 +- src/simd/comparemasked_helpers_test.go | 60 +- src/simd/genfiles.go | 238 +++++++- src/simd/helpers_test.go | 32 +- src/simd/simulation_helpers_test.go | 20 +- src/simd/slice_amd64.go | 808 +++++++++++++++++++++++++ src/simd/slicepart_amd64.go | 506 +--------------- src/simd/slicepart_test.go | 2 +- src/simd/ternary_helpers_test.go | 111 +++- src/simd/ternary_test.go | 6 +- src/simd/unary_helpers_test.go | 162 +++-- src/simd/unary_test.go | 18 + src/simd/unsafe_helpers.go | 217 +++++++ 14 files changed, 1624 insertions(+), 676 deletions(-) create mode 100644 src/simd/unsafe_helpers.go diff --git a/src/simd/binary_helpers_test.go b/src/simd/binary_helpers_test.go index fbf31beb7c..82cf784bca 100644 --- a/src/simd/binary_helpers_test.go +++ b/src/simd/binary_helpers_test.go @@ -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) }) }) } diff --git a/src/simd/compare_helpers_test.go b/src/simd/compare_helpers_test.go index e6d7c82c8f..aef703c66a 100644 --- a/src/simd/compare_helpers_test.go +++ b/src/simd/compare_helpers_test.go @@ -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) }) }) } diff --git a/src/simd/comparemasked_helpers_test.go b/src/simd/comparemasked_helpers_test.go index 0baba27e54..542145c11e 100644 --- a/src/simd/comparemasked_helpers_test.go +++ b/src/simd/comparemasked_helpers_test.go @@ -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) }) }) } diff --git a/src/simd/genfiles.go b/src/simd/genfiles.go index 76f16392e6..269659a653 100644 --- a/src/simd/genfiles.go +++ b/src/simd/genfiles.go @@ -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}} { + 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) diff --git a/src/simd/helpers_test.go b/src/simd/helpers_test.go index 14490a84b2..6c681abe98 100644 --- a/src/simd/helpers_test.go +++ b/src/simd/helpers_test.go @@ -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)}) diff --git a/src/simd/simulation_helpers_test.go b/src/simd/simulation_helpers_test.go index ec3d795249..8677216d9f 100644 --- a/src/simd/simulation_helpers_test.go +++ b/src/simd/simulation_helpers_test.go @@ -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 { diff --git a/src/simd/slice_amd64.go b/src/simd/slice_amd64.go index ad7bce8964..bd1d4f1530 100644 --- a/src/simd/slice_amd64.go +++ b/src/simd/slice_amd64.go @@ -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) +} diff --git a/src/simd/slicepart_amd64.go b/src/simd/slicepart_amd64.go index 3fcfc6255b..6d0b5a41f2 100644 --- a/src/simd/slicepart_amd64.go +++ b/src/simd/slicepart_amd64.go @@ -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) -} diff --git a/src/simd/slicepart_test.go b/src/simd/slicepart_test.go index c9492bea1b..07869e954b 100644 --- a/src/simd/slicepart_test.go +++ b/src/simd/slicepart_test.go @@ -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) diff --git a/src/simd/ternary_helpers_test.go b/src/simd/ternary_helpers_test.go index e48ec2409c..401270c7bd 100644 --- a/src/simd/ternary_helpers_test.go +++ b/src/simd/ternary_helpers_test.go @@ -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) }) }) } diff --git a/src/simd/ternary_test.go b/src/simd/ternary_test.go index afca850d61..9ce0ff7676 100644 --- a/src/simd/ternary_test.go +++ b/src/simd/ternary_test.go @@ -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]) diff --git a/src/simd/unary_helpers_test.go b/src/simd/unary_helpers_test.go index 4e0f09428e..f5b9e3b676 100644 --- a/src/simd/unary_helpers_test.go +++ b/src/simd/unary_helpers_test.go @@ -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) }) }) } diff --git a/src/simd/unary_test.go b/src/simd/unary_test.go index 6565df3096..4263b81cd7 100644 --- a/src/simd/unary_test.go +++ b/src/simd/unary_test.go @@ -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 index 0000000000..c6ea50d551 --- /dev/null +++ b/src/simd/unsafe_helpers.go @@ -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])) +} -- 2.52.0