Last active
February 8, 2019 20:49
-
-
Save mjs3339/d4eb8d74e26a6c87933103b325149658 to your computer and use it in GitHub Desktop.
C# FNV1a32 XOR Folding Version
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
/// <summary> | |
/// XOR folding version reduces collisions by greater than ~2/3's | |
/// </summary> | |
public class FNV1a32 : HashAlgorithm | |
{ | |
private const uint K = 0x1000193; | |
private uint _hash; | |
public uint Hash; | |
public uint Seed = 0x811c9dc5; | |
public FNV1a32() | |
{ | |
_hash = Seed; | |
} | |
public FNV1a32(uint seed) | |
{ | |
Seed = seed; | |
_hash = Seed; | |
} | |
public override int HashSize => 32; | |
public override void Initialize() | |
{ | |
_hash = Seed; | |
} | |
protected override void HashCore(byte[] bytes, int ibStart, int cbSize) | |
{ | |
Hash32(bytes, ibStart, cbSize); | |
} | |
private void Hash32(byte[] bytes, int ibStart, int cbSize) | |
{ | |
if(bytes == null) | |
return; | |
if(ibStart >= bytes.Length || cbSize > bytes.Length) | |
return; | |
var ohLen = cbSize >> 1; | |
var h1 = _hash; | |
for (var i = ibStart; i < ohLen; i++) | |
h1 = (h1 ^ bytes[i]) * K; | |
var h2 = h1; | |
for (var i = ibStart+ ohLen; i < cbSize; i++) | |
h2 = (h2 ^ bytes[i]) * K; | |
h1 ^= (uint)cbSize; | |
h2 ^= (uint)cbSize; | |
_hash = (h1 >> 24) ^ (h2 & 0xffffffff); | |
} | |
/// <summary> | |
/// Exposed so that hash64 can be used externally. | |
/// </summary> | |
public uint Hash32(byte[] bytes) | |
{ | |
var cbSize = bytes.Length; | |
var ohLen = cbSize >> 1; | |
_hash = Seed; | |
var h1 = _hash; | |
for(var i = 0; i < ohLen; i++) | |
h1 = (h1 ^ bytes[i]) * K; | |
var h2 = h1; | |
for(var i = ohLen; i < cbSize; i++) | |
h2 = (h2 ^ bytes[i]) * K; | |
h1 ^= (uint)cbSize; | |
h2 ^= (uint)cbSize; | |
_hash = (h1 >> 24) ^ (h2 & 0xffffffff); | |
return _hash; | |
} | |
protected override byte[] HashFinal() | |
{ | |
Hash = _hash; | |
return _hash.GetBytes(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment