]> Cypherpunks repositories - gostls13.git/commitdiff
simd/archsimd: add more tests for Convert operations
authorCherry Mui <cherryyz@google.com>
Fri, 26 Dec 2025 21:38:56 +0000 (16:38 -0500)
committerCherry Mui <cherryyz@google.com>
Sat, 27 Dec 2025 17:02:27 +0000 (09:02 -0800)
For now, only include operations that input and output vectors
have the same number of elements.

Change-Id: If4722f1b0168eaf0e333bdcd218e394fa4ab440f
Reviewed-on: https://go-review.googlesource.com/c/go/+/732662
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/simd/archsimd/internal/simd_test/simulation_helpers_test.go
src/simd/archsimd/internal/simd_test/unary_test.go

index 2f040ffb3e71d39806fa43b4f9987c8c07e7c29e..a51912a47f6e07891198ed7753bdbb22d338b469 100644 (file)
@@ -121,16 +121,6 @@ func toUint64[T number](x T) uint64 {
 }
 
 func toUint32[T number](x T) uint32 {
-       switch y := (any(x)).(type) {
-       case float32:
-               if y < 0 || y > float32(math.MaxUint32) || y != y {
-                       return math.MaxUint32
-               }
-       case float64:
-               if y < 0 || y > float64(math.MaxUint32) || y != y {
-                       return math.MaxUint32
-               }
-       }
        return uint32(x)
 }
 
@@ -158,6 +148,74 @@ func toFloat64[T number](x T) float64 {
        return float64(x)
 }
 
+// X86 specific behavior for conversion from float to int32.
+// If the value cannot be represented as int32, it returns -0x80000000.
+func floatToInt32_x86[T float](x T) int32 {
+       switch y := (any(x)).(type) {
+       case float32:
+               if y != y || y < math.MinInt32 ||
+                       y >= math.MaxInt32 { // float32(MaxInt32) == 0x80000000, actually overflows
+                       return -0x80000000
+               }
+       case float64:
+               if y != y || y < math.MinInt32 ||
+                       y > math.MaxInt32 { // float64(MaxInt32) is exact, no overflow
+                       return -0x80000000
+               }
+       }
+       return int32(x)
+}
+
+// X86 specific behavior for conversion from float to int64.
+// If the value cannot be represented as int64, it returns -0x80000000_00000000.
+func floatToInt64_x86[T float](x T) int64 {
+       switch y := (any(x)).(type) {
+       case float32:
+               if y != y || y < math.MinInt64 ||
+                       y >= math.MaxInt64 { // float32(MaxInt64) == 0x80000000_00000000, actually overflows
+                       return -0x80000000_00000000
+               }
+       case float64:
+               if y != y || y < math.MinInt64 ||
+                       y >= math.MaxInt64 { // float64(MaxInt64) == 0x80000000_00000000, also overflows
+                       return -0x80000000_00000000
+               }
+       }
+       return int64(x)
+}
+
+// X86 specific behavior for conversion from float to uint32.
+// If the value cannot be represented as uint32, it returns 1<<32 - 1.
+func floatToUint32_x86[T float](x T) uint32 {
+       switch y := (any(x)).(type) {
+       case float32:
+               if y < 0 || y > math.MaxUint32 || y != y {
+                       return 1<<32 - 1
+               }
+       case float64:
+               if y < 0 || y > math.MaxUint32 || y != y {
+                       return 1<<32 - 1
+               }
+       }
+       return uint32(x)
+}
+
+// X86 specific behavior for conversion from float to uint64.
+// If the value cannot be represented as uint64, it returns 1<<64 - 1.
+func floatToUint64_x86[T float](x T) uint64 {
+       switch y := (any(x)).(type) {
+       case float32:
+               if y < 0 || y > math.MaxUint64 || y != y {
+                       return 1<<64 - 1
+               }
+       case float64:
+               if y < 0 || y > math.MaxUint64 || y != y {
+                       return 1<<64 - 1
+               }
+       }
+       return uint64(x)
+}
+
 func ceilResidueForPrecision[T float](i int) func(T) T {
        f := 1.0
        for i > 0 {
index 9110a6eac67075b09c82d0e5f649874e680a16f5..561709841da01340bcaf6c988a656fc448b96ccf 100644 (file)
@@ -116,18 +116,59 @@ func TestCeilScaledResidue(t *testing.T) {
                map1[float64](func(x float64) float64 { return x - math.Ceil(x) }))
 }
 
-func TestToUint32(t *testing.T) {
-       if !archsimd.X86.AVX512() {
-               t.Skip("Needs AVX512")
-       }
-       testFloat32x4ConvertToUint32(t, archsimd.Float32x4.ConvertToUint32, map1[float32](toUint32))
-       testFloat32x8ConvertToUint32(t, archsimd.Float32x8.ConvertToUint32, map1[float32](toUint32))
-       testFloat32x16ConvertToUint32(t, archsimd.Float32x16.ConvertToUint32, map1[float32](toUint32))
-}
+func TestConvert(t *testing.T) {
+       testFloat32x4ConvertToFloat64(t, archsimd.Float32x4.ConvertToFloat64, map1[float32](toFloat64))
+       testFloat64x4ConvertToFloat32(t, archsimd.Float64x4.ConvertToFloat32, map1[float64](toFloat32))
 
-func TestToInt32(t *testing.T) {
-       testFloat32x4ConvertToInt32(t, archsimd.Float32x4.ConvertToInt32, map1[float32](toInt32))
-       testFloat32x8ConvertToInt32(t, archsimd.Float32x8.ConvertToInt32, map1[float32](toInt32))
+       testFloat32x4ConvertToInt32(t, archsimd.Float32x4.ConvertToInt32, map1[float32](floatToInt32_x86))
+       testFloat32x8ConvertToInt32(t, archsimd.Float32x8.ConvertToInt32, map1[float32](floatToInt32_x86))
+       testFloat64x4ConvertToInt32(t, archsimd.Float64x4.ConvertToInt32, map1[float64](floatToInt32_x86))
+
+       testInt32x4ConvertToFloat32(t, archsimd.Int32x4.ConvertToFloat32, map1[int32](toFloat32))
+       testInt32x4ConvertToFloat64(t, archsimd.Int32x4.ConvertToFloat64, map1[int32](toFloat64))
+       testInt32x8ConvertToFloat32(t, archsimd.Int32x8.ConvertToFloat32, map1[int32](toFloat32))
+
+       if archsimd.X86.AVX512() {
+               testFloat32x8ConvertToFloat64(t, archsimd.Float32x8.ConvertToFloat64, map1[float32](toFloat64))
+               testFloat64x8ConvertToFloat32(t, archsimd.Float64x8.ConvertToFloat32, map1[float64](toFloat32))
+
+               testFloat32x16ConvertToInt32(t, archsimd.Float32x16.ConvertToInt32, map1[float32](floatToInt32_x86))
+               testFloat64x8ConvertToInt32(t, archsimd.Float64x8.ConvertToInt32, map1[float64](floatToInt32_x86))
+               testFloat32x4ConvertToInt64(t, archsimd.Float32x4.ConvertToInt64, map1[float32](floatToInt64_x86))
+               testFloat32x8ConvertToInt64(t, archsimd.Float32x8.ConvertToInt64, map1[float32](floatToInt64_x86))
+               testFloat64x2ConvertToInt64(t, archsimd.Float64x2.ConvertToInt64, map1[float64](floatToInt64_x86))
+               testFloat64x4ConvertToInt64(t, archsimd.Float64x4.ConvertToInt64, map1[float64](floatToInt64_x86))
+               testFloat64x8ConvertToInt64(t, archsimd.Float64x8.ConvertToInt64, map1[float64](floatToInt64_x86))
+
+               testFloat32x4ConvertToUint32(t, archsimd.Float32x4.ConvertToUint32, map1[float32](floatToUint32_x86))
+               testFloat32x8ConvertToUint32(t, archsimd.Float32x8.ConvertToUint32, map1[float32](floatToUint32_x86))
+               testFloat32x16ConvertToUint32(t, archsimd.Float32x16.ConvertToUint32, map1[float32](floatToUint32_x86))
+               testFloat64x4ConvertToUint32(t, archsimd.Float64x4.ConvertToUint32, map1[float64](floatToUint32_x86))
+               testFloat64x8ConvertToUint32(t, archsimd.Float64x8.ConvertToUint32, map1[float64](floatToUint32_x86))
+               testFloat32x4ConvertToUint64(t, archsimd.Float32x4.ConvertToUint64, map1[float32](floatToUint64_x86))
+               testFloat32x8ConvertToUint64(t, archsimd.Float32x8.ConvertToUint64, map1[float32](floatToUint64_x86))
+               testFloat64x2ConvertToUint64(t, archsimd.Float64x2.ConvertToUint64, map1[float64](floatToUint64_x86))
+               testFloat64x4ConvertToUint64(t, archsimd.Float64x4.ConvertToUint64, map1[float64](floatToUint64_x86))
+               testFloat64x8ConvertToUint64(t, archsimd.Float64x8.ConvertToUint64, map1[float64](floatToUint64_x86))
+
+               testInt32x16ConvertToFloat32(t, archsimd.Int32x16.ConvertToFloat32, map1[int32](toFloat32))
+               testInt64x4ConvertToFloat32(t, archsimd.Int64x4.ConvertToFloat32, map1[int64](toFloat32))
+               testInt64x8ConvertToFloat32(t, archsimd.Int64x8.ConvertToFloat32, map1[int64](toFloat32))
+               testInt64x2ConvertToFloat64(t, archsimd.Int64x2.ConvertToFloat64, map1[int64](toFloat64))
+               testInt64x4ConvertToFloat64(t, archsimd.Int64x4.ConvertToFloat64, map1[int64](toFloat64))
+               testInt64x8ConvertToFloat64(t, archsimd.Int64x8.ConvertToFloat64, map1[int64](toFloat64))
+
+               testUint32x4ConvertToFloat32(t, archsimd.Uint32x4.ConvertToFloat32, map1[uint32](toFloat32))
+               testUint32x8ConvertToFloat32(t, archsimd.Uint32x8.ConvertToFloat32, map1[uint32](toFloat32))
+               testUint32x16ConvertToFloat32(t, archsimd.Uint32x16.ConvertToFloat32, map1[uint32](toFloat32))
+               testUint64x4ConvertToFloat32(t, archsimd.Uint64x4.ConvertToFloat32, map1[uint64](toFloat32))
+               testUint64x8ConvertToFloat32(t, archsimd.Uint64x8.ConvertToFloat32, map1[uint64](toFloat32))
+               testUint32x4ConvertToFloat64(t, archsimd.Uint32x4.ConvertToFloat64, map1[uint32](toFloat64))
+               testUint32x8ConvertToFloat64(t, archsimd.Uint32x8.ConvertToFloat64, map1[uint32](toFloat64))
+               testUint64x2ConvertToFloat64(t, archsimd.Uint64x2.ConvertToFloat64, map1[uint64](toFloat64))
+               testUint64x4ConvertToFloat64(t, archsimd.Uint64x4.ConvertToFloat64, map1[uint64](toFloat64))
+               testUint64x8ConvertToFloat64(t, archsimd.Uint64x8.ConvertToFloat64, map1[uint64](toFloat64))
+       }
 }
 
 func TestExtend(t *testing.T) {