diff --git a/CardinalityEstimation/CardinalityEstimation.csproj b/CardinalityEstimation/CardinalityEstimation.csproj index 1870c90..55724b3 100644 --- a/CardinalityEstimation/CardinalityEstimation.csproj +++ b/CardinalityEstimation/CardinalityEstimation.csproj @@ -1,6 +1,7 @@  - net9.0;net8.0 + net9.0;net8.0;netstandard2.0 + latest Debug;Release;Release-Signed true CardinalityEstimation.Signed diff --git a/CardinalityEstimation/CardinalityEstimator.cs b/CardinalityEstimation/CardinalityEstimator.cs index ae526c1..08aa788 100644 --- a/CardinalityEstimation/CardinalityEstimator.cs +++ b/CardinalityEstimation/CardinalityEstimator.cs @@ -27,6 +27,7 @@ namespace CardinalityEstimation { using System; using System.Collections.Generic; + using System.Numerics; using System.Text; using Hash; @@ -214,8 +215,8 @@ internal CardinalityEstimator(GetHashCodeDelegate hashFunction, CardinalityEstim this.hashFunction = hashFunction; if (this.hashFunction == null) { - this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); - this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); + this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); + this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); } else { @@ -237,8 +238,8 @@ internal CardinalityEstimator(GetHashCodeSpanDelegate hashFunctionSpan, Cardinal this.hashFunctionSpan = hashFunctionSpan; if (this.hashFunctionSpan == null) { - this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); - this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); + this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); + this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); } else { @@ -846,7 +847,7 @@ public static byte GetSigma(ulong hash, byte bitsToCount) int knownZeros = 64 - bitsToCount; var masked = hash & mask; - var leadingZeros = (byte)ulong.LeadingZeroCount(masked); + var leadingZeros = (byte)BitOperations.LeadingZeroCount(masked); return (byte)(leadingZeros - knownZeros + 1); } diff --git a/CardinalityEstimation/ConcurrentCardinalityEstimator.cs b/CardinalityEstimation/ConcurrentCardinalityEstimator.cs index cb8e985..0893d9a 100644 --- a/CardinalityEstimation/ConcurrentCardinalityEstimator.cs +++ b/CardinalityEstimation/ConcurrentCardinalityEstimator.cs @@ -168,7 +168,7 @@ public ConcurrentCardinalityEstimator(CardinalityEstimator other) lockSlim = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); // Init the hash function - use default since we can't get it from the other estimator - hashFunction = ((x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x))); + hashFunction = ((x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0)); sparseMaxElements = Math.Max(0, (m / 15) - 10); @@ -217,8 +217,8 @@ internal ConcurrentCardinalityEstimator(GetHashCodeDelegate hashFunction, Cardin this.hashFunction = hashFunction; if (this.hashFunction == null) { - this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); - this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); + this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); + this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); } else { @@ -237,8 +237,8 @@ internal ConcurrentCardinalityEstimator(GetHashCodeSpanDelegate hashFunctionSpan this.hashFunctionSpan = hashFunctionSpan; if (this.hashFunction == null) { - this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); - this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x)); + this.hashFunction = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); + this.hashFunctionSpan = (x) => BitConverter.ToUInt64(System.IO.Hashing.XxHash128.Hash(x), 0); } } diff --git a/CardinalityEstimation/Polyfills/BitOperations.cs b/CardinalityEstimation/Polyfills/BitOperations.cs new file mode 100644 index 0000000..cb84892 --- /dev/null +++ b/CardinalityEstimation/Polyfills/BitOperations.cs @@ -0,0 +1,26 @@ +#if !NETCOREAPP3_0_OR_GREATER +namespace System.Numerics; + +internal static class BitOperations +{ + public static uint LeadingZeroCount(ulong x) + { + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x |= x >> 32; + + x -= x >> 1 & 0x5555555555555555; + x = (x >> 2 & 0x3333333333333333) + (x & 0x3333333333333333); + x = (x >> 4) + x & 0x0f0f0f0f0f0f0f0f; + x += x >> 8; + x += x >> 16; + x += x >> 32; + + const int numLongBits = sizeof(long) * 8; + return numLongBits - (uint)(x & 0x0000007f); + } +} +#endif diff --git a/CardinalityEstimation/Polyfills/Linq.cs b/CardinalityEstimation/Polyfills/Linq.cs new file mode 100644 index 0000000..940a7f2 --- /dev/null +++ b/CardinalityEstimation/Polyfills/Linq.cs @@ -0,0 +1,13 @@ +#if !NETCOREAPP2_1_OR_GREATER +using System.Collections.Generic; + +namespace System.Linq; + +internal static class LinqExtensions +{ + public static HashSet ToHashSet(this IEnumerable source) + { + return new(source); + } +} +#endif \ No newline at end of file