Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active February 8, 2019 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/d4eb8d74e26a6c87933103b325149658 to your computer and use it in GitHub Desktop.
Save mjs3339/d4eb8d74e26a6c87933103b325149658 to your computer and use it in GitHub Desktop.
C# FNV1a32 XOR Folding Version
/// <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