]> Cypherpunks repositories - gostls13.git/commitdiff
simd/archsimd: add tests for IsNaN
authorCherry Mui <cherryyz@google.com>
Wed, 31 Dec 2025 08:00:16 +0000 (03:00 -0500)
committerCherry Mui <cherryyz@google.com>
Fri, 2 Jan 2026 20:14:17 +0000 (12:14 -0800)
Change-Id: I374ce84fd21c41a04e2d5964d8aa872545c6a8a7
Reviewed-on: https://go-review.googlesource.com/c/go/+/733661
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
src/simd/archsimd/_gen/tmplgen/main.go
src/simd/archsimd/internal/simd_test/compare_helpers_test.go
src/simd/archsimd/internal/simd_test/compare_test.go
src/simd/archsimd/internal/simd_test/helpers_test.go
src/simd/archsimd/internal/simd_test/simulation_helpers_test.go

index e0d607af120937e50169049752ccdc1878c0d647..8db185e1e0495ae4e35f796d9bf0ada862d92318 100644 (file)
@@ -104,6 +104,11 @@ var uintShapes = &shapes{
        uints: []int{8, 16, 32, 64},
 }
 
+var floatShapes = &shapes{
+       vecs:   []int{128, 256, 512},
+       floats: []int{32, 64},
+}
+
 var integerShapes = &shapes{
        vecs:  []int{128, 256, 512},
        ints:  []int{8, 16, 32, 64},
@@ -507,6 +512,22 @@ func test{{.VType}}Compare(t *testing.T, f func(_, _ archsimd.{{.VType}}) archsi
 }
 `)
 
+var compareUnaryTemplate = shapedTemplateOf(floatShapes, "compare_unary_helpers", `
+// test{{.VType}}UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func test{{.VType}}UnaryCompare(t *testing.T, f func(x archsimd.{{.VType}}) archsimd.Mask{{.WxC}}, want func(x []{{.Etype}}) []int64) {
+       n := {{.Count}}
+       t.Helper()
+       forSlice(t, {{.Etype}}s, n, func(x []{{.Etype}}) bool {
+               t.Helper()
+               a := archsimd.Load{{.VType}}Slice(x)
+               g := make([]int{{.EWidth}}, n)
+               f(a).ToInt{{.WxC}}().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() {t.Helper(); t.Logf("x=%v", x)})
+       })
+}
+`)
+
 // TODO this has not been tested yet.
 var compareMaskedTemplate = templateOf("comparemasked_helpers", `
 // test{{.VType}}CompareMasked tests the simd masked comparison method f against the expected behavior generated by want
@@ -941,7 +962,7 @@ func main() {
                one(*th, curryTestPrologue("ternary simd methods"), ternaryTemplate, ternaryFlakyTemplate)
        }
        if *ch != "" {
-               one(*ch, curryTestPrologue("simd methods that compare two operands"), compareTemplate)
+               one(*ch, curryTestPrologue("simd methods that compare two operands"), compareTemplate, compareUnaryTemplate)
        }
        if *cmh != "" {
                one(*cmh, curryTestPrologue("simd methods that compare two operands under a mask"), compareMaskedTemplate)
index c520aa7f17f209d740c86cb188bcb1ca3e5cf7eb..7a33f0ffa4365a563139cc0d2b0a27464bbfe750 100644 (file)
@@ -462,3 +462,87 @@ func testFloat64x8Compare(t *testing.T, f func(_, _ archsimd.Float64x8) archsimd
                return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x); t.Logf("y=%v", y) })
        })
 }
+
+// testFloat32x4UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func testFloat32x4UnaryCompare(t *testing.T, f func(x archsimd.Float32x4) archsimd.Mask32x4, want func(x []float32) []int64) {
+       n := 4
+       t.Helper()
+       forSlice(t, float32s, n, func(x []float32) bool {
+               t.Helper()
+               a := archsimd.LoadFloat32x4Slice(x)
+               g := make([]int32, n)
+               f(a).ToInt32x4().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat64x2UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func testFloat64x2UnaryCompare(t *testing.T, f func(x archsimd.Float64x2) archsimd.Mask64x2, want func(x []float64) []int64) {
+       n := 2
+       t.Helper()
+       forSlice(t, float64s, n, func(x []float64) bool {
+               t.Helper()
+               a := archsimd.LoadFloat64x2Slice(x)
+               g := make([]int64, n)
+               f(a).ToInt64x2().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat32x8UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func testFloat32x8UnaryCompare(t *testing.T, f func(x archsimd.Float32x8) archsimd.Mask32x8, want func(x []float32) []int64) {
+       n := 8
+       t.Helper()
+       forSlice(t, float32s, n, func(x []float32) bool {
+               t.Helper()
+               a := archsimd.LoadFloat32x8Slice(x)
+               g := make([]int32, n)
+               f(a).ToInt32x8().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat64x4UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func testFloat64x4UnaryCompare(t *testing.T, f func(x archsimd.Float64x4) archsimd.Mask64x4, want func(x []float64) []int64) {
+       n := 4
+       t.Helper()
+       forSlice(t, float64s, n, func(x []float64) bool {
+               t.Helper()
+               a := archsimd.LoadFloat64x4Slice(x)
+               g := make([]int64, n)
+               f(a).ToInt64x4().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat32x16UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func testFloat32x16UnaryCompare(t *testing.T, f func(x archsimd.Float32x16) archsimd.Mask32x16, want func(x []float32) []int64) {
+       n := 16
+       t.Helper()
+       forSlice(t, float32s, n, func(x []float32) bool {
+               t.Helper()
+               a := archsimd.LoadFloat32x16Slice(x)
+               g := make([]int32, n)
+               f(a).ToInt32x16().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
+
+// testFloat64x8UnaryCompare tests the simd unary comparison method f against the expected behavior generated by want
+func testFloat64x8UnaryCompare(t *testing.T, f func(x archsimd.Float64x8) archsimd.Mask64x8, want func(x []float64) []int64) {
+       n := 8
+       t.Helper()
+       forSlice(t, float64s, n, func(x []float64) bool {
+               t.Helper()
+               a := archsimd.LoadFloat64x8Slice(x)
+               g := make([]int64, n)
+               f(a).ToInt64x8().StoreSlice(g)
+               w := want(x)
+               return checkSlicesLogInput(t, s64(g), w, 0.0, func() { t.Helper(); t.Logf("x=%v", x) })
+       })
+}
index efafbfdc35fee59ba65da7a7698c78a8fb66206c..e678676be0103c62f551b89a5da65d891a5b37da 100644 (file)
@@ -298,3 +298,15 @@ func TestNotEqual(t *testing.T) {
                testUint64x8Compare(t, archsimd.Uint64x8.NotEqual, notEqualSlice[uint64])
        }
 }
+
+func TestIsNaN(t *testing.T) {
+       testFloat32x4UnaryCompare(t, archsimd.Float32x4.IsNaN, isNaNSlice[float32])
+       testFloat32x8UnaryCompare(t, archsimd.Float32x8.IsNaN, isNaNSlice[float32])
+       testFloat64x2UnaryCompare(t, archsimd.Float64x2.IsNaN, isNaNSlice[float64])
+       testFloat64x4UnaryCompare(t, archsimd.Float64x4.IsNaN, isNaNSlice[float64])
+
+       if archsimd.X86.AVX512() {
+               testFloat32x16UnaryCompare(t, archsimd.Float32x16.IsNaN, isNaNSlice[float32])
+               testFloat64x8UnaryCompare(t, archsimd.Float64x8.IsNaN, isNaNSlice[float64])
+       }
+}
index 37cc98194a7dfd35876574cc908ac9a2fab8855b..d6963586c09902c1e408634147f6cd1b1e0bf8eb 100644 (file)
@@ -182,12 +182,14 @@ var nzero = -zero
 var inf = 1 / zero
 var ninf = -1 / zero
 var nan = math.NaN()
+var snan32 = math.Float32frombits(0x7f800001)
+var snan64 = math.Float64frombits(0x7ff0000000000001)
 
 // N controls how large the test vectors are
 const N = 144
 
-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 float32s = nOf(N, []float32{float32(inf), float32(ninf), 1, float32(nan), snan32, -float32(nan), -snan32, 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, snan64, -nan, -snan64, zero, -zero, 1 / zero, -1 / zero, 0.0001, 0.0000001, 1, -1, 0, 2, -2, 3, -3, math.MaxFloat64, 1.0 / math.MaxFloat64, 10, -10, 100, 20, -20, 300, -300, -4000, -80, -16, -32, -64})
 
 var int32s = nOf(N, []int32{1, -1, 0, 2, 4, 8, 1024, 0xffffff, -0xffffff, 0x55555, 0x77777, 0xccccc, -0x55555, -0x77777, -0xccccc, -4, -8, -16, -32, -64})
 var uint32s = nOf(N, []uint32{1, 0, 2, 4, 8, 1024, 0xffffff, ^uint32(0xffffff), 0x55555, 0x77777, 0xccccc, ^uint32(0x55555), ^uint32(0x77777), ^uint32(0xccccc)})
index da107d806179493b96dcfc482c6e7993ae996417..ac60b6d3776f4a58d00c771d1471db3e7ba0fc62 100644 (file)
@@ -29,6 +29,10 @@ func notEqual[T number](x, y T) bool {
        return x != y
 }
 
+func isNaN[T float](x T) bool {
+       return x != x
+}
+
 func abs[T number](x T) T {
        // TODO this will need a non-standard FP-equality test.
        if x == 0 { // true if x is -0.
@@ -299,6 +303,15 @@ func notEqualSlice[T number](x, y []T) []int64 {
        return mapCompare[T](notEqual)(x, y)
 }
 
+func isNaNSlice[T float](x []T) []int64 {
+       return map1[T](func(x T) int64 {
+               if isNaN(x) {
+                       return -1
+               }
+               return 0
+       })(x)
+}
+
 func ceilSlice[T float](x []T) []T {
        return map1[T](ceil)(x)
 }