protected override void Blocks(byte[] m, int offset, int count) { unchecked { UInt64 hibit = m_final ? 0 : ((UInt64)1 << 40); /* 1 << 128 */ UInt64 r0, r1, r2; UInt64 s1, s2; UInt64 h0, h1, h2; UInt64 c; UInt128 d0 = new UInt128(); UInt128 d1 = new UInt128(); UInt128 d2 = new UInt128(); r0 = m_r[0]; r1 = m_r[1]; r2 = m_r[2]; h0 = m_h[0]; h1 = m_h[1]; h2 = m_h[2]; s1 = r1 * (5 << 2); s2 = r2 * (5 << 2); while (count >= BlockSize) { UInt64 t0, t1; /* h += m[i] */ t0 = BytesToInt64(m, offset); t1 = BytesToInt64(m, 8 + offset); h0 += ((t0) & 0xfffffffffff); h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); h2 += (((t1 >> 24)) & 0x3ffffffffff) | hibit; /* h *= r */ d0.SetMultiplyUInt64(ref h0, ref r0); d0.AddMultiplyUInt64(ref h1, ref s2); d0.AddMultiplyUInt64(ref h2, ref s1); d1.SetMultiplyUInt64(ref h0, ref r1); d1.AddMultiplyUInt64(ref h1, ref r0); d1.AddMultiplyUInt64(ref h2, ref s2); d2.SetMultiplyUInt64(ref h0, ref r2); d2.AddMultiplyUInt64(ref h1, ref r1); d2.AddMultiplyUInt64(ref h2, ref r0); /* (partial) h %= p */ c = (d0 >> 44).Low; h0 = d0.Low & 0xfffffffffff; d1.Add(c); c = (d1 >> 44).Low; h1 = d1.Low & 0xfffffffffff; d2.Add(c); c = (d2 >> 42).Low; h2 = d2.Low & 0x3ffffffffff; h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; h1 += c; offset += BlockSize; count -= BlockSize; } m_h[0] = h0; m_h[1] = h1; m_h[2] = h2; } }