hash.odin 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. package hash
  2. import "core:mem"
  3. import "core:intrinsics"
  4. @(optimization_mode="speed")
  5. adler32 :: proc(data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
  6. ADLER_CONST :: 65521;
  7. buffer := raw_data(data);
  8. a, b: u64 = u64(seed) & 0xFFFF, u64(seed) >> 16;
  9. buf := data[:];
  10. for len(buf) != 0 && uintptr(buffer) & 7 != 0 {
  11. a = (a + u64(buf[0]));
  12. b = (b + a);
  13. buffer = intrinsics.ptr_offset(buffer, 1);
  14. buf = buf[1:];
  15. }
  16. for len(buf) > 7 {
  17. count := min(len(buf), 5552);
  18. for count > 7 {
  19. a += u64(buf[0]); b += a;
  20. a += u64(buf[1]); b += a;
  21. a += u64(buf[2]); b += a;
  22. a += u64(buf[3]); b += a;
  23. a += u64(buf[4]); b += a;
  24. a += u64(buf[5]); b += a;
  25. a += u64(buf[6]); b += a;
  26. a += u64(buf[7]); b += a;
  27. buf = buf[8:];
  28. count -= 8;
  29. }
  30. a %= ADLER_CONST;
  31. b %= ADLER_CONST;
  32. }
  33. for len(buf) != 0 {
  34. a = (a + u64(buf[0])) % ADLER_CONST;
  35. b = (b + a) % ADLER_CONST;
  36. buf = buf[1:];
  37. }
  38. return (u32(b) << 16) | u32(a);
  39. }
  40. @(optimization_mode="speed")
  41. djb2 :: proc(data: []byte) -> u32 {
  42. hash: u32 = 5381;
  43. for b in data {
  44. hash = (hash << 5) + hash + u32(b); // hash * 33 + u32(b)
  45. }
  46. return hash;
  47. }
  48. @(optimization_mode="speed")
  49. fnv32 :: proc(data: []byte) -> u32 {
  50. h: u32 = 0x811c9dc5;
  51. for b in data {
  52. h = (h * 0x01000193) ~ u32(b);
  53. }
  54. return h;
  55. }
  56. @(optimization_mode="speed")
  57. fnv64 :: proc(data: []byte) -> u64 {
  58. h: u64 = 0xcbf29ce484222325;
  59. for b in data {
  60. h = (h * 0x100000001b3) ~ u64(b);
  61. }
  62. return h;
  63. }
  64. @(optimization_mode="speed")
  65. fnv32a :: proc(data: []byte) -> u32 {
  66. h: u32 = 0x811c9dc5;
  67. for b in data {
  68. h = (h ~ u32(b)) * 0x01000193;
  69. }
  70. return h;
  71. }
  72. @(optimization_mode="speed")
  73. fnv64a :: proc(data: []byte) -> u64 {
  74. h: u64 = 0xcbf29ce484222325;
  75. for b in data {
  76. h = (h ~ u64(b)) * 0x100000001b3;
  77. }
  78. return h;
  79. }
  80. @(optimization_mode="speed")
  81. jenkins :: proc(data: []byte) -> u32 {
  82. hash: u32 = 0;
  83. for b in data {
  84. hash += u32(b);
  85. hash += hash << 10;
  86. hash ~= hash >> 6;
  87. }
  88. hash += hash << 3;
  89. hash ~= hash >> 11;
  90. hash += hash << 15;
  91. return hash;
  92. }
  93. @(optimization_mode="speed")
  94. murmur32 :: proc(data: []byte) -> u32 {
  95. c1_32: u32 : 0xcc9e2d51;
  96. c2_32: u32 : 0x1b873593;
  97. h1: u32 = 0;
  98. nblocks := len(data)/4;
  99. p := raw_data(data);
  100. p1 := mem.ptr_offset(p, 4*nblocks);
  101. for ; p < p1; p = mem.ptr_offset(p, 4) {
  102. k1 := (cast(^u32)p)^;
  103. k1 *= c1_32;
  104. k1 = (k1 << 15) | (k1 >> 17);
  105. k1 *= c2_32;
  106. h1 ~= k1;
  107. h1 = (h1 << 13) | (h1 >> 19);
  108. h1 = h1*5 + 0xe6546b64;
  109. }
  110. tail := data[nblocks*4:];
  111. k1: u32;
  112. switch len(tail)&3 {
  113. case 3:
  114. k1 ~= u32(tail[2]) << 16;
  115. fallthrough;
  116. case 2:
  117. k1 ~= u32(tail[2]) << 8;
  118. fallthrough;
  119. case 1:
  120. k1 ~= u32(tail[0]);
  121. k1 *= c1_32;
  122. k1 = (k1 << 15) | (k1 >> 17) ;
  123. k1 *= c2_32;
  124. h1 ~= k1;
  125. }
  126. h1 ~= u32(len(data));
  127. h1 ~= h1 >> 16;
  128. h1 *= 0x85ebca6b;
  129. h1 ~= h1 >> 13;
  130. h1 *= 0xc2b2ae35;
  131. h1 ~= h1 >> 16;
  132. return h1;
  133. }
  134. @(optimization_mode="speed")
  135. murmur64 :: proc(data: []byte) -> u64 {
  136. SEED :: 0x9747b28c;
  137. when size_of(int) == 8 {
  138. m :: 0xc6a4a7935bd1e995;
  139. r :: 47;
  140. h: u64 = SEED ~ (u64(len(data)) * m);
  141. data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64));
  142. for _, i in data64 {
  143. k := data64[i];
  144. k *= m;
  145. k ~= k>>r;
  146. k *= m;
  147. h ~= k;
  148. h *= m;
  149. }
  150. switch len(data)&7 {
  151. case 7: h ~= u64(data[6]) << 48; fallthrough;
  152. case 6: h ~= u64(data[5]) << 40; fallthrough;
  153. case 5: h ~= u64(data[4]) << 32; fallthrough;
  154. case 4: h ~= u64(data[3]) << 24; fallthrough;
  155. case 3: h ~= u64(data[2]) << 16; fallthrough;
  156. case 2: h ~= u64(data[1]) << 8; fallthrough;
  157. case 1:
  158. h ~= u64(data[0]);
  159. h *= m;
  160. }
  161. h ~= h>>r;
  162. h *= m;
  163. h ~= h>>r;
  164. return h;
  165. } else {
  166. m :: 0x5bd1e995;
  167. r :: 24;
  168. h1 := u32(SEED) ~ u32(len(data));
  169. h2 := u32(SEED) >> 32;
  170. data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32));
  171. len := len(data);
  172. i := 0;
  173. for len >= 8 {
  174. k1, k2: u32;
  175. k1 = data32[i]; i += 1;
  176. k1 *= m;
  177. k1 ~= k1>>r;
  178. k1 *= m;
  179. h1 *= m;
  180. h1 ~= k1;
  181. len -= 4;
  182. k2 = data32[i]; i += 1;
  183. k2 *= m;
  184. k2 ~= k2>>r;
  185. k2 *= m;
  186. h2 *= m;
  187. h2 ~= k2;
  188. len -= 4;
  189. }
  190. if len >= 4 {
  191. k1: u32;
  192. k1 = data32[i]; i += 1;
  193. k1 *= m;
  194. k1 ~= k1>>r;
  195. k1 *= m;
  196. h1 *= m;
  197. h1 ~= k1;
  198. len -= 4;
  199. }
  200. // TODO(bill): Fix this
  201. #no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3];
  202. switch len {
  203. case 3:
  204. h2 ~= u32(data8[2]) << 16;
  205. fallthrough;
  206. case 2:
  207. h2 ~= u32(data8[1]) << 8;
  208. fallthrough;
  209. case 1:
  210. h2 ~= u32(data8[0]);
  211. h2 *= m;
  212. }
  213. h1 ~= h2>>18;
  214. h1 *= m;
  215. h2 ~= h1>>22;
  216. h2 *= m;
  217. h1 ~= h2>>17;
  218. h1 *= m;
  219. h2 ~= h1>>19;
  220. h2 *= m;
  221. return u64(h1)<<32 | u64(h2);
  222. }
  223. }
  224. @(optimization_mode="speed")
  225. sdbm :: proc(data: []byte) -> u32 {
  226. hash: u32 = 0;
  227. for b in data {
  228. hash = u32(b) + (hash<<6) + (hash<<16) - hash;
  229. }
  230. return hash;
  231. }