-
-
Save rdev5/5bf9916849ad578b0439 to your computer and use it in GitHub Desktop.
MurMurHash3 .Net (C#) implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace TinyWAF.Helpers | |
{ | |
public static class MurmurHash3 | |
{ | |
// Source: https://gist.github.com/rdev5/5bf9916849ad578b0439 | |
const uint seed = 144; | |
// Source: http://stackoverflow.com/a/1879470/901156 | |
public static Stream CreateStreamFromString(string s) | |
{ | |
var stream = new MemoryStream(); | |
var writer = new StreamWriter(stream); | |
writer.Write(s); | |
writer.Flush(); | |
stream.Position = 0; | |
return stream; | |
} | |
public static int Hash(string input) | |
{ | |
const uint c1 = 0xcc9e2d51; | |
const uint c2 = 0x1b873593; | |
uint h1 = seed; | |
uint k1 = 0; | |
uint streamLength = 0; | |
// TODO: Parallelize | |
var chunk = new byte[4]; | |
var reader = Encoding.UTF8.GetBytes(input); | |
for (var i = 0; i < reader.Length; i += 4) | |
{ | |
switch(reader.Length - i) | |
{ | |
case 3: | |
k1 = (uint) | |
(chunk[0] | |
| chunk[1] << 8 | |
| chunk[2] << 16); | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
break; | |
case 2: | |
k1 = (uint) | |
(chunk[0] | |
| chunk[1] << 8); | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
break; | |
case 1: | |
k1 = (uint)(chunk[0]); | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
break; | |
default: | |
chunk[0] = reader[i]; | |
chunk[1] = reader[i + 1]; | |
chunk[2] = reader[i + 2]; | |
chunk[3] = reader[i + 3]; | |
/* Get four bytes from the input into an uint */ | |
k1 = (uint) | |
(chunk[0] | |
| chunk[1] << 8 | |
| chunk[2] << 16 | |
| chunk[3] << 24); | |
/* bitmagic hash */ | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
h1 = rotl32(h1, 13); | |
h1 = h1 * 5 + 0xe6546b64; | |
break; | |
} | |
} | |
// finalization, magic chants to wrap it all up | |
h1 ^= (uint)reader.Length; | |
h1 = fmix(h1); | |
// ignore overflow | |
unchecked | |
{ | |
return (int)h1; | |
} | |
} | |
public static int Hash(Stream stream) | |
{ | |
const uint c1 = 0xcc9e2d51; | |
const uint c2 = 0x1b873593; | |
uint h1 = seed; | |
uint k1 = 0; | |
uint streamLength = 0; | |
using (BinaryReader reader = new BinaryReader(stream)) | |
{ | |
byte[] chunk = reader.ReadBytes(4); | |
while (chunk.Length > 0) | |
{ | |
streamLength += (uint)chunk.Length; | |
switch(chunk.Length) | |
{ | |
case 4: | |
/* Get four bytes from the input into an uint */ | |
k1 = (uint) | |
(chunk[0] | |
| chunk[1] << 8 | |
| chunk[2] << 16 | |
| chunk[3] << 24); | |
/* bitmagic hash */ | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
h1 = rotl32(h1, 13); | |
h1 = h1 * 5 + 0xe6546b64; | |
break; | |
case 3: | |
k1 = (uint) | |
(chunk[0] | |
| chunk[1] << 8 | |
| chunk[2] << 16); | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
break; | |
case 2: | |
k1 = (uint) | |
(chunk[0] | |
| chunk[1] << 8); | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
break; | |
case 1: | |
k1 = (uint)(chunk[0]); | |
k1 *= c1; | |
k1 = rotl32(k1, 15); | |
k1 *= c2; | |
h1 ^= k1; | |
break; | |
} | |
chunk = reader.ReadBytes(4); | |
} | |
} | |
// finalization, magic chants to wrap it all up | |
h1 ^= streamLength; | |
h1 = fmix(h1); | |
unchecked //ignore overflow | |
{ | |
return (int)h1; | |
} | |
} | |
private static uint rotl32(uint x, byte r) | |
{ | |
return (x << r) | (x >> (32 - r)); | |
} | |
private static uint fmix(uint h) | |
{ | |
h ^= h >> 16; | |
h *= 0x85ebca6b; | |
h ^= h >> 13; | |
h *= 0xc2b2ae35; | |
h ^= h >> 16; | |
return h; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment