private static unsafe ulong HashLen0to16(byte *data, int length) { if (length >= 8) { ulong mul = FarmHashConstants.k2 + (uint)length * 2; ulong a = Utilities.Fetch64(data) + FarmHashConstants.k2; ulong b = Utilities.Fetch64(data, length - 8); ulong c = Utilities.RotateWithCheck(b, 37) * mul + a; ulong d = (Utilities.RotateWithCheck(a, 25) + b) * mul; return(HashLen16(c, d, mul)); } if (length >= 4) { ulong mul = FarmHashConstants.k2 + (uint)length * 2; ulong a = Utilities.Fetch32(data, 0); return(HashLen16((uint)length + (a << 3), Utilities.Fetch32(data, length - 4), mul)); } if (length > 0) { byte a = data[0]; byte b = data[length >> 1]; byte c = data[length - 1]; uint y = a + ((uint)b << 8); uint z = (uint)length + ((uint)c << 2); return(FarmHash.ShiftMix(y * FarmHashConstants.k2 ^ z * FarmHashConstants.k0) * FarmHashConstants.k2); } return(FarmHashConstants.k2); }
private static unsafe ulong H32(byte *data, int offset, int length, ulong mul, ulong seed0 = 0, ulong seed1 = 0) { ulong a = Utilities.Fetch64(data, offset) * FarmHashConstants.k1; ulong b = Utilities.Fetch64(data, 8 + offset); ulong c = Utilities.Fetch64(data, length - 8 + offset) * mul; ulong d = Utilities.Fetch64(data, length - 16 + offset) * FarmHashConstants.k2; ulong u = Utilities.RotateWithCheck(a + b, 43) + Utilities.RotateWithCheck(c, 30) + d + seed0; ulong v = a + Utilities.RotateWithCheck(b + FarmHashConstants.k2, 18) + c + seed1; a = FarmHash.ShiftMix((u ^ v) * mul); b = FarmHash.ShiftMix((v ^ a) * mul); return(b); }
private static unsafe ulong Hash64(byte *s, int len) { const ulong seed = 81; if (len <= 32) { if (len <= 16) { return(HashLen0to16(s, len)); } return(HashLen17to32(s, len)); } if (len <= 64) { return(HashLen33to64(s, len)); } // For strings over 64 bytes we loop. Internal state consists of 56 bytes: v, w, x, y, and z. ulong x = seed; ulong y = unchecked (seed * FarmHashConstants.k1) + 113; ulong z = FarmHash.ShiftMix(y * FarmHashConstants.k2 + 113) * FarmHashConstants.k2; Uint128 v = new Uint128(0, 0); Uint128 w = new Uint128(0, 0); x = x * FarmHashConstants.k2 + Utilities.Fetch64(s); // Set end so that after the loop we have 1 to 64 bytes left to process. int index = 0; int end = (len - 1) / 64 * 64; int last64 = end + ((len - 1) & 63) - 63; do { x = Utilities.RotateWithCheck(x + y + v.Low + Utilities.Fetch64(s, 8), 37) * FarmHashConstants.k1; y = Utilities.RotateWithCheck(y + v.High + Utilities.Fetch64(s, 48), 42) * FarmHashConstants.k1; x ^= w.High; y += v.Low + Utilities.Fetch64(s, 40); z = Utilities.RotateWithCheck(z + w.Low, 33) * FarmHashConstants.k1; v = WeakHashLen32WithSeeds(s, 0, v.High * FarmHashConstants.k1, x + w.Low); w = WeakHashLen32WithSeeds(s, 32, z + w.High, y + Utilities.Fetch64(s, 16)); Utilities.Swap(ref z, ref x); index += 64; } while (index != end); ulong mul = FarmHashConstants.k1 + ((z & 0xff) << 1); // Make s point to the last 64 bytes of input. index = last64; w.Low += ((uint)len - 1) & 63; v.Low += w.Low; w.Low += v.Low; x = Utilities.RotateWithCheck(x + y + v.Low + Utilities.Fetch64(s, index + 8), 37) * mul; y = Utilities.RotateWithCheck(y + v.High + Utilities.Fetch64(s, index + 48), 42) * mul; x ^= w.High * 9; y += v.Low * 9 + Utilities.Fetch64(s, index + 40); z = Utilities.RotateWithCheck(z + w.Low, 33) * mul; v = WeakHashLen32WithSeeds(s, index + 0, v.High * mul, x + w.Low); w = WeakHashLen32WithSeeds(s, index + 32, z + w.High, y + Utilities.Fetch64(s, index + 16)); Utilities.Swap(ref z, ref x); return(HashLen16(HashLen16(v.Low, w.Low, mul) + FarmHash.ShiftMix(y) * FarmHashConstants.k0 + z, HashLen16(v.High, w.High, mul) + x, mul)); }
private static unsafe ulong Hash64WithSeeds(byte *s, int len, ulong seed0, ulong seed1) { if (len <= 64) { return(HashLen16(Hash64(s, len) - seed0, seed1, 0x9ddfea08eb382d69UL)); //PORT NOTE: This used to refer to Hash128to64, which was the same as HashLen16, just with hardcoded mul } // For strings over 64 bytes we loop. Internal state consists of // 64 bytes: u, v, w, x, y, and z. ulong x = seed0; ulong y = seed1 * FarmHashConstants.k2 + 113; ulong z = FarmHash.ShiftMix(y * FarmHashConstants.k2) * FarmHashConstants.k2; Uint128 v = new Uint128(seed0, seed1); Uint128 w = new Uint128(0, 0); ulong u = x - z; x *= FarmHashConstants.k2; ulong mul = FarmHashConstants.k2 + (u & 0x82); // Set end so that after the loop we have 1 to 64 bytes left to process. int index = 0; int end = (len - 1) / 64 * 64; int last64 = end + ((len - 1) & 63) - 63; do { ulong a0 = Utilities.Fetch64(s); ulong a1 = Utilities.Fetch64(s, 8); ulong a2 = Utilities.Fetch64(s, 16); ulong a3 = Utilities.Fetch64(s, 24); ulong a4 = Utilities.Fetch64(s, 32); ulong a5 = Utilities.Fetch64(s, 40); ulong a6 = Utilities.Fetch64(s, 48); ulong a7 = Utilities.Fetch64(s, 56); x += a0 + a1; y += a2; z += a3; v.Low += a4; v.High += a5 + a1; w.Low += a6; w.High += a7; x = Utilities.RotateWithCheck(x, 26); x *= 9; y = Utilities.RotateWithCheck(y, 29); z *= mul; v.Low = Utilities.RotateWithCheck(v.Low, 33); v.High = Utilities.RotateWithCheck(v.High, 30); w.Low ^= x; w.Low *= 9; z = Utilities.RotateWithCheck(z, 32); z += w.High; w.High += z; z *= 9; Utilities.Swap(ref u, ref y); z += a0 + a6; v.Low += a2; v.High += a3; w.Low += a4; w.High += a5 + a6; x += a1; y += a7; y += v.Low; v.Low += x - y; v.High += w.Low; w.Low += v.High; w.High += x - y; x += w.High; w.High = Utilities.RotateWithCheck(w.High, 34); Utilities.Swap(ref u, ref z); index += 64; } while (index != end); // Make s point to the last 64 bytes of input. index = last64; u *= 9; v.High = Utilities.RotateWithCheck(v.High, 28); v.Low = Utilities.RotateWithCheck(v.Low, 20); w.Low += ((uint)len - 1) & 63; u += y; y += u; x = Utilities.RotateWithCheck(y - x + v.Low + Utilities.Fetch64(s, index + 8), 37) * mul; y = Utilities.RotateWithCheck(y ^ v.High ^ Utilities.Fetch64(s, index + 48), 42) * mul; x ^= w.High * 9; y += v.Low + Utilities.Fetch64(s, index + 40); z = Utilities.RotateWithCheck(z + w.Low, 33) * mul; v = WeakHashLen32WithSeeds(s, index + 0, v.High * mul, x + w.Low); w = WeakHashLen32WithSeeds(s, index + 32, z + w.High, y + Utilities.Fetch64(s, index + 16)); return(H(HashLen16(v.Low + x, w.Low ^ y, mul) + z - u, H(v.High + y, w.High + z, FarmHashConstants.k2, 30) ^ x, FarmHashConstants.k2, 31)); }