]> Cypherpunks repositories - gostls13.git/commitdiff
bytes,slices,strings: optimize Repeat a bit
authorJes Cok <xigua67damn@gmail.com>
Thu, 1 Aug 2024 16:18:06 +0000 (16:18 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 1 Aug 2024 21:32:50 +0000 (21:32 +0000)
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: 54ba5c7126b1d4a301e95d664b5f6deee6d579d9
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>
src/bytes/bytes.go
src/slices/slices.go
src/strings/strings.go

index 45d8d074753562b741f9f91fc1d44201e4459654..5c03e54d78761f9e4fd137a0a5dc4b547efcc4c5 100644 (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
index b3cd4e2c054001149e49b7c4969ab558e55cfc44..200e653dde5067ac488f39148efa6820392acd58 100644 (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])
index 0bd3c1c23378012499d1aa292ba287c667c6b86c..0729c4ad425d34427eca9422a4777415fda22664 100644 (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()