-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0b05034
commit b17fea6
Showing
2 changed files
with
64 additions
and
0 deletions.
There are no files selected for viewing
43 changes: 43 additions & 0 deletions
43
src/Nito.Comparers.Core/Internals/CommutativeHashCombiner.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
#pragma warning disable CA1815, CA1721 | ||
|
||
namespace Nito.Comparers.Internals | ||
{ | ||
/// <summary> | ||
/// A hash combiner that is implemented with a simple commutative algorithm. This is a mutable struct for performance reasons. | ||
/// </summary> | ||
public struct CommutativeHashCombiner | ||
{ | ||
private uint _hash; | ||
|
||
/// <summary> | ||
/// Gets the current result of the hash function. | ||
/// </summary> | ||
public int HashCode => unchecked((int) _hash); | ||
|
||
/// <summary> | ||
/// Creates a new hash, starting at <paramref name="seed"/>. | ||
/// </summary> | ||
/// <param name="seed">The seed for the hash. Defaults to the FNV hash offset, for no particular reason.</param> | ||
public static CommutativeHashCombiner Create(int seed = unchecked((int)2166136261)) => new() { _hash = unchecked((uint) seed) }; | ||
|
||
/// <summary> | ||
/// Adds the specified integer to this hash. This operation is commutative. | ||
/// </summary> | ||
/// <param name="data">The integer to hash.</param> | ||
public void Combine(int data) | ||
{ | ||
unchecked | ||
{ | ||
// Simple addition is pretty much the best we can do since this operation must be commutative. | ||
// We also add a constant value to act as a kind of "length counter" in the higher 16 bits. | ||
// The hash combination is free to overflow into the "length counter". | ||
// The higher 16 bits were chosen because that gives a decent distinction for sequences of <64k items while also distinguishing between small integer values (commonly used as ids). | ||
_hash += (uint)data + 65536; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters