]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.simd] simd: added String() method to SIMD vectors.
authorDavid Chase <drchase@google.com>
Tue, 14 Oct 2025 16:25:07 +0000 (12:25 -0400)
committerDavid Chase <drchase@google.com>
Fri, 24 Oct 2025 16:19:39 +0000 (09:19 -0700)
this required a little plumbing to get access
to the "good" floating point formatting.

Change-Id: Iebec157c28a39df59351bade53b09a3729fc49c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/711781
Reviewed-by: Junyang Shao <shaojunyang@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

src/go/build/deps_test.go
src/internal/ftoa/ftoa.go [new file with mode: 0644]
src/simd/genfiles.go
src/simd/internal/simd_test/simd_test.go
src/simd/other_gen_amd64.go
src/simd/string.go [new file with mode: 0644]
src/strconv/ftoa.go

index ec3c4bbdaa0d342d484bc0ca6e1c13ba06972836..93abfd394afea28f1235be465729fc5ebeebad2d 100644 (file)
@@ -49,11 +49,13 @@ var depsRules = `
          internal/coverage/uleb128,
          internal/coverage/calloc,
          internal/cpu,
+         internal/ftoa,
          internal/goarch,
          internal/godebugs,
          internal/goexperiment,
          internal/goos,
          internal/goversion,
+         internal/itoa,
          internal/nettrace,
          internal/platform,
          internal/profilerecord,
@@ -70,7 +72,7 @@ var depsRules = `
        internal/goarch < internal/abi;
        internal/byteorder, internal/cpu, internal/goarch < internal/chacha8rand;
 
-       internal/cpu < simd;
+       internal/cpu, internal/ftoa, internal/itoa < simd;
 
        # RUNTIME is the core runtime group of packages, all of them very light-weight.
        internal/abi,
@@ -81,13 +83,13 @@ var depsRules = `
        internal/godebugs,
        internal/goexperiment,
        internal/goos,
+       internal/itoa,
        internal/profilerecord,
        internal/trace/tracev2,
        math/bits,
        structs
        < internal/bytealg
        < internal/stringslite
-       < internal/itoa
        < internal/unsafeheader
        < internal/race
        < internal/msan
@@ -175,7 +177,7 @@ var depsRules = `
        MATH
        < runtime/metrics;
 
-       MATH, unicode/utf8
+       MATH, unicode/utf8, internal/ftoa
        < strconv;
 
        unicode !< strconv;
diff --git a/src/internal/ftoa/ftoa.go b/src/internal/ftoa/ftoa.go
new file mode 100644 (file)
index 0000000..678668c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// A hook to get correct floating point conversion from strconv
+// in packages that cannot import strconv.
+
+package ftoa
+
+var formatFloatPtr func(f float64, fmt byte, prec, bitSize int) string
+
+func FormatFloat(f float64, fmt byte, prec, bitSize int) string {
+       if formatFloatPtr != nil {
+               return formatFloatPtr(f, fmt, prec, bitSize)
+       }
+       return "internal/ftoa.formatFloatPtr called before strconv.init()"
+}
+
+func SetFormatFloat(ff func(f float64, fmt byte, prec, bitSize int) string) {
+       if formatFloatPtr == nil {
+               formatFloatPtr = ff
+       }
+}
index 7e904edb107e3be30b4a1cfbee77d6d6e8014346..80234ac9f8a404b34911492f968e4bdd80a26a33 100644 (file)
@@ -263,6 +263,7 @@ func unsafePrologue(s string, out io.Writer) {
 package simd
 
 import "unsafe"
+
 `, s)
 }
 
@@ -795,6 +796,15 @@ func (from {{.Base}}{{.WxC}}) ToMask() (to Mask{{.WxC}}) {
 }
 `)
 
+var stringTemplate = shapedTemplateOf(allShapes, "String methods", `
+// String returns a string representation of SIMD vector x
+func (x {{.VType}}) String() string {
+       var s [{{.Count}}]{{.Etype}}
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+`)
+
 const TD = "internal/simd_test/"
 
 func main() {
@@ -836,6 +846,7 @@ func main() {
                        maskCvtTemplate,
                        bitWiseIntTemplate,
                        bitWiseUintTemplate,
+                       stringTemplate,
                )
        }
        if *ush != "" {
index 422378eebe44d8def1c9093ca5c52f257ef6195d..295f7bf9ce6d292fcc863f919db71ca75601ba74 100644 (file)
@@ -1001,3 +1001,32 @@ func TestSelect2FromPairConstGroupedInt512(t *testing.T) {
        foo(lh, 0, 3)
        foo(hl, 2, 1)
 }
+
+func TestString(t *testing.T) {
+       x := simd.LoadUint32x4Slice([]uint32{0, 1, 2, 3})
+       y := simd.LoadInt64x4Slice([]int64{-4, -5, -6, -7})
+       z := simd.LoadFloat32x4Slice([]float32{0.5, 1.5, -2.5, 3.5e9})
+       w := simd.LoadFloat64x4Slice([]float64{0.5, 1.5, -2.5, 3.5e9})
+
+       sx := "{0,1,2,3}"
+       sy := "{-4,-5,-6,-7}"
+       sz := "{0.5,1.5,-2.5,3.5e+09}"
+       sw := sz
+
+       if x.String() != sx {
+               t.Errorf("x=%s wanted %s", x, sx)
+       }
+       if y.String() != sy {
+               t.Errorf("y=%s wanted %s", y, sy)
+       }
+       if z.String() != sz {
+               t.Errorf("z=%s wanted %s", z, sz)
+       }
+       if w.String() != sw {
+               t.Errorf("w=%s wanted %s", w, sw)
+       }
+       t.Logf("w=%s", w)
+       t.Logf("x=%s", x)
+       t.Logf("y=%s", y)
+       t.Logf("z=%s", z)
+}
index 76fbe48b203625ede6eda448f92b08bd2ad581e3..da11b227df302e58e34cb7b446af4a391ac9eb26 100644 (file)
@@ -591,3 +591,213 @@ func (x Uint32x16) Not() Uint32x16 {
 func (x Uint64x8) Not() Uint64x8 {
        return x.Xor(x.Equal(x).AsInt64x8().AsUint64x8())
 }
+
+// String returns a string representation of SIMD vector x
+func (x Int8x16) String() string {
+       var s [16]int8
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int16x8) String() string {
+       var s [8]int16
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int32x4) String() string {
+       var s [4]int32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int64x2) String() string {
+       var s [2]int64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint8x16) String() string {
+       var s [16]uint8
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint16x8) String() string {
+       var s [8]uint16
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint32x4) String() string {
+       var s [4]uint32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint64x2) String() string {
+       var s [2]uint64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Float32x4) String() string {
+       var s [4]float32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Float64x2) String() string {
+       var s [2]float64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int8x32) String() string {
+       var s [32]int8
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int16x16) String() string {
+       var s [16]int16
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int32x8) String() string {
+       var s [8]int32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int64x4) String() string {
+       var s [4]int64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint8x32) String() string {
+       var s [32]uint8
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint16x16) String() string {
+       var s [16]uint16
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint32x8) String() string {
+       var s [8]uint32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint64x4) String() string {
+       var s [4]uint64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Float32x8) String() string {
+       var s [8]float32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Float64x4) String() string {
+       var s [4]float64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int8x64) String() string {
+       var s [64]int8
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int16x32) String() string {
+       var s [32]int16
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int32x16) String() string {
+       var s [16]int32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Int64x8) String() string {
+       var s [8]int64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint8x64) String() string {
+       var s [64]uint8
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint16x32) String() string {
+       var s [32]uint16
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint32x16) String() string {
+       var s [16]uint32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Uint64x8) String() string {
+       var s [8]uint64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Float32x16) String() string {
+       var s [16]float32
+       x.Store(&s)
+       return sliceToString(s[:])
+}
+
+// String returns a string representation of SIMD vector x
+func (x Float64x8) String() string {
+       var s [8]float64
+       x.Store(&s)
+       return sliceToString(s[:])
+}
diff --git a/src/simd/string.go b/src/simd/string.go
new file mode 100644 (file)
index 0000000..35584da
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build goexperiment.simd && amd64
+
+package simd
+
+import (
+       "internal/ftoa"
+       "internal/itoa"
+)
+
+type number interface {
+       ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
+}
+
+func sliceToString[T number](x []T) string {
+       s := ""
+       pfx := "{"
+       for _, y := range x {
+               s += pfx
+               pfx = ","
+               switch e := any(y).(type) {
+               case int8:
+                       s += itoa.Itoa(int(e))
+               case int16:
+                       s += itoa.Itoa(int(e))
+               case int32:
+                       s += itoa.Itoa(int(e))
+               case int64:
+                       s += itoa.Itoa(int(e))
+               case uint8:
+                       s += itoa.Uitoa(uint(e))
+               case uint16:
+                       s += itoa.Uitoa(uint(e))
+               case uint32:
+                       s += itoa.Uitoa(uint(e))
+               case uint64:
+                       s += itoa.Uitoa(uint(e))
+               case float32:
+                       s += ftoa.FormatFloat(float64(e), 'g', -1, 32)
+               case float64:
+                       s += ftoa.FormatFloat(e, 'g', -1, 64)
+               }
+       }
+       s += "}"
+       return s
+}
index bfe26366e12c136fbc1954ac0e62cc0b32b6f064..629df3824025998fe6438d79ef535ecf0579edbb 100644 (file)
 
 package strconv
 
-import "math"
+import (
+       "internal/ftoa"
+       "math"
+)
 
 // TODO: move elsewhere?
 type floatInfo struct {
@@ -22,6 +25,10 @@ type floatInfo struct {
 var float32info = floatInfo{23, 8, -127}
 var float64info = floatInfo{52, 11, -1023}
 
+func init() {
+       ftoa.SetFormatFloat(FormatFloat)
+}
+
 // FormatFloat converts the floating-point number f to a string,
 // according to the format fmt and precision prec. It rounds the
 // result assuming that the original was obtained from a floating-point