public class CRC64
{
private readonly ulong[] _table;
private readonly ulong _polynomial = 0x42F0E1EBA9EA3693;
private readonly ulong _initialValue = 0x0000000000000000;
private readonly ulong _finalXorValue = 0x0000000000000000;
public CRC64()
{
_table = CreateLookupTable(_polynomial);
}
public CRC64(ulong polynomial, ulong initialValue, ulong finalXorValue)
{
_polynomial = polynomial;
_initialValue = initialValue;
_finalXorValue = finalXorValue;
_table = CreateLookupTable(_polynomial);
}
public ulong Compute(byte[] bytes)
{
ulong current = _initialValue;
for (var i = 0; i < bytes.Length; i++)
current = TableValue(_table, bytes[i], current);
return current ^ _finalXorValue;
}
private ulong PolynomialCaculate(int index, ulong polynomial)
{
ulong returnValue = (ulong)index;
ulong topBit = (ulong)1L << (64 - 1);
ulong mask = 0xffffffffffffffffUL;
returnValue <<= (64 - 8);
for (int i = 0; i < 8; i++)
{
if ((returnValue & topBit) != 0)
returnValue = (returnValue << 1) ^ polynomial;
else
returnValue <<= 1;
}
return returnValue & mask;
}
private ulong[] CreateLookupTable(ulong polynomial)
{
ulong[] table = new ulong[256];
for (var i = 0; i < 256; i++)
table[i] = PolynomialCaculate(i, polynomial);
return table;
}
private ulong TableValue(ulong[] table, byte b, ulong crc)
{
return table[((crc >> 56) ^ b) & 0xffUL] ^ (crc << 8);
}
}

Leave a comment