aboutsummaryrefslogtreecommitdiff
path: root/src/simd
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2025-12-26 16:38:56 -0500
committerCherry Mui <cherryyz@google.com>2025-12-27 09:02:27 -0800
commitca13fe02c48db993a34d441d87180cf665d5b288 (patch)
tree9b8a918a89a8c512ed1874a2cbd1dc36c07fce4f /src/simd
parent037c047f2cb5c962335898c85af2ecef8045027f (diff)
downloadgo-ca13fe02c48db993a34d441d87180cf665d5b288.tar.xz
simd/archsimd: add more tests for Convert operations
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>
Diffstat (limited to 'src/simd')
-rw-r--r--src/simd/archsimd/internal/simd_test/simulation_helpers_test.go78
-rw-r--r--src/simd/archsimd/internal/simd_test/unary_test.go63
2 files changed, 120 insertions, 21 deletions
diff --git a/src/simd/archsimd/internal/simd_test/simulation_helpers_test.go b/src/simd/archsimd/internal/simd_test/simulation_helpers_test.go
index 2f040ffb3e..a51912a47f 100644
--- a/src/simd/archsimd/internal/simd_test/simulation_helpers_test.go
+++ b/src/simd/archsimd/internal/simd_test/simulation_helpers_test.go
@@ -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 {
diff --git a/src/simd/archsimd/internal/simd_test/unary_test.go b/src/simd/archsimd/internal/simd_test/unary_test.go
index 9110a6eac6..561709841d 100644
--- a/src/simd/archsimd/internal/simd_test/unary_test.go
+++ b/src/simd/archsimd/internal/simd_test/unary_test.go
@@ -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))
+
+ 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))
-func TestToInt32(t *testing.T) {
- testFloat32x4ConvertToInt32(t, archsimd.Float32x4.ConvertToInt32, map1[float32](toInt32))
- testFloat32x8ConvertToInt32(t, archsimd.Float32x8.ConvertToInt32, map1[float32](toInt32))
+ 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) {