예제 #1
0
파일: CityHash.cs 프로젝트: leiwcq/E
        /// <summary>
        /// Computes the 128-bit city hash and are tuned for strings of at least a few hundred bytes using
        /// the specified <paramref name="seed"/> starting at a <paramref name="offset"/> position.
        /// </summary>
        /// <param name="value">The encoded string.</param>
        /// <param name="seed">The seed used by the hash alrorithm.</param>
        /// <param name="offset">The offset position in the byte array.</param>
        /// <returns>The 128-bit city hash.</returns>
        /// <remarks>
        /// The city hash is designed to compute hash for STRINGs only!
        /// The city hash "works" with other types of data, but keep in mind it was not built for it.
        /// </remarks>
        protected static UInt128 CityHash128(byte[] value, UInt128 seed, int offset)
        {
            if (value.Length - offset < 128)
            {
                return(CityMurmur(value, seed, offset));
            }

            // We expect len >= 128 to be the common case.  Keep 56 bytes of state:
            // v, w, x, y, and z.
            var len = value.Length - offset;
            var x   = seed.Low;
            var y   = seed.High;
            var z   = (ulong)len * K1;
            var v   = new UInt128
            {
                Low = Rotate(seed.High ^ K1, 49) * K1 + Fetch64(value, offset)
            };

            v.High = Rotate(v.Low, 42) * K1 + Fetch64(value, offset + 8);

            var w = new UInt128
            {
                Low  = Rotate(y + z, 35) * K1 + x,
                High = Rotate(seed.Low + Fetch64(value, offset + 88), 53) * K1
            };


            // This is the same inner loop as CityHash64(), manually unrolled.
            var s = offset;

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

                Swap(ref z, ref x);

                s += 64;

                x  = Rotate(x + y + v.Low + Fetch64(value, s + 8), 37) * K1;
                y  = Rotate(y + v.High + Fetch64(value, s + 48), 42) * K1;
                x ^= w.High;
                y += v.Low + Fetch64(value, s + 40);
                z  = Rotate(z + w.Low, 33) * K1;
                v  = WeakHashLen32WithSeeds(value, s, v.High * K1, x + w.Low);
                w  = WeakHashLen32WithSeeds(value, s + 32, z + w.High, y + Fetch64(value, s + 16));

                Swap(ref z, ref x);

                s   += 64;
                len -= 128;
            } while (len >= 128);

            x     += Rotate(v.Low + z, 49) * K0;
            y      = y * K0 + Rotate(w.High, 37);
            z      = z * K0 + Rotate(w.Low, 27);
            w.Low *= 9;
            v.Low *= K0;

            // If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end of s.
            for (var tail = 0; tail < len;)
            {
                tail += 32;

                y       = Rotate(x + y, 42) * K0 + v.High;
                w.Low  += Fetch64(value, s + len - tail + 16);
                x       = x * K0 + w.Low;
                z      += w.High + Fetch64(value, s + len - tail);
                w.High += v.Low;
                v       = WeakHashLen32WithSeeds(value, s + len - tail, v.Low + z, v.High);
                v.Low  *= 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.Low);
            y = HashLen16(y + z, w.Low);

            return(new UInt128
            {
                Low = HashLen16(x + v.High, w.High) + y,
                High = HashLen16(x + w.High, y + v.High)
            });
        }
예제 #2
0
파일: CityHash.cs 프로젝트: leiwcq/E
 /// <summary>
 /// Computes the 128-bit city hash and are tuned for strings of at least a few hundred bytes using
 /// the specified <paramref name="seed"/>.
 /// </summary>
 /// <param name="value">The string value.</param>
 /// <param name="seed">The seed used by the city hash algorithm.</param>
 /// <returns>The 128-bit city hash.</returns>
 /// <remarks>This function encodes the string using the unicode block (ISO/IEC 8859-1).</remarks>
 public static UInt128 CityHash128(string value, UInt128 seed)
 {
     return(CityHash128(Encoding.GetEncoding("ISO-8859-1").GetBytes(value), seed, 0));
 }