xxHash32.go 4.6 KB

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