diff --git a/CardinalityEstimation.Test/CardinalityEstimatorTests.cs b/CardinalityEstimation.Test/CardinalityEstimatorTests.cs index 65f0df4..f20bb83 100644 --- a/CardinalityEstimation.Test/CardinalityEstimatorTests.cs +++ b/CardinalityEstimation.Test/CardinalityEstimatorTests.cs @@ -91,7 +91,7 @@ public void TestCountAdditions() [Fact] public void TestChanged() { - var estimator = new CardinalityEstimator(); + var estimator = new CardinalityEstimator(Murmur3.GetHashCode); Assert.Equal(0UL, estimator.CountAdditions); diff --git a/CardinalityEstimation/CardinalityEstimation.csproj b/CardinalityEstimation/CardinalityEstimation.csproj index 27c71bb..60d67dd 100644 --- a/CardinalityEstimation/CardinalityEstimation.csproj +++ b/CardinalityEstimation/CardinalityEstimation.csproj @@ -1,6 +1,6 @@  - net6.0;net7.0;net8.0 + net8.0;net7.0;net6.0 Debug;Release;Release-Signed true CardinalityEstimation.Signed diff --git a/CardinalityEstimation/CardinalityEstimator.cs b/CardinalityEstimation/CardinalityEstimator.cs index 801ee9e..57a464d 100644 --- a/CardinalityEstimation/CardinalityEstimator.cs +++ b/CardinalityEstimation/CardinalityEstimator.cs @@ -69,7 +69,7 @@ public class CardinalityEstimator : ICardinalityEstimator, ICardinalityE /// /// Number of bits to compute the HLL estimate on /// - private readonly int bitsForHll; + private readonly byte bitsForHll; /// /// HLL lookup table size @@ -173,7 +173,7 @@ public CardinalityEstimator(CardinalityEstimator other) internal CardinalityEstimator(GetHashCodeDelegate hashFunction, CardinalityEstimatorState state) { bitsPerIndex = state.BitsPerIndex; - bitsForHll = 64 - bitsPerIndex; + bitsForHll = (byte)(64 - bitsPerIndex); m = (int) Math.Pow(2, bitsPerIndex); alphaM = GetAlphaM(m); subAlgorithmSelectionThreshold = GetSubAlgorithmSelectionThreshold(bitsPerIndex); @@ -183,9 +183,9 @@ internal CardinalityEstimator(GetHashCodeDelegate hashFunction, CardinalityEstim if (this.hashFunction == null) { #if NET8_0_OR_GREATER - hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); + this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); #else - hashFunction = Murmur3.GetHashCode; + this.hashFunction = Murmur3.GetHashCode; #endif } @@ -656,8 +656,21 @@ private double GetAlphaM(int m) /// Hash value to calculate the statistic on /// Lowest bit to count from /// The number of leading zeroes in the binary representation of , plus one - internal static byte GetSigma(ulong hash, int bitsToCount) + public static byte GetSigma(ulong hash, byte bitsToCount) { + if (hash == 0) + { + return (byte)(bitsToCount + 1); + } + +#if NET8_0_OR_GREATER + ulong mask = ((1UL << bitsToCount) - 1); + int knownZeros = 64 - bitsToCount; + + var masked = hash & mask; + var leadingZeros = (byte)ulong.LeadingZeroCount(masked); + return (byte)(leadingZeros - knownZeros + 1); +#else byte sigma = 1; for (int i = bitsToCount - 1; i >= 0; --i) { @@ -671,6 +684,7 @@ internal static byte GetSigma(ulong hash, int bitsToCount) } } return sigma; +#endif } /// @@ -692,7 +706,7 @@ private void SwitchToDenseRepresentation() lookupSparse = null; isSparse = false; } - #endregion +#endregion #region IEquatable implementation public bool Equals(CardinalityEstimator other)