1 /// Implementation of MurmurHash digester.
2 module tern.digest.murmurhash;
3 
4 import tern.memory;
5 import tern.serialization;
6 import tern.digest;
7 import core.bitop;
8 
9 /**
10  * Implementation of MurmurHash digester.
11  *
12  * MurmurHash is a non-cryptographic hash function suitable for general hash-based 
13  * lookup. It provides fast and relatively good distribution of hash values.
14  *
15  * Example:
16  * ```d
17  * ubyte[] data = [1, 2, 3, 4, 5];
18  * auto hashValue = MurmurHash.hash(data);
19  * ```
20  */
21 public static @digester class MurmurHash
22 {
23 private:
24 static:
25 pure:
26     enum C1 = 0xcc9e2d51;
27     enum C2 = 0x1b873593;
28     enum R1 = 15;
29     enum R2 = 13;
30     enum M = 5;
31     enum N = 0xe6546b64;
32 
33 public:
34     /**
35      * Computes the MurmurHash digest of the given data.
36      *
37      * Params:
38      *  data = The input byte array for which the hash is to be computed.
39      *  seed = An optional seed value used to initialize the hash function. Defaults to 0.
40      *
41      * Returns:
42      *  An array of bytes representing the computed MurmurHash digest.
43      */
44     ubyte[] hash(ubyte[] data, uint seed = 0)
45     {
46         sachp(data, 4);
47 
48         uint hash = seed;
49         foreach (k; cast(uint[])data)
50         {
51             k *= C1;
52             k = rol(k, R1);
53             k *= C2;
54 
55             hash ^= k;
56             hash = rol(hash, R2);
57             hash = hash * M + N;
58         }
59 
60         hash ^= data.length * 4;
61         hash ^= hash >> 16;
62         hash *= 0x85ebca6b;
63         hash ^= hash >> 13;
64         hash *= 0xC2b2ae35;
65         hash ^= hash >> 16;
66 
67         return hash.serialize!true();
68     }
69 }