예제 #1
0
        private static unsafe ulong Hash64_na(byte *s, uint len)
        {
            const ulong seed = 81;

            // 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 * k1 + 113);
            ulong     z = ShiftMix(y * k2 + 113) * k2;
            uint128_t v = Uint128(0, 0);
            uint128_t w = Uint128(0, 0);

            x = x * k2 + Fetch64(s);

            ulong tmp;

            // Set end so that after the loop we have 1 to 64 bytes left to process.
            byte *end    = s + (len - 1) / 64 * 64;
            byte *last64 = end + ((len - 1) & 63) - 63;

            do
            {
                x  = Rotate64(x + y + v.first + Fetch64(s + 8), 37) * k1;
                y  = Rotate64(y + v.second + Fetch64(s + 48), 42) * k1;
                x ^= w.second;
                y += v.first + Fetch64(s + 40);
                z  = Rotate64(z + w.first, 33) * k1;
                v  = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first);
                w  = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));

                tmp = z;
                z   = x;
                x   = tmp;

                s += 64;
            } while (s != end);

            ulong mul = k1 + ((z & 0xff) << 1);

            // Make s point to the last 64 bytes of input.
            s        = last64;
            w.first += (len - 1) & 63;
            v.first += w.first;
            w.first += v.first;
            x        = Rotate64(x + y + v.first + Fetch64(s + 8), 37) * mul;
            y        = Rotate64(y + v.second + Fetch64(s + 48), 42) * mul;
            x       ^= w.second * 9;
            y       += v.first * 9 + Fetch64(s + 40);
            z        = Rotate64(z + w.first, 33) * mul;
            v        = WeakHashLen32WithSeeds(s, v.second * mul, x + w.first);
            w        = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));

            tmp = z;
            z   = x;
            x   = tmp;

            return(HashLen16(HashLen16(v.first, w.first, mul) + ShiftMix(y) * k0 + z,
                             HashLen16(v.second, w.second, mul) + x,
                             mul));
        }
예제 #2
0
        private static ulong Hash128to64(uint128_t x)
        {
            // Taken from https://github.com/google/farmhash/blob/master/src/farmhash.h

            const ulong kMul = 0x9DDFEA08EB382D69;
            ulong       a    = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;

            a ^= (a >> 47);
            ulong b = (Uint128High64(x) ^ a) * kMul;

            b ^= (b >> 47);
            b *= kMul;
            return(b);
        }
예제 #3
0
        private static unsafe uint128_t CityMurmur(byte *s, uint len, uint128_t seed)
        {
            // Taken from https://github.com/google/farmhash/blob/master/src/farmhash.cc

            ulong a = Uint128Low64(seed);
            ulong b = Uint128High64(seed);
            ulong c = 0;
            ulong d = 0;
            long  l = len - 16;

            if (l <= 0)
            {              // len <= 16
                a = ShiftMix(a * K1) * K1;
                c = b * K1 + HashLen0to16(s, len);
                d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c));
            }
            else
            {              // len > 16
                c  = HashLen16(Fetch64(s + len - 8) + K1, a);
                d  = HashLen16(b + len, c + Fetch64(s + len - 16));
                a += d;
                do
                {
                    a ^= ShiftMix(Fetch64(s) * K1) * K1;
                    a *= K1;
                    b ^= a;
                    c ^= ShiftMix(Fetch64(s + 8) * K1) * K1;
                    c *= K1;
                    d ^= c;
                    s += 16;
                    l -= 16;
                } while (l > 0);
            }
            a = HashLen16(a, c);
            b = HashLen16(d, b);
            return(Uint128(a ^ b, HashLen16(b, a)));
        }
예제 #4
0
        private static unsafe uint128_t CityHash128WithSeed(byte *s, uint len, uint128_t seed)
        {
            // Taken from https://github.com/google/farmhash/blob/master/src/farmhash.cc

            if (len < 128)
            {
                return(CityMurmur(s, len, seed));
            }

            ulong tmp_x;

            // We expect len >= 128 to be the common case.  Keep 56 bytes of state:
            // v, w, x, y, and z.
            uint128_t v = new uint128_t(0, 0);
            uint128_t w = new uint128_t(0, 0);
            ulong     x = Uint128Low64(seed);
            ulong     y = Uint128High64(seed);
            ulong     z = len * K1;

            v.first  = Rotate64(y ^ K1, 49) * K1 + Fetch64(s);
            v.second = Rotate64(v.first, 42) * K1 + Fetch64(s + 8);
            w.first  = Rotate64(y + z, 35) * K1 + x;
            w.second = Rotate64(x + Fetch64(s + 88), 53) * K1;

            // This is the same inner loop as CityHash64(), manually unrolled.
            do
            {
                x  = Rotate64(x + y + v.first + Fetch64(s + 8), 37) * K1;
                y  = Rotate64(y + v.second + Fetch64(s + 48), 42) * K1;
                x ^= w.second;
                y += v.first + Fetch64(s + 40);
                z  = Rotate64(z + w.first, 33) * K1;
                v  = WeakHashLen32WithSeeds(s, v.second * K1, x + w.first);
                w  = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));

                tmp_x = x;
                x     = z;
                z     = tmp_x;

                s += 64;
                x  = Rotate64(x + y + v.first + Fetch64(s + 8), 37) * K1;
                y  = Rotate64(y + v.second + Fetch64(s + 48), 42) * K1;
                x ^= w.second;
                y += v.first + Fetch64(s + 40);
                z  = Rotate64(z + w.first, 33) * K1;
                v  = WeakHashLen32WithSeeds(s, v.second * K1, x + w.first);
                w  = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));

                tmp_x = x;
                x     = z;
                z     = tmp_x;

                s   += 64;
                len -= 128;
            } while (len >= 128);
            x       += Rotate64(v.first + z, 49) * K0;
            y        = y * K0 + Rotate64(w.second, 37);
            z        = z * K0 + Rotate64(w.first, 27);
            w.first *= 9;
            v.first *= K0;

            // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
            for (uint tail_done = 0; tail_done < len;)
            {
                tail_done += 32;
                y          = Rotate64(x + y, 42) * K0 + v.second;
                w.first   += Fetch64(s + len - tail_done + 16);
                x          = x * K0 + w.first;
                z         += w.second + Fetch64(s + len - tail_done);
                w.second  += v.first;
                v          = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second);
                v.first   *= K0;
            }
            // At this point our 56 bytes of state should contain more than
            // enough information for a strong 128-bit hash.  We use two
            // different 56-byte-to-8-byte hashes to get a 16-byte final result.
            x = HashLen16(x, v.first);
            y = HashLen16(y + z, w.first);
            return(Uint128(HashLen16(x + v.second, w.second) + y, HashLen16(x + w.second, y + v.second)));
        }
예제 #5
0
        public static unsafe byte[] Hash64(byte *s, uint len)
        {
            // Taken from https://github.com/google/farmhash/blob/master/src/farmhash.cc

            const ulong seed = 81;

            ulong tmp_x;

            if (0 <= len && len <= 16)
            {
                return(GetBytes64(HashLen0to16(s, len)));
            }
            else if (17 <= len && len <= 32)
            {
                return(GetBytes64(HashLen17to32(s, len)));
            }
            else if (33 <= len && len <= 64)
            {
                return(GetBytes64(HashLen33to64(s, len)));
            }

            ulong     x = seed;
            ulong     y = unchecked (seed * K1 + 113);
            ulong     z = ShiftMix(y * K2 + 113) * K2;
            uint128_t v = new uint128_t(0, 0);
            uint128_t w = new uint128_t(0, 0);

            x = x * K2 + Fetch64(s);

            byte *end    = s + (len - 1) / 64 * 64;
            byte *last64 = end + ((len - 1) & 63) - 63;

            do
            {
                x  = Rotate64(x + y + v.first + Fetch64(s + 8), 37) * K1;
                y  = Rotate64(y + v.second + Fetch64(s + 48), 42) * K1;
                x ^= w.second;
                y += v.first + Fetch64(s + 40);
                z  = Rotate64(z + w.first, 33) * K1;
                v  = WeakHashLen32WithSeeds(s, v.second * K1, x + w.first);
                w  = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));

                // swap
                tmp_x = x;
                x     = z;
                z     = tmp_x;

                s += 64;
            } while (s != end);

            ulong mul = K1 + ((z & 0xff) << 1);

            // Make s point to the last 64 bytes of input.
            s        = last64;
            w.first += ((len - 1) & 63);
            v.first += w.first;
            w.first += v.first;
            x        = Rotate64(x + y + v.first + Fetch64(s + 8), 37) * mul;
            y        = Rotate64(y + v.second + Fetch64(s + 48), 42) * mul;
            x       ^= w.second * 9;
            y       += v.first * 9 + Fetch64(s + 40);
            z        = Rotate64(z + w.first, 33) * mul;
            v        = WeakHashLen32WithSeeds(s, v.second * mul, x + w.first);
            w        = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16));

            // swap
            tmp_x = x;
            x     = z;
            z     = tmp_x;

            return(GetBytes64(HashLen16(HashLen16(v.first, w.first, mul) + ShiftMix(y) * K0 + z, HashLen16(v.second, w.second, mul) + x, mul)));
        }
예제 #6
0
 private static ulong Uint128High64(uint128_t x) => x.second;
예제 #7
0
 private static ulong Uint128Low64(uint128_t x) => x.first;
예제 #8
0
        private static unsafe ulong Hash64_uo(byte *s, uint len)
        {
            const ulong seed0 = 81;
            const ulong seed1 = 0;

            // 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 * k2 + 113;
            ulong z = ShiftMix(y * k2) * k2;

            // v and w used to be uint128_t(seed0, seed1), uint128_t(0, 0), but
            // using only primitives meant a 40% performance increase, hence the
            // deviation with original farmhash algorithm; see commit 380c059
            ulong v_first  = seed0;
            ulong v_second = seed1;
            ulong w_first  = 0;
            ulong w_second = 0;
            ulong u        = x - z;

            x *= k2;
            ulong mul = k2 + (u & 0x82);

            // Set end so that after the loop we have 1 to 64 bytes left to process.
            byte *end    = s + (len - 1) / 64 * 64;
            byte *last64 = end + ((len - 1) & 63) - 63;

            do
            {
                ulong a0 = Fetch64(s);
                ulong a1 = Fetch64(s + 8);
                ulong a2 = Fetch64(s + 16);
                ulong a3 = Fetch64(s + 24);
                ulong a4 = Fetch64(s + 32);
                ulong a5 = Fetch64(s + 40);
                ulong a6 = Fetch64(s + 48);
                ulong a7 = Fetch64(s + 56);
                x        += a0 + a1;
                y        += a2;
                z        += a3;
                v_first  += a4;
                v_second += a5 + a1;
                w_first  += a6;
                w_second += a7;

                x         = Rotate64(x, 26);
                x        *= 9;
                y         = Rotate64(y, 29);
                z        *= mul;
                v_first   = Rotate64(v_first, 33);
                v_second  = Rotate64(v_second, 30);
                w_first  ^= x;
                w_first  *= 9;
                z         = Rotate64(z, 32);
                z        += w_second;
                w_second += z;
                z        *= 9;

                ulong tmp = u;
                u = y;
                y = tmp;

                z        += a0 + a6;
                v_first  += a2;
                v_second += a3;
                w_first  += a4;
                w_second += a5 + a6;
                x        += a1;
                y        += a7;

                y        += v_first;
                v_first  += x - y;
                v_second += w_first;
                w_first  += v_second;
                w_second += x - y;
                x        += w_second;
                w_second  = Rotate64(w_second, 34);
                tmp       = u;
                u         = z;
                z         = tmp;
                s        += 64;
            } while (s != end);
            // Make s point to the last 64 bytes of input.
            s        = last64;
            u       *= 9;
            v_second = Rotate64(v_second, 28);
            v_first  = Rotate64(v_first, 20);
            w_first += (len - 1) & 63;
            u       += y;
            y       += u;
            x        = Rotate64(y - x + v_first + Fetch64(s + 8), 37) * mul;
            y        = Rotate64(y ^ v_second ^ Fetch64(s + 48), 42) * mul;
            x       ^= w_second * 9;
            y       += v_first + Fetch64(s + 40);
            z        = Rotate64(z + w_first, 33) * mul;
            uint128_t v = WeakHashLen32WithSeeds(s, v_second * mul, x + w_first);
            uint128_t w = WeakHashLen32WithSeeds(s + 32, z + w_second, y + Fetch64(s + 16));

            return(H(HashLen16(v.first + x, w.first ^ y, mul) + z - u,
                     H(v.second + y, w.second + z, k2, 30) ^ x,
                     k2,
                     31));
        }
예제 #9
0
        private static ulong Hash64_na(ReadOnlySpan <byte> s, uint len)
        {
            const ulong seed = 81;

            // 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 * k1 + 113);
            ulong     z = ShiftMix(y * k2 + 113) * k2;
            uint128_t v = UInt128(0, 0);
            uint128_t w = UInt128(0, 0);

            x = x * k2 + Fetch64(s);

            ulong tmp;

            // Set end so that after the loop we have 1 to 64 bytes left to process.
            uint end     = (len - 1) / 64 * 64;
            uint last64  = end + ((len - 1) & 63) - 63;
            uint s_index = 0;

            do
            {
                x  = Rotate64(x + y + v.first + Fetch64(s.Slice((int)(8 + s_index))), 37) * k1;
                y  = Rotate64(y + v.second + Fetch64(s.Slice((int)(48 + s_index))), 42) * k1;
                x ^= w.second;
                y += v.first + Fetch64(s.Slice((int)(40 + s_index)));
                z  = Rotate64(z + w.first, 33) * k1;
                v  = WeakHashLen32WithSeeds(s.Slice((int)(s_index)), v.second * k1, x + w.first);
                w  = WeakHashLen32WithSeeds(s.Slice((int)(32 + s_index)), z + w.second, y + Fetch64(s.Slice((int)(16 + s_index))));

                tmp = z;
                z   = x;
                x   = tmp;

                s_index += 64;
            } while (s_index != end);

            ulong mul = k1 + ((z & 0xff) << 1);

            // Make s point to the last 64 bytes of input.
            s_index  = last64;
            w.first += (len - 1) & 63;
            v.first += w.first;
            w.first += v.first;
            x        = Rotate64(x + y + v.first + Fetch64(s.Slice((int)(8 + s_index))), 37) * mul;
            y        = Rotate64(y + v.second + Fetch64(s.Slice((int)(48 + s_index))), 42) * mul;
            x       ^= w.second * 9;
            y       += v.first * 9 + Fetch64(s.Slice((int)(40 + s_index)));
            z        = Rotate64(z + w.first, 33) * mul;
            v        = WeakHashLen32WithSeeds(s.Slice((int)(s_index)), v.second * mul, x + w.first);
            w        = WeakHashLen32WithSeeds(s.Slice((int)(32 + s_index)), z + w.second, y + Fetch64(s.Slice((int)(16 + s_index))));

            tmp = z;
            z   = x;
            x   = tmp;

            return(HashLen16(HashLen16(v.first, w.first, mul) + ShiftMix(y) * k0 + z,
                             HashLen16(v.second, w.second, mul) + x,
                             mul));
        }