Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active April 24, 2018 20:53
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/f841ec8c08f12f59689063b300d3a9ba to your computer and use it in GitHub Desktop.
Save mjs3339/f841ec8c08f12f59689063b300d3a9ba to your computer and use it in GitHub Desktop.
C# FNV1a128 Implementation
/// <summary>
/// No collisions with 20M random byte arrays. 32x slower than FNV1a64.
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
/// </summary>
public class FNV1a128 : HashAlgorithm
{
private readonly BigInteger _K = "309485009821345068724781371".NewBigInteger10();
private BigInteger _hash;
private readonly BigInteger Seed = "144066263297769815596495629667062367629".NewBigInteger10();
public FNV1a128()
{
}
public FNV1a128(string seed)
{
Seed = seed.NewBigInteger10();
Initialize();
}
public override int HashSize => 128;
public override void Initialize()
{
_hash = Seed;
public class FNV1a128 : HashAlgorithm
{
private readonly BigInteger _K = "309485009821345068724781371".NewBigInteger10();
private BigInteger _hash;
private readonly BigInteger Seed = "144066263297769815596495629667062367629".NewBigInteger10();
public FNV1a128()
{
_hash = Seed;
}
public FNV1a128(string seed)
{
Seed = seed.NewBigInteger10();
_hash = Seed;
}
public override int HashSize => 128;
public override void Initialize()
{
_hash = Seed;
}
protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
{
Hash64(bytes, ibStart, cbSize);
}
private void Hash64(byte[] bytes, int ibStart, int cbSize)
{
if (bytes == null)
return;
if (ibStart >= bytes.Length || cbSize > bytes.Length)
return;
var p = 0;
while (cbSize > 0)
{
_hash ^= bytes[p + ibStart];
_hash *= _K;
cbSize--;
p++;
}
_hash = _hash ^ (_hash >> 64);
}
/// <summary>
/// BigInteger does not overflow, so we limit the output to 128Bits.
/// </summary>
protected override byte[] HashFinal()
{
return _hash.ToByteArray().SubByte(0, 16);
}
} }
protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
{
Hash64(bytes, ibStart, cbSize);
}
private void Hash64(byte[] bytes, int ibStart, int cbSize)
{
if (bytes == null)
return;
if (ibStart >= bytes.Length || cbSize > bytes.Length)
return;
var p = 0;
while (cbSize > 0)
{
_hash ^= bytes[p + ibStart];
_hash *= _K;
cbSize--;
p++;
}
_hash = _hash ^ (_hash >> 64);
}
/// <summary>
/// BigInteger does not overflow, so we limit the output to 128Bits.
/// </summary>
protected override byte[] HashFinal()
{
return _hash.ToByteArray().SubByte(0, 16);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment