| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- package hash
- import "core:mem"
- import "base:intrinsics"
- @(optimization_mode="speed")
- adler32 :: proc(data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
- ADLER_CONST :: 65521
- buffer := raw_data(data)
- a, b: u64 = u64(seed) & 0xFFFF, u64(seed) >> 16
- buf := data[:]
- for len(buf) != 0 && uintptr(buffer) & 7 != 0 {
- a = (a + u64(buf[0]))
- b = (b + a)
- buffer = buffer[1:]
- buf = buf[1:]
- }
- for len(buf) > 7 {
- count := min(len(buf), 5552)
- for count > 7 {
- a += u64(buf[0]); b += a
- a += u64(buf[1]); b += a
- a += u64(buf[2]); b += a
- a += u64(buf[3]); b += a
- a += u64(buf[4]); b += a
- a += u64(buf[5]); b += a
- a += u64(buf[6]); b += a
- a += u64(buf[7]); b += a
- buf = buf[8:]
- count -= 8
- }
- a %= ADLER_CONST
- b %= ADLER_CONST
- }
- for len(buf) != 0 {
- a = (a + u64(buf[0])) % ADLER_CONST
- b = (b + a) % ADLER_CONST
- buf = buf[1:]
- }
- return (u32(b) << 16) | u32(a)
- }
- @(optimization_mode="speed")
- djb2 :: proc(data: []byte, seed := u32(5381)) -> u32 {
- hash: u32 = seed
- for b in data {
- hash = (hash << 5) + hash + u32(b) // hash * 33 + u32(b)
- }
- return hash
- }
- djbx33a :: proc(data: []byte, seed := u32(5381)) -> (result: [16]byte) #no_bounds_check {
- state := [4]u32{seed, seed, seed, seed}
-
- s: u32 = 0
- for p in data {
- state[s] = (state[s] << 5) + state[s] + u32(p) // hash * 33 + u32(b)
- s = (s + 1) & 3
- }
-
-
- (^u32le)(&result[0])^ = u32le(state[0])
- (^u32le)(&result[4])^ = u32le(state[1])
- (^u32le)(&result[8])^ = u32le(state[2])
- (^u32le)(&result[12])^ = u32le(state[3])
- return
- }
- // If you have a choice, prefer fnv32a
- @(optimization_mode="speed")
- fnv32_no_a :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
- h: u32 = seed
- for b in data {
- h = (h * 0x01000193) ~ u32(b)
- }
- return h
- }
- fnv32 :: fnv32_no_a // NOTE(bill): Not a fan of these aliases but seems necessary
- fnv64 :: fnv64_no_a // NOTE(bill): Not a fan of these aliases but seems necessary
- // If you have a choice, prefer fnv64a
- @(optimization_mode="speed")
- fnv64_no_a :: proc(data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
- h: u64 = seed
- for b in data {
- h = (h * 0x100000001b3) ~ u64(b)
- }
- return h
- }
- @(optimization_mode="speed")
- fnv32a :: proc(data: []byte, seed := u32(0x811c9dc5)) -> u32 {
- h: u32 = seed
- for b in data {
- h = (h ~ u32(b)) * 0x01000193
- }
- return h
- }
- @(optimization_mode="speed")
- fnv64a :: proc(data: []byte, seed := u64(0xcbf29ce484222325)) -> u64 {
- h: u64 = seed
- for b in data {
- h = (h ~ u64(b)) * 0x100000001b3
- }
- return h
- }
- @(optimization_mode="speed")
- jenkins :: proc(data: []byte, seed := u32(0)) -> u32 {
- hash: u32 = seed
- for b in data {
- hash += u32(b)
- hash += hash << 10
- hash ~= hash >> 6
- }
- hash += hash << 3
- hash ~= hash >> 11
- hash += hash << 15
- return hash
- }
- @(optimization_mode="speed")
- murmur32 :: proc(data: []byte, seed := u32(0)) -> u32 {
- c1_32: u32 : 0xcc9e2d51
- c2_32: u32 : 0x1b873593
- h1: u32 = seed
- nblocks := len(data)/4
- p := raw_data(data)
- p1 := p[4*nblocks:]
- for ; p < p1; p = p[4:] {
- k1 := (cast(^u32)p)^
- k1 *= c1_32
- k1 = (k1 << 15) | (k1 >> 17)
- k1 *= c2_32
- h1 ~= k1
- h1 = (h1 << 13) | (h1 >> 19)
- h1 = h1*5 + 0xe6546b64
- }
- tail := data[nblocks*4:]
- k1: u32
- switch len(tail)&3 {
- case 3:
- k1 ~= u32(tail[2]) << 16
- fallthrough
- case 2:
- k1 ~= u32(tail[1]) << 8
- fallthrough
- case 1:
- k1 ~= u32(tail[0])
- k1 *= c1_32
- k1 = (k1 << 15) | (k1 >> 17)
- k1 *= c2_32
- h1 ~= k1
- }
- h1 ~= u32(len(data))
- h1 ~= h1 >> 16
- h1 *= 0x85ebca6b
- h1 ~= h1 >> 13
- h1 *= 0xc2b2ae35
- h1 ~= h1 >> 16
- return h1
- }
- // See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L96
- @(optimization_mode="speed")
- murmur64a :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
- m :: 0xc6a4a7935bd1e995
- r :: 47
- h: u64 = seed ~ (u64(len(data)) * m)
- data64 := mem.slice_data_cast([]u64, data)
- for _, i in data64 {
- k := data64[i]
- k *= m
- k ~= k>>r
- k *= m
- h ~= k
- h *= m
- }
- offset := len(data64) * size_of(u64)
- switch len(data)&7 {
- case 7: h ~= u64(data[offset + 6]) << 48; fallthrough
- case 6: h ~= u64(data[offset + 5]) << 40; fallthrough
- case 5: h ~= u64(data[offset + 4]) << 32; fallthrough
- case 4: h ~= u64(data[offset + 3]) << 24; fallthrough
- case 3: h ~= u64(data[offset + 2]) << 16; fallthrough
- case 2: h ~= u64(data[offset + 1]) << 8; fallthrough
- case 1:
- h ~= u64(data[offset + 0])
- h *= m
- }
- h ~= h>>r
- h *= m
- h ~= h>>r
- return h
- }
- // See https://github.com/aappleby/smhasher/blob/master/src/MurmurHash2.cpp#L140
- @(optimization_mode="speed")
- murmur64b :: proc(data: []byte, seed := u64(0x9747b28c)) -> u64 {
- m :: 0x5bd1e995
- r :: 24
- h1 := u32(seed) ~ u32(len(data))
- h2 := u32(seed) >> 32
- data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32))
- len := len(data)
- i := 0
- for len >= 8 {
- k1, k2: u32
- k1 = data32[i]; i += 1
- k1 *= m
- k1 ~= k1>>r
- k1 *= m
- h1 *= m
- h1 ~= k1
- len -= 4
- k2 = data32[i]; i += 1
- k2 *= m
- k2 ~= k2>>r
- k2 *= m
- h2 *= m
- h2 ~= k2
- len -= 4
- }
- if len >= 4 {
- k1: u32
- k1 = data32[i]; i += 1
- k1 *= m
- k1 ~= k1>>r
- k1 *= m
- h1 *= m
- h1 ~= k1
- len -= 4
- }
- // TODO(bill): Fix this
- #no_bounds_check data8 := mem.slice_to_bytes(data32[i:])[:3]
- switch len {
- case 3:
- h2 ~= u32(data8[2]) << 16
- fallthrough
- case 2:
- h2 ~= u32(data8[1]) << 8
- fallthrough
- case 1:
- h2 ~= u32(data8[0])
- h2 *= m
- }
- h1 ~= h2>>18
- h1 *= m
- h2 ~= h1>>22
- h2 *= m
- h1 ~= h2>>17
- h1 *= m
- h2 ~= h1>>19
- h2 *= m
- return u64(h1)<<32 | u64(h2)
- }
- @(optimization_mode="speed")
- sdbm :: proc(data: []byte, seed := u32(0)) -> u32 {
- hash: u32 = seed
- for b in data {
- hash = u32(b) + (hash<<6) + (hash<<16) - hash
- }
- return hash
- }
|