sdk/Util/Crc64.cs (117 lines of code) (raw):

/* * Copyright (C) Alibaba Cloud Computing * All rights reserved. * */ namespace Aliyun.OSS.Util { public class Crc64 { private static ulong[] _table; private static object _lock = new object(); private const int GF2_DIM = 64; /* dimension of GF(2) vectors (length of CRC) */ private static ulong _poly; private static void GenStdCrcTable(ulong poly) { _poly = poly; _table = new ulong[256]; for (uint n = 0; n < 256; n++) { ulong crc = n; for (int k = 0; k < 8; k++) { if ((crc & 1) == 1) { crc = (crc >> 1) ^ poly; } else { crc = (crc >> 1); } } _table[n] = crc; } } private static ulong TableValue(ulong[] table, byte b, ulong crc) { unchecked { return (crc >> 8) ^ table[(crc ^ b) & 0xffUL]; } } public static void Init(ulong poly) { if (_table == null) { lock (_lock) { if (_table == null) { GenStdCrcTable(poly); } } } } public static void InitECMA() { Init(0xC96C5795D7870F42); } public static ulong Compute(byte[] bytes, int start, int size, ulong crc = 0) { crc = ~crc; for (var i = start; i < start + size; i++) { crc = TableValue(_table, bytes[i], crc); } crc = ~crc; return crc; } private static ulong Gf2MatrixTimes(ulong[] mat, ulong vec) { ulong sum = 0; int idx = 0; while (vec != 0) { if ((vec & 1) == 1) sum ^= mat[idx]; vec >>= 1; idx++; } return sum; } private static void Gf2MatrixSquare(ulong[] square, ulong[] mat) { for (int n = 0; n < GF2_DIM; n++) square[n] = Gf2MatrixTimes(mat, mat[n]); } /// <summary> /// Return the CRC-64 of two sequential blocks, where summ1 is the CRC-64 of the /// first block, summ2 is the CRC-64 of the second block, and len2 is the length /// of the second block. /// </summary> /// <returns>The combined crc</returns> /// <param name="crc1">Crc1.</param> /// <param name="crc2">Crc2.</param> /// <param name="len2">Len2.</param> static public ulong Combine(ulong crc1, ulong crc2, long len2) { // degenerate case. if (len2 == 0) return crc1; int n; ulong row; ulong[] even = new ulong[GF2_DIM]; // even-power-of-two zeros operator ulong[] odd = new ulong[GF2_DIM]; // odd-power-of-two zeros operator // put operator for one zero bit in odd odd[0] = _poly; // CRC-64 polynomial row = 1; for (n = 1; n < GF2_DIM; n++) { odd[n] = row; row <<= 1; } // put operator for two zero bits in even Gf2MatrixSquare(even, odd); // put operator for four zero bits in odd Gf2MatrixSquare(odd, even); // apply len2 zeros to crc1 (first square will put the operator for one // zero byte, eight zero bits, in even) do { // apply zeros operator for this bit of len2 Gf2MatrixSquare(even, odd); if ((len2 & 1) == 1) crc1 = Gf2MatrixTimes(even, crc1); len2 >>= 1; // if no more bits set, then done if (len2 == 0) break; // another iteration of the loop with odd and even swapped Gf2MatrixSquare(odd, even); if ((len2 & 1) == 1) crc1 = Gf2MatrixTimes(odd, crc1); len2 >>= 1; // if no more bits set, then done } while (len2 != 0); // return combined crc. crc1 ^= crc2; return crc1; } } }