public static ulong ComputeHash(byte[] input) { uint len = (uint)input.Length; uint num_chunks = len / 128; // copy tail, pad with zeroes byte[] tail = new byte[128]; uint tail_size = len % 128; Array.Copy(input, len - tail_size, tail, 0, tail_size); UInt128 hash; if (num_chunks != 0) { hash = HashChunk(input, 128, 0); } else { hash = HashChunk(tail, tail_size, 0); } hash += ROUND_MAGIC; int offset = 0; if (num_chunks != 0) { while (--num_chunks > 0) { offset += 128; hash = HashMulAdd(hash, ROUND_MAGIC, HashChunk(input, 128, offset)); } if (tail_size > 0) { hash = HashMulAdd(hash, ROUND_MAGIC, HashChunk(tail, tail_size, 0)); } } hash += new UInt128(tail_size * 8, 0); if (hash > new UInt128(0x7fffffffffffffff, 0xffffffffffffffff)) { hash++; } hash = hash << 1 >> 1; ulong X = hash.hi + (hash.lo >> 32); X = ((X + (X >> 32) + 1) >> 32) + hash.hi; ulong Y = (X << 32) + hash.lo; ulong A = X + FINAL_MAGIC0; if (A < X) { A += 0x101; } ulong B = Y + FINAL_MAGIC1; if (B < Y) { B += 0x101; } UInt128 H = new UInt128(A) * B; UInt128 mul = new UInt128(0x101); H = (mul * H.hi) + H.lo; H = (mul * H.hi) + H.lo; if (H.hi > 0) { H += mul; } if (H.lo > 0xFFFFFFFFFFFFFEFE) { H += mul; } return(H.lo); }
public bool Equals(UInt128 other) { return(hi == other.hi && lo == other.lo); }