[dev.simd] simd: added String() method to SIMD vectors.

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>
This commit is contained in:
David Chase 2025-10-14 12:25:07 -04:00
parent d03634f807
commit c75965b666
7 changed files with 335 additions and 4 deletions

View 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;

23
src/internal/ftoa/ftoa.go Normal file
View file

@ -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
}
}

View 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 != "" {

View 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)
}

View 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[:])
}

49
src/simd/string.go Normal file
View file

@ -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
}

View file

@ -10,7 +10,10 @@
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