Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Last active January 12, 2021 14:25
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/850e143b26289d1a32f1344e548e08f0 to your computer and use it in GitHub Desktop.
Save mjs3339/850e143b26289d1a32f1344e548e08f0 to your computer and use it in GitHub Desktop.
C# Implementation of the FNV1a Hashing Algorithm.
using System;
using System.Security.Cryptography;
[Serializable]
public class FNV1a64 : HashAlgorithm
{
private const ulong K = 0x100000001B3;
private const ulong M = 0x1000000000000000;
public ulong _hash;
public ulong Hash;
public ulong Seed = 0xCBF29CE484222325;
public FNV1a64()
{
_hash = Seed;
}
public FNV1a64(ulong seed)
{
Seed = seed;
_hash = Seed;
}
public override int HashSize => 64;
public override void Initialize()
{
_hash = Seed;
}
protected override void HashCore(byte[] bytes, int ibStart, int cbSize)
{
Hash64(bytes, ibStart, cbSize);
}
private unsafe void Hash64(byte[] bytes, int ibStart, int cbSize)
{
if (bytes == null)
return;
if (ibStart >= bytes.Length || cbSize > bytes.Length)
return;
fixed (byte* pb = bytes)
{
var nb = pb + ibStart;
while (cbSize >= 8)
{
_hash ^= *(ulong*) nb;
nb += 8;
cbSize -= 8;
_hash *= K;
_hash %= M;
}
switch (cbSize & 7)
{
case 7:
_hash ^= *(ulong*) (nb + 6);
_hash *= K;
_hash %= M;
goto case 6;
case 6:
_hash ^= *(ulong*) (nb + 5);
_hash *= K;
_hash %= M;
goto case 5;
case 5:
_hash ^= *(ulong*) (nb + 4);
_hash *= K;
_hash %= M;
goto case 4;
case 4:
_hash ^= *(ulong*) (nb + 3);
_hash *= K;
_hash %= M;
goto case 3;
case 3:
_hash ^= *(ulong*) (nb + 2);
_hash *= K;
_hash %= M;
goto case 2;
case 2:
_hash ^= *(ulong*) (nb + 1);
_hash *= K;
_hash %= M;
goto case 1;
case 1:
_hash ^= *nb;
_hash *= K;
_hash %= M;
break;
}
}
}
public unsafe ulong Hash64(byte[] bytes)
{
var cbSize = bytes.Length;
_hash = Seed;
fixed (byte* pb = bytes)
{
var nb = pb;
while (cbSize >= 8)
{
_hash ^= *(ulong*) nb;
nb += 8;
cbSize -= 8;
_hash *= K;
_hash %= M;
}
switch (cbSize & 7)
{
case 7:
_hash ^= *(ulong*) (nb + 6);
_hash *= K;
_hash %= M;
goto case 6;
case 6:
_hash ^= *(ulong*) (nb + 5);
_hash *= K;
_hash %= M;
goto case 5;
case 5:
_hash ^= *(ulong*) (nb + 4);
_hash *= K;
_hash %= M;
goto case 4;
case 4:
_hash ^= *(ulong*) (nb + 3);
_hash *= K;
_hash %= M;
goto case 3;
case 3:
_hash ^= *(ulong*) (nb + 2);
_hash *= K;
_hash %= M;
goto case 2;
case 2:
_hash ^= *(ulong*) (nb + 1);
_hash *= K;
_hash %= M;
goto case 1;
case 1:
_hash ^= *nb;
_hash *= K;
_hash %= M;
break;
}
}
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