github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/bytes/bytes_s390x.go (about) 1 // Copyright 2016 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 bytes 6 7 //go:noescape 8 9 // indexShortStr returns the index of the first instance of sep in s, 10 // or -1 if sep is not present in s. 11 // indexShortStr requires 2 <= len(sep) <= shortStringLen 12 func indexShortStr(s, c []byte) int // ../runtime/asm_s390x.s 13 14 // supportsVX reports whether the vector facility is available. 15 // indexShortStr must not be called if the vector facility is not 16 // available. 17 func supportsVX() bool // ../runtime/asm_s390x.s 18 19 var shortStringLen = -1 20 21 func init() { 22 if supportsVX() { 23 shortStringLen = 64 24 } 25 } 26 27 // Index returns the index of the first instance of sep in s, or -1 if sep is not present in s. 28 func Index(s, sep []byte) int { 29 n := len(sep) 30 switch { 31 case n == 0: 32 return 0 33 case n == 1: 34 return IndexByte(s, sep[0]) 35 case n == len(s): 36 if Equal(sep, s) { 37 return 0 38 } 39 return -1 40 case n > len(s): 41 return -1 42 case n <= shortStringLen: 43 // Use brute force when s and sep both are small 44 if len(s) <= 64 { 45 return indexShortStr(s, sep) 46 } 47 c := sep[0] 48 i := 0 49 t := s[:len(s)-n+1] 50 fails := 0 51 for i < len(t) { 52 if t[i] != c { 53 // IndexByte skips 16/32 bytes per iteration, 54 // so it's faster than indexShortStr. 55 o := IndexByte(t[i:], c) 56 if o < 0 { 57 return -1 58 } 59 i += o 60 } 61 if Equal(s[i:i+n], sep) { 62 return i 63 } 64 fails++ 65 i++ 66 // Switch to indexShortStr when IndexByte produces too many false positives. 67 // Too many means more that 1 error per 8 characters. 68 // Allow some errors in the beginning. 69 if fails > (i+16)/8 { 70 r := indexShortStr(s[i:], sep) 71 if r >= 0 { 72 return r + i 73 } 74 return -1 75 } 76 } 77 return -1 78 } 79 // Rabin-Karp search 80 hashsep, pow := hashStr(sep) 81 var h uint32 82 for i := 0; i < n; i++ { 83 h = h*primeRK + uint32(s[i]) 84 } 85 if h == hashsep && Equal(s[:n], sep) { 86 return 0 87 } 88 for i := n; i < len(s); { 89 h *= primeRK 90 h += uint32(s[i]) 91 h -= pow * uint32(s[i-n]) 92 i++ 93 if h == hashsep && Equal(s[i-n:i], sep) { 94 return i - n 95 } 96 } 97 return -1 98 } 99 100 // Count counts the number of non-overlapping instances of sep in s. 101 // If sep is an empty slice, Count returns 1 + the number of Unicode code points in s. 102 func Count(s, sep []byte) int { 103 return countGeneric(s, sep) 104 } 105 106 // primeRK is the prime base used in Rabin-Karp algorithm. 107 const primeRK = 16777619 108 109 // hashStr returns the hash and the appropriate multiplicative 110 // factor for use in Rabin-Karp algorithm. 111 func hashStr(sep []byte) (uint32, uint32) { 112 hash := uint32(0) 113 for i := 0; i < len(sep); i++ { 114 hash = hash*primeRK + uint32(sep[i]) 115 } 116 var pow, sq uint32 = 1, primeRK 117 for i := len(sep); i > 0; i >>= 1 { 118 if i&1 != 0 { 119 pow *= sq 120 } 121 sq *= sq 122 } 123 return hash, pow 124 }