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:
parent
e50913cefc
commit
67c3f012cf
@ -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
|
||||
|
@ -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])
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user