Kinetica C# API  Version 7.0.19.0
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Pages
MurMurHash3.cs
Go to the documentation of this file.
1 /*
2 This code is public domain.
3 
4 The MurmurHash3 algorithm was created by Austin Appleby and put into the public domain. See http://code.google.com/p/smhasher/
5 */
6 
7 using System;
8 
9 
10 namespace kinetica
11 {
12 
23  public static class MurMurHash3
24  {
26  public class LongPair
27  {
28  public long val1 { get; set; }
29  public long val2 { get; set; }
30  }
31 
32 
33  private static ulong fmix64( UInt64 k )
34  {
35  k ^= k >> 33;
36  k *= 0xff51afd7ed558ccdL;
37  k ^= k >> 33;
38  k *= 0xc4ceb9fe1a85ec53L;
39  k ^= k >> 33;
40  return k;
41  } // end fmix64
42 
43 
50  private static ulong RotateLeft( this ulong original, int bits )
51  {
52  return ( original << bits ) | ( original >> ( 64 - bits ) );
53  }
54 
55 
56 
57 
59  public static void murmurhash3_x64_128( byte[] key, uint offset, uint len, int seed, out LongPair output )
60  {
61  // The original algorithm does have a 32 bit unsigned seed.
62  // We have to mask to match the behavior of the unsigned types and prevent sign extension.
63  ulong h1 = (ulong) (seed & 0x00000000FFFFFFFFL);
64  ulong h2 = (ulong) (seed & 0x00000000FFFFFFFFL);
65 
66  const ulong c1 = 0x87c37b91114253d5L;
67  const ulong c2 = 0x4cf5ad432745937fL;
68 
69  uint roundedEnd = offset + (len & 0xFFFFFFF0); // round down to 16 byte block
70 
71  // Process the body in 16 byte blocks
72  for ( int i = (int)offset; i < roundedEnd; i += 16 )
73  {
74  ulong key1 = BitConverter.ToUInt64( key, i );
75  ulong key2 = BitConverter.ToUInt64( key, (i + 8) );
76 
77  key1 *= c1; key1 = key1.RotateLeft( 31 ); key1 *= c2; h1 ^= key1;
78  h1 = h1.RotateLeft( 27 ); h1 += h2; h1 = h1 * 5 + 0x52dce729;
79  key2 *= c2; key2 = key2.RotateLeft( 33 ); key2 *= c1; h2 ^= key2;
80  h2 = h2.RotateLeft( 31 ); h2 += h1; h2 = h2 * 5 + 0x38495ab5;
81  }
82 
83  // Process the remaining bytes, if any
84  ulong k1 = 0;
85  ulong k2 = 0;
86 
87  switch ( len & 15 )
88  {
89  case 15:
90  k2 = ( ulong ) ( key[roundedEnd + 14] & 0xffL ) << 48;
91  goto case 14; // fall through
92  case 14:
93  k2 |= ( ulong ) ( key[roundedEnd + 13] & 0xffL ) << 40;
94  goto case 13; // fall through
95  case 13:
96  k2 |= ( ulong ) ( key[roundedEnd + 12] & 0xffL ) << 32;
97  goto case 12; // fall through
98  case 12:
99  k2 |= ( ulong ) ( key[roundedEnd + 11] & 0xffL ) << 24;
100  goto case 11; // fall through
101  case 11:
102  k2 |= ( ulong ) ( key[roundedEnd + 10] & 0xffL ) << 16;
103  goto case 10; // fall through
104  case 10:
105  k2 |= ( ulong ) ( key[roundedEnd + 9] & 0xffL ) << 8;
106  goto case 9; // fall through
107  case 9:
108  k2 |= ( ulong ) ( key[roundedEnd + 8] & 0xffL );
109  k2 *= c2; k2 = k2.RotateLeft( 33 ); k2 *= c1; h2 ^= k2;
110  //break;
111  goto case 8; // fall through
112 
113  case 8:
114  k1 = ( ( ulong ) key[roundedEnd + 7] ) << 56;
115  goto case 7; // fall through
116  case 7:
117  k1 |= ( ulong ) ( key[roundedEnd + 6] & 0xffL ) << 48;
118  goto case 6; // fall through
119  case 6:
120  k1 |= ( ulong ) ( key[roundedEnd + 5] & 0xffL ) << 40;
121  goto case 5; // fall through
122  case 5:
123  k1 |= ( ulong ) ( key[roundedEnd + 4] & 0xffL ) << 32;
124  goto case 4; // fall through
125  case 4:
126  k1 |= ( ulong ) ( key[roundedEnd + 3] & 0xffL ) << 24;
127  goto case 3; // fall through
128  case 3:
129  k1 |= ( ulong ) ( key[roundedEnd + 2] & 0xffL ) << 16;
130  goto case 2; // fall through
131  case 2:
132  k1 |= ( ulong ) ( key[roundedEnd + 1] & 0xffL ) << 8;
133  goto case 1; // fall through
134  case 1:
135  k1 |= ( ulong ) ( key[roundedEnd] & 0xffL );
136  k1 *= c1; k1 = k1.RotateLeft( 31 ); k1 *= c2; h1 ^= k1;
137  break;
138  }
139 
140  //----------
141  // Finalize the values
142 
143  h1 ^= len;
144  h2 ^= len;
145 
146  h1 += h2;
147  h2 += h1;
148 
149  h1 = fmix64( h1 );
150  h2 = fmix64( h2 );
151 
152  h1 += h2;
153  h2 += h1;
154 
155  // Save the values in the output
156  output = new LongPair();
157  output.val1 = (long) h1;
158  output.val2 = (long) h2;
159  } // end murmurhash3_x64_128
160 
161  } // end class MurMurHash3
162 
163 } // end namespace kinetica
static void murmurhash3_x64_128(byte[] key, uint offset, uint len, int seed, out LongPair output)
Returns the MurmurHash3_x64_128 hash, placing the result in output
Definition: MurMurHash3.cs:59