github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/common/bitutil/bitutil.go (about) 1 package bitutil 2 3 import ( 4 "runtime" 5 "unsafe" 6 ) 7 8 const wordSize = int(unsafe.Sizeof(uintptr(0))) 9 const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x" 10 11 func XORBytes(dst, a, b []byte) int { 12 if supportsUnaligned { 13 return fastXORBytes(dst, a, b) 14 } 15 return safeXORBytes(dst, a, b) 16 } 17 18 func fastXORBytes(dst, a, b []byte) int { 19 n := len(a) 20 if len(b) < n { 21 n = len(b) 22 } 23 w := n / wordSize 24 if w > 0 { 25 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 26 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 27 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 28 for i := 0; i < w; i++ { 29 dw[i] = aw[i] ^ bw[i] 30 } 31 } 32 for i := n - n%wordSize; i < n; i++ { 33 dst[i] = a[i] ^ b[i] 34 } 35 return n 36 } 37 38 func safeXORBytes(dst, a, b []byte) int { 39 n := len(a) 40 if len(b) < n { 41 n = len(b) 42 } 43 for i := 0; i < n; i++ { 44 dst[i] = a[i] ^ b[i] 45 } 46 return n 47 } 48 49 func ANDBytes(dst, a, b []byte) int { 50 if supportsUnaligned { 51 return fastANDBytes(dst, a, b) 52 } 53 return safeANDBytes(dst, a, b) 54 } 55 56 func fastANDBytes(dst, a, b []byte) int { 57 n := len(a) 58 if len(b) < n { 59 n = len(b) 60 } 61 w := n / wordSize 62 if w > 0 { 63 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 64 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 65 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 66 for i := 0; i < w; i++ { 67 dw[i] = aw[i] & bw[i] 68 } 69 } 70 for i := n - n%wordSize; i < n; i++ { 71 dst[i] = a[i] & b[i] 72 } 73 return n 74 } 75 76 func safeANDBytes(dst, a, b []byte) int { 77 n := len(a) 78 if len(b) < n { 79 n = len(b) 80 } 81 for i := 0; i < n; i++ { 82 dst[i] = a[i] & b[i] 83 } 84 return n 85 } 86 87 func ORBytes(dst, a, b []byte) int { 88 if supportsUnaligned { 89 return fastORBytes(dst, a, b) 90 } 91 return safeORBytes(dst, a, b) 92 } 93 94 func fastORBytes(dst, a, b []byte) int { 95 n := len(a) 96 if len(b) < n { 97 n = len(b) 98 } 99 w := n / wordSize 100 if w > 0 { 101 dw := *(*[]uintptr)(unsafe.Pointer(&dst)) 102 aw := *(*[]uintptr)(unsafe.Pointer(&a)) 103 bw := *(*[]uintptr)(unsafe.Pointer(&b)) 104 for i := 0; i < w; i++ { 105 dw[i] = aw[i] | bw[i] 106 } 107 } 108 for i := n - n%wordSize; i < n; i++ { 109 dst[i] = a[i] | b[i] 110 } 111 return n 112 } 113 114 func safeORBytes(dst, a, b []byte) int { 115 n := len(a) 116 if len(b) < n { 117 n = len(b) 118 } 119 for i := 0; i < n; i++ { 120 dst[i] = a[i] | b[i] 121 } 122 return n 123 } 124 125 func TestBytes(p []byte) bool { 126 if supportsUnaligned { 127 return fastTestBytes(p) 128 } 129 return safeTestBytes(p) 130 } 131 132 func fastTestBytes(p []byte) bool { 133 n := len(p) 134 w := n / wordSize 135 if w > 0 { 136 pw := *(*[]uintptr)(unsafe.Pointer(&p)) 137 for i := 0; i < w; i++ { 138 if pw[i] != 0 { 139 return true 140 } 141 } 142 } 143 for i := n - n%wordSize; i < n; i++ { 144 if p[i] != 0 { 145 return true 146 } 147 } 148 return false 149 } 150 151 func safeTestBytes(p []byte) bool { 152 for i := 0; i < len(p); i++ { 153 if p[i] != 0 { 154 return true 155 } 156 } 157 return false 158 }