Exemplo n.º 1
0
        // Hash 128 input bits down to 64 bits of output.
        // This is intended to be a reasonably good hash function.
        private static ulong Hash128To64(Uint128 x)
        {
            // Murmur-inspired hashing.
            const ulong kMul = 0x9ddfea08eb382d69UL;
            var         a    = (x.First ^ x.Second) * kMul;

            a ^= a >> 47;
            var b = (x.Second ^ a) * kMul;

            b ^= b >> 47;
            b *= kMul;
            return(b);
        }
Exemplo n.º 2
0
        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));
        }
Exemplo n.º 3
0
        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));
        }