| File: FowlerNollVo1aHash.cs | Web Access |
| Project: src\msbuild\src\StringTools\StringTools.csproj (Microsoft.NET.StringTools) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace Microsoft.NET.StringTools { /// <summary> /// Fowler/Noll/Vo hashing. /// </summary> public static class FowlerNollVo1aHash { // Fowler/Noll/Vo hashing. // http://www.isthe.com/chongo/tech/comp/fnv/ // https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash // http://www.isthe.com/chongo/src/fnv/hash_32a.c // 32 bit FNV prime and offset basis for FNV-1a. private const uint fnvPrimeA32Bit = 16777619; private const uint fnvOffsetBasisA32Bit = 2166136261; // 64 bit FNV prime and offset basis for FNV-1a. private const long fnvPrimeA64Bit = 1099511628211; private const long fnvOffsetBasisA64Bit = unchecked((long)14695981039346656037); /// <summary> /// Computes 32 bit Fowler/Noll/Vo-1a hash of a string (regardless of encoding). /// </summary> /// <param name="text">String to be hashed.</param> /// <returns>32 bit signed hash</returns> public static int ComputeHash32(string text) { uint hash = fnvOffsetBasisA32Bit; unchecked { for (int i = 0; i < text.Length; i++) { char ch = text[i]; byte b = (byte)ch; hash ^= b; hash *= fnvPrimeA32Bit; b = (byte)(ch >> 8); hash ^= b; hash *= fnvPrimeA32Bit; } } return unchecked((int)hash); } /// <summary> /// Computes 32 bit Fowler/Noll/Vo-1a inspired hash of a string. /// The hashing algorithm process the data by the whole 16bit chars, instead of by bytes. /// this speeds up the hashing process almost by 2x, while not significantly increasing collisions rate. /// Analysis: https://github.com/KirillOsenkov/MSBuildStructuredLog/wiki/String-Hashing#faster-fnv-1a /// </summary> /// <param name="text">String to be hashed.</param> /// <returns>32 bit unsigned hash</returns> public static int ComputeHash32Fast(string text) { uint hash = fnvOffsetBasisA32Bit; unchecked { for (int i = 0; i < text.Length; i++) { char ch = text[i]; hash = (hash ^ ch) * fnvPrimeA32Bit; } } return unchecked((int)hash); } /// <summary> /// Computes 64 bit Fowler/Noll/Vo-1a inspired hash of a string. /// The hashing algorithm process the data by the whole 16bit chars, instead of by bytes. /// this speeds up the hashing process almost by 2x, while not significantly increasing collisions rate. /// Analysis: https://github.com/KirillOsenkov/MSBuildStructuredLog/wiki/String-Hashing#faster-fnv-1a /// </summary> /// <param name="text">String to be hashed.</param> /// <returns>64 bit unsigned hash</returns> public static long ComputeHash64Fast(string text) { long hash = fnvOffsetBasisA64Bit; unchecked { for (int i = 0; i < text.Length; i++) { char ch = text[i]; hash = (hash ^ ch) * fnvPrimeA64Bit; } } return hash; } /// <summary> /// Computes 64 bit Fowler/Noll/Vo-1a hash of a string (regardless of encoding). /// </summary> /// <param name="text">String to be hashed.</param> /// <returns>64 bit unsigned hash</returns> public static long ComputeHash64(string text) { long hash = fnvOffsetBasisA64Bit; unchecked { for (int i = 0; i < text.Length; i++) { char ch = text[i]; byte b = (byte)ch; hash ^= b; hash *= fnvPrimeA64Bit; b = (byte)(ch >> 8); hash ^= b; hash *= fnvPrimeA64Bit; } } return hash; } /// <summary> /// Combines two 64 bit hashes generated by <see cref="FowlerNollVo1aHash"/> class into one. /// </summary> /// <param name="left">First hash value to be combined.</param> /// <param name="right">Second hash value to be combined.</param> /// <returns></returns> public static long Combine64(long left, long right) { unchecked { return (left ^ right) * fnvPrimeA64Bit; } } } }