xxh32zero.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Package xxh32 implements the very fast XXH hashing algorithm (32 bits version).
  2. // (ported from the reference implementation https://github.com/Cyan4973/xxHash/)
  3. package xxh32
  4. import (
  5. "encoding/binary"
  6. )
  7. const (
  8. prime1 uint32 = 2654435761
  9. prime2 uint32 = 2246822519
  10. prime3 uint32 = 3266489917
  11. prime4 uint32 = 668265263
  12. prime5 uint32 = 374761393
  13. primeMask = 0xFFFFFFFF
  14. prime1plus2 = uint32((uint64(prime1) + uint64(prime2)) & primeMask) // 606290984
  15. prime1minus = uint32((-int64(prime1)) & primeMask) // 1640531535
  16. )
  17. // XXHZero represents an xxhash32 object with seed 0.
  18. type XXHZero struct {
  19. v [4]uint32
  20. totalLen uint64
  21. buf [16]byte
  22. bufused int
  23. }
  24. // Sum appends the current hash to b and returns the resulting slice.
  25. // It does not change the underlying hash state.
  26. func (xxh XXHZero) Sum(b []byte) []byte {
  27. h32 := xxh.Sum32()
  28. return append(b, byte(h32), byte(h32>>8), byte(h32>>16), byte(h32>>24))
  29. }
  30. // Reset resets the Hash to its initial state.
  31. func (xxh *XXHZero) Reset() {
  32. xxh.v[0] = prime1plus2
  33. xxh.v[1] = prime2
  34. xxh.v[2] = 0
  35. xxh.v[3] = prime1minus
  36. xxh.totalLen = 0
  37. xxh.bufused = 0
  38. }
  39. // Size returns the number of bytes returned by Sum().
  40. func (xxh *XXHZero) Size() int {
  41. return 4
  42. }
  43. // BlockSizeIndex gives the minimum number of bytes accepted by Write().
  44. func (xxh *XXHZero) BlockSize() int {
  45. return 1
  46. }
  47. // Write adds input bytes to the Hash.
  48. // It never returns an error.
  49. func (xxh *XXHZero) Write(input []byte) (int, error) {
  50. if xxh.totalLen == 0 {
  51. xxh.Reset()
  52. }
  53. n := len(input)
  54. m := xxh.bufused
  55. xxh.totalLen += uint64(n)
  56. r := len(xxh.buf) - m
  57. if n < r {
  58. copy(xxh.buf[m:], input)
  59. xxh.bufused += len(input)
  60. return n, nil
  61. }
  62. var buf *[16]byte
  63. if m != 0 {
  64. // some data left from previous update
  65. buf = &xxh.buf
  66. c := copy(buf[m:], input)
  67. n -= c
  68. input = input[c:]
  69. }
  70. update(&xxh.v, buf, input)
  71. xxh.bufused = copy(xxh.buf[:], input[n-n%16:])
  72. return n, nil
  73. }
  74. // Portable version of update. This updates v by processing all of buf
  75. // (if not nil) and all full 16-byte blocks of input.
  76. func updateGo(v *[4]uint32, buf *[16]byte, input []byte) {
  77. // Causes compiler to work directly from registers instead of stack:
  78. v1, v2, v3, v4 := v[0], v[1], v[2], v[3]
  79. if buf != nil {
  80. v1 = rol13(v1+binary.LittleEndian.Uint32(buf[:])*prime2) * prime1
  81. v2 = rol13(v2+binary.LittleEndian.Uint32(buf[4:])*prime2) * prime1
  82. v3 = rol13(v3+binary.LittleEndian.Uint32(buf[8:])*prime2) * prime1
  83. v4 = rol13(v4+binary.LittleEndian.Uint32(buf[12:])*prime2) * prime1
  84. }
  85. for ; len(input) >= 16; input = input[16:] {
  86. sub := input[:16] //BCE hint for compiler
  87. v1 = rol13(v1+binary.LittleEndian.Uint32(sub[:])*prime2) * prime1
  88. v2 = rol13(v2+binary.LittleEndian.Uint32(sub[4:])*prime2) * prime1
  89. v3 = rol13(v3+binary.LittleEndian.Uint32(sub[8:])*prime2) * prime1
  90. v4 = rol13(v4+binary.LittleEndian.Uint32(sub[12:])*prime2) * prime1
  91. }
  92. v[0], v[1], v[2], v[3] = v1, v2, v3, v4
  93. }
  94. // Sum32 returns the 32 bits Hash value.
  95. func (xxh *XXHZero) Sum32() uint32 {
  96. h32 := uint32(xxh.totalLen)
  97. if h32 >= 16 {
  98. h32 += rol1(xxh.v[0]) + rol7(xxh.v[1]) + rol12(xxh.v[2]) + rol18(xxh.v[3])
  99. } else {
  100. h32 += prime5
  101. }
  102. p := 0
  103. n := xxh.bufused
  104. buf := xxh.buf
  105. for n := n - 4; p <= n; p += 4 {
  106. h32 += binary.LittleEndian.Uint32(buf[p:p+4]) * prime3
  107. h32 = rol17(h32) * prime4
  108. }
  109. for ; p < n; p++ {
  110. h32 += uint32(buf[p]) * prime5
  111. h32 = rol11(h32) * prime1
  112. }
  113. h32 ^= h32 >> 15
  114. h32 *= prime2
  115. h32 ^= h32 >> 13
  116. h32 *= prime3
  117. h32 ^= h32 >> 16
  118. return h32
  119. }
  120. // Portable version of ChecksumZero.
  121. func checksumZeroGo(input []byte) uint32 {
  122. n := len(input)
  123. h32 := uint32(n)
  124. if n < 16 {
  125. h32 += prime5
  126. } else {
  127. v1 := prime1plus2
  128. v2 := prime2
  129. v3 := uint32(0)
  130. v4 := prime1minus
  131. p := 0
  132. for n := n - 16; p <= n; p += 16 {
  133. sub := input[p:][:16] //BCE hint for compiler
  134. v1 = rol13(v1+binary.LittleEndian.Uint32(sub[:])*prime2) * prime1
  135. v2 = rol13(v2+binary.LittleEndian.Uint32(sub[4:])*prime2) * prime1
  136. v3 = rol13(v3+binary.LittleEndian.Uint32(sub[8:])*prime2) * prime1
  137. v4 = rol13(v4+binary.LittleEndian.Uint32(sub[12:])*prime2) * prime1
  138. }
  139. input = input[p:]
  140. n -= p
  141. h32 += rol1(v1) + rol7(v2) + rol12(v3) + rol18(v4)
  142. }
  143. p := 0
  144. for n := n - 4; p <= n; p += 4 {
  145. h32 += binary.LittleEndian.Uint32(input[p:p+4]) * prime3
  146. h32 = rol17(h32) * prime4
  147. }
  148. for p < n {
  149. h32 += uint32(input[p]) * prime5
  150. h32 = rol11(h32) * prime1
  151. p++
  152. }
  153. h32 ^= h32 >> 15
  154. h32 *= prime2
  155. h32 ^= h32 >> 13
  156. h32 *= prime3
  157. h32 ^= h32 >> 16
  158. return h32
  159. }
  160. func rol1(u uint32) uint32 {
  161. return u<<1 | u>>31
  162. }
  163. func rol7(u uint32) uint32 {
  164. return u<<7 | u>>25
  165. }
  166. func rol11(u uint32) uint32 {
  167. return u<<11 | u>>21
  168. }
  169. func rol12(u uint32) uint32 {
  170. return u<<12 | u>>20
  171. }
  172. func rol13(u uint32) uint32 {
  173. return u<<13 | u>>19
  174. }
  175. func rol17(u uint32) uint32 {
  176. return u<<17 | u>>15
  177. }
  178. func rol18(u uint32) uint32 {
  179. return u<<18 | u>>14
  180. }