1
0
mirror of https://github.com/golang/go synced 2024-11-11 18:21:40 -07:00

bytes,slices,strings: optimize Repeat a bit

Like slices.Repeat, use math/bits.Mul to detect overflow in order to
avoid a divide which is slow.

While here, also use builtin min/max to simplify code.

Change-Id: I4a6d8cd5df97fa75f4e324d4be1405ce53c03d31
GitHub-Last-Rev: 54ba5c7126
GitHub-Pull-Request: golang/go#68704
Reviewed-on: https://go-review.googlesource.com/c/go/+/602475
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
Jes Cok 2024-08-01 16:18:06 +00:00 committed by Gopher Robot
parent e50913cefc
commit 67c3f012cf
3 changed files with 13 additions and 17 deletions

View File

@ -8,6 +8,7 @@ package bytes
import (
"internal/bytealg"
"math/bits"
"unicode"
"unicode/utf8"
_ "unsafe" // for linkname
@ -594,10 +595,11 @@ func Repeat(b []byte, count int) []byte {
if count < 0 {
panic("bytes: negative Repeat count")
}
if len(b) > maxInt/count {
hi, lo := bits.Mul(uint(len(b)), uint(count))
if hi > 0 || lo > uint(maxInt) {
panic("bytes: Repeat output length overflow")
}
n := len(b) * count
n := int(lo) // lo = len(b) * count
if len(b) == 0 {
return []byte{}
@ -624,10 +626,7 @@ func Repeat(b []byte, count int) []byte {
nb := bytealg.MakeNoZero(n)[:n:n]
bp := copy(nb, b)
for bp < n {
chunk := bp
if chunk > chunkMax {
chunk = chunkMax
}
chunk := min(bp, chunkMax)
bp += copy(nb[bp:], nb[:chunk])
}
return nb

View File

@ -496,11 +496,12 @@ func Repeat[S ~[]E, E any](x S, count int) S {
}
const maxInt = ^uint(0) >> 1
if hi, lo := bits.Mul(uint(len(x)), uint(count)); hi > 0 || lo > maxInt {
hi, lo := bits.Mul(uint(len(x)), uint(count))
if hi > 0 || lo > maxInt {
panic("the result of (len(x) * count) overflows")
}
newslice := make(S, len(x)*count)
newslice := make(S, int(lo)) // lo = len(x) * count
n := copy(newslice, x)
for n < len(newslice) {
n += copy(newslice[n:], newslice[:n])

View File

@ -10,6 +10,7 @@ package strings
import (
"internal/bytealg"
"internal/stringslite"
"math/bits"
"unicode"
"unicode/utf8"
)
@ -568,10 +569,11 @@ func Repeat(s string, count int) string {
if count < 0 {
panic("strings: negative Repeat count")
}
if len(s) > maxInt/count {
hi, lo := bits.Mul(uint(len(s)), uint(count))
if hi > 0 || lo > uint(maxInt) {
panic("strings: Repeat output length overflow")
}
n := len(s) * count
n := int(lo) // lo = len(s) * count
if len(s) == 0 {
return ""
@ -617,13 +619,7 @@ func Repeat(s string, count int) string {
b.Grow(n)
b.WriteString(s)
for b.Len() < n {
chunk := n - b.Len()
if chunk > b.Len() {
chunk = b.Len()
}
if chunk > chunkMax {
chunk = chunkMax
}
chunk := min(n-b.Len(), b.Len(), chunkMax)
b.WriteString(b.String()[:chunk])
}
return b.String()