From 68e52bc03cd3072985ead4895a3ae97f43c02331 Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Fri, 27 Oct 2023 16:20:44 +0000 Subject: [PATCH] bytes,internal/bytealg: eliminate IndexRabinKarpBytes using generics This is a follow-up to CL 538175. Change-Id: Iec2523b36a16d7e157c17858c89fcd43c2470d58 GitHub-Last-Rev: 812d36e57c71ea3bf44d2d64bde0703ef02a1b91 GitHub-Pull-Request: golang/go#63770 Reviewed-on: https://go-review.googlesource.com/c/go/+/538195 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Auto-Submit: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Bryan Mills --- src/bytes/bytes.go | 2 +- src/internal/bytealg/bytealg.go | 35 +++------------------------------ 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/src/bytes/bytes.go b/src/bytes/bytes.go index 95afb30b40c..c84accd8f56 100644 --- a/src/bytes/bytes.go +++ b/src/bytes/bytes.go @@ -1331,7 +1331,7 @@ func Index(s, sep []byte) int { // we should cutover at even larger average skips, // because Equal becomes that much more expensive. // This code does not take that effect into account. - j := bytealg.IndexRabinKarpBytes(s[i:], sep) + j := bytealg.IndexRabinKarp(s[i:], sep) if j < 0 { return -1 } diff --git a/src/internal/bytealg/bytealg.go b/src/internal/bytealg/bytealg.go index ae4b8b48d2e..92be8ea79b7 100644 --- a/src/internal/bytealg/bytealg.go +++ b/src/internal/bytealg/bytealg.go @@ -24,10 +24,6 @@ const ( // If MaxLen is not 0, make sure MaxLen >= 4. var MaxLen int -// FIXME: the logic of IndexRabinKarpBytes and IndexRabinKarp are exactly the same, -// except that the types are different. -// Can we eliminate one of them without causing allocation? - // PrimeRK is the prime base used in Rabin-Karp algorithm. const PrimeRK = 16777619 @@ -65,34 +61,9 @@ func HashStrRev[T string | []byte](sep T) (uint32, uint32) { return hash, pow } -// IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the -// first occurrence of substr in s, or -1 if not present. -func IndexRabinKarpBytes(s, sep []byte) int { - // Rabin-Karp search - hashsep, pow := HashStr(sep) - n := len(sep) - var h uint32 - for i := 0; i < n; i++ { - h = h*PrimeRK + uint32(s[i]) - } - if h == hashsep && Equal(s[:n], sep) { - return 0 - } - for i := n; i < len(s); { - h *= PrimeRK - h += uint32(s[i]) - h -= pow * uint32(s[i-n]) - i++ - if h == hashsep && Equal(s[i-n:i], sep) { - return i - n - } - } - return -1 -} - // IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the // first occurrence of substr in s, or -1 if not present. -func IndexRabinKarp(s, substr string) int { +func IndexRabinKarp[T string | []byte](s, substr T) int { // Rabin-Karp search hashss, pow := HashStr(substr) n := len(substr) @@ -100,7 +71,7 @@ func IndexRabinKarp(s, substr string) int { for i := 0; i < n; i++ { h = h*PrimeRK + uint32(s[i]) } - if h == hashss && s[:n] == substr { + if h == hashss && string(s[:n]) == string(substr) { return 0 } for i := n; i < len(s); { @@ -108,7 +79,7 @@ func IndexRabinKarp(s, substr string) int { h += uint32(s[i]) h -= pow * uint32(s[i-n]) i++ - if h == hashss && s[i-n:i] == substr { + if h == hashss && string(s[i-n:i]) == string(substr) { return i - n } }