github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/internal/bytealg/bytealg.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bytealg 6 7 import ( 8 "unsafe" 9 10 "github.com/hxx258456/ccgo/internal/cpu" 11 ) 12 13 // Offsets into internal/cpu records for use in assembly. 14 const ( 15 offsetX86HasSSE2 = unsafe.Offsetof(cpu.X86.HasSSE2) 16 offsetX86HasSSE42 = unsafe.Offsetof(cpu.X86.HasSSE42) 17 offsetX86HasAVX2 = unsafe.Offsetof(cpu.X86.HasAVX2) 18 offsetX86HasPOPCNT = unsafe.Offsetof(cpu.X86.HasPOPCNT) 19 20 offsetS390xHasVX = unsafe.Offsetof(cpu.S390X.HasVX) 21 22 offsetPPC64HasPOWER9 = unsafe.Offsetof(cpu.PPC64.IsPOWER9) 23 ) 24 25 // MaxLen is the maximum length of the string to be searched for (argument b) in Index. 26 // If MaxLen is not 0, make sure MaxLen >= 4. 27 var MaxLen int 28 29 // FIXME: the logic of HashStrBytes, HashStrRevBytes, IndexRabinKarpBytes and HashStr, HashStrRev, 30 // IndexRabinKarp are exactly the same, except that the types are different. Can we eliminate 31 // three of them without causing allocation? 32 33 // PrimeRK is the prime base used in Rabin-Karp algorithm. 34 const PrimeRK = 16777619 35 36 // HashStrBytes returns the hash and the appropriate multiplicative 37 // factor for use in Rabin-Karp algorithm. 38 func HashStrBytes(sep []byte) (uint32, uint32) { 39 hash := uint32(0) 40 for i := 0; i < len(sep); i++ { 41 hash = hash*PrimeRK + uint32(sep[i]) 42 } 43 var pow, sq uint32 = 1, PrimeRK 44 for i := len(sep); i > 0; i >>= 1 { 45 if i&1 != 0 { 46 pow *= sq 47 } 48 sq *= sq 49 } 50 return hash, pow 51 } 52 53 // HashStr returns the hash and the appropriate multiplicative 54 // factor for use in Rabin-Karp algorithm. 55 func HashStr(sep string) (uint32, uint32) { 56 hash := uint32(0) 57 for i := 0; i < len(sep); i++ { 58 hash = hash*PrimeRK + uint32(sep[i]) 59 } 60 var pow, sq uint32 = 1, PrimeRK 61 for i := len(sep); i > 0; i >>= 1 { 62 if i&1 != 0 { 63 pow *= sq 64 } 65 sq *= sq 66 } 67 return hash, pow 68 } 69 70 // HashStrRevBytes returns the hash of the reverse of sep and the 71 // appropriate multiplicative factor for use in Rabin-Karp algorithm. 72 func HashStrRevBytes(sep []byte) (uint32, uint32) { 73 hash := uint32(0) 74 for i := len(sep) - 1; i >= 0; i-- { 75 hash = hash*PrimeRK + uint32(sep[i]) 76 } 77 var pow, sq uint32 = 1, PrimeRK 78 for i := len(sep); i > 0; i >>= 1 { 79 if i&1 != 0 { 80 pow *= sq 81 } 82 sq *= sq 83 } 84 return hash, pow 85 } 86 87 // HashStrRev returns the hash of the reverse of sep and the 88 // appropriate multiplicative factor for use in Rabin-Karp algorithm. 89 func HashStrRev(sep string) (uint32, uint32) { 90 hash := uint32(0) 91 for i := len(sep) - 1; i >= 0; i-- { 92 hash = hash*PrimeRK + uint32(sep[i]) 93 } 94 var pow, sq uint32 = 1, PrimeRK 95 for i := len(sep); i > 0; i >>= 1 { 96 if i&1 != 0 { 97 pow *= sq 98 } 99 sq *= sq 100 } 101 return hash, pow 102 } 103 104 // IndexRabinKarpBytes uses the Rabin-Karp search algorithm to return the index of the 105 // first occurrence of substr in s, or -1 if not present. 106 func IndexRabinKarpBytes(s, sep []byte) int { 107 // Rabin-Karp search 108 hashsep, pow := HashStrBytes(sep) 109 n := len(sep) 110 var h uint32 111 for i := 0; i < n; i++ { 112 h = h*PrimeRK + uint32(s[i]) 113 } 114 if h == hashsep && Equal(s[:n], sep) { 115 return 0 116 } 117 for i := n; i < len(s); { 118 h *= PrimeRK 119 h += uint32(s[i]) 120 h -= pow * uint32(s[i-n]) 121 i++ 122 if h == hashsep && Equal(s[i-n:i], sep) { 123 return i - n 124 } 125 } 126 return -1 127 } 128 129 // IndexRabinKarp uses the Rabin-Karp search algorithm to return the index of the 130 // first occurrence of substr in s, or -1 if not present. 131 func IndexRabinKarp(s, substr string) int { 132 // Rabin-Karp search 133 hashss, pow := HashStr(substr) 134 n := len(substr) 135 var h uint32 136 for i := 0; i < n; i++ { 137 h = h*PrimeRK + uint32(s[i]) 138 } 139 if h == hashss && s[:n] == substr { 140 return 0 141 } 142 for i := n; i < len(s); { 143 h *= PrimeRK 144 h += uint32(s[i]) 145 h -= pow * uint32(s[i-n]) 146 i++ 147 if h == hashss && s[i-n:i] == substr { 148 return i - n 149 } 150 } 151 return -1 152 }