diff --git a/HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs b/HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs index 23969ca..439a877 100644 --- a/HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs +++ b/HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs @@ -53,7 +53,6 @@ public void OneOffValidationOfImplementations() var functions = new Dictionary> { {"CurrentImpl", Bitwise.NumberOfLeadingZeros}, - {"Imperative", Bitwise.Imperative.NumberOfLeadingZeros}, {"IfAndShift", LeadingZeroCount.IfAndShift.GetLeadingZeroCount}, //{"MathLog", LeadingZeroCount.MathLog.GetLeadingZeroCount}, {"StringManipulation", LeadingZeroCount.StringManipulation.GetLeadingZeroCount}, @@ -121,17 +120,6 @@ public int CurrentImplementation() return sum; } - [Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)] - public int ImperativeImplementation() - { - var sum = 0; - for (int i = 0; i < _testValues.Length; i++) - { - sum += Bitwise.Imperative.NumberOfLeadingZeros(_testValues[i]); - } - return sum; - } - [Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)] public int IfAndShift() { diff --git a/HdrHistogram.UnitTests/Utilities/BitwiseTests.cs b/HdrHistogram.UnitTests/Utilities/BitwiseTests.cs new file mode 100644 index 0000000..dfadecc --- /dev/null +++ b/HdrHistogram.UnitTests/Utilities/BitwiseTests.cs @@ -0,0 +1,45 @@ +/* + * This is a .NET port of the original Java version, which was written by + * Gil Tene as described in + * https://github.com/HdrHistogram/HdrHistogram + * and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +using HdrHistogram.Utilities; +using Xunit; + +namespace HdrHistogram.UnitTests.Utilities +{ + public class BitwiseTests + { + [Theory] + [InlineData(0L, 64)] + [InlineData(1L, 63)] + [InlineData(2L, 62)] + [InlineData(4L, 61)] + [InlineData(8L, 60)] + [InlineData(16L, 59)] + [InlineData(32L, 58)] + [InlineData(64L, 57)] + [InlineData(128L, 56)] + [InlineData(256L, 55)] + [InlineData(512L, 54)] + [InlineData(1024L, 53)] + [InlineData(2048L, 52)] + [InlineData(4096L, 51)] + [InlineData(8192L, 50)] + [InlineData(16384L, 49)] + [InlineData(32768L, 48)] + [InlineData(65536L, 47)] + [InlineData(1L << 30, 33)] + [InlineData(1L << 31, 32)] + [InlineData(1L << 32, 31)] + [InlineData(1L << 62, 1)] + [InlineData(long.MaxValue, 1)] + public void NumberOfLeadingZeros_ReturnsCorrectValue(long value, int expected) + { + Assert.Equal(expected, Bitwise.NumberOfLeadingZeros(value)); + } + } +} diff --git a/HdrHistogram/HdrHistogram.csproj b/HdrHistogram/HdrHistogram.csproj index 26279d1..aae3933 100644 --- a/HdrHistogram/HdrHistogram.csproj +++ b/HdrHistogram/HdrHistogram.csproj @@ -1,7 +1,7 @@ - + - net10.0;net9.0;net8.0;netstandard2.0 + net10.0;net9.0;net8.0 HdrHistogram supports low latency recording and analyzing of sampled data value counts across a configurable integer value range with configurable value precision within the range. Gil Tene, Lee Campbell Net 8.0 release @@ -21,21 +21,8 @@ - - bin\Release\net8.0\HdrHistogram.xml + + bin\Release\$(TargetFramework)\HdrHistogram.xml - - bin\Release\net9.0\HdrHistogram.xml - - - - bin\Release\net10.0\HdrHistogram.xml - - - - bin\Release\netstandard2.0\HdrHistogram.xml - RELEASE;NETSTANDARD2_0 - - - \ No newline at end of file + diff --git a/HdrHistogram/HistogramLogReader.cs b/HdrHistogram/HistogramLogReader.cs index c861b59..000cfef 100644 --- a/HdrHistogram/HistogramLogReader.cs +++ b/HdrHistogram/HistogramLogReader.cs @@ -240,11 +240,7 @@ private IEnumerable ReadLines() private static bool IsComment(string line) { -#if NETSTANDARD2_0 - return line.StartsWith("#", StringComparison.Ordinal); -#else return line.StartsWith('#'); -#endif } private static bool IsStartTime(string line) diff --git a/HdrHistogram/Utilities/Bitwise.cs b/HdrHistogram/Utilities/Bitwise.cs index 9f4782e..fd5431b 100644 --- a/HdrHistogram/Utilities/Bitwise.cs +++ b/HdrHistogram/Utilities/Bitwise.cs @@ -22,90 +22,7 @@ public static class Bitwise /// The number of leading zeros. public static int NumberOfLeadingZeros(long value) { -#if NET5_0_OR_GREATER - return IntrinsicNumberOfLeadingZeros(value); -#else - return Imperative.NumberOfLeadingZeros(value); -#endif - } - -#if NET5_0_OR_GREATER - /// - /// Returns the Leading Zero Count (lzc) of the for its binary representation. - /// - /// The value to find the number of leading zeros - /// The number of leading zeros. - private static int IntrinsicNumberOfLeadingZeros(long value) - { - ulong testValue = (ulong)value; - return System.Numerics.BitOperations.LeadingZeroCount(testValue); - - } -#endif - - //Code has been tested and taken from : - //http://stackoverflow.com/questions/9543410/i-dont-think-numberofleadingzeroslong-i-in-long-java-is-based-floorlog2x/9543537#9543537 - //http://stackoverflow.com/questions/21888140/de-bruijn-algorithm-binary-digit-count-64bits-c-sharp/21888542#21888542 - //http://stackoverflow.com/questions/15967240/fastest-implementation-of-log2int-and-log2float - //http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious - - /// - /// Imperative implementation of the LeadingZeroCount, when access to the System.Numerics.BitOperations.LeadingZeroCount(ulong) is not available. - /// - public static class Imperative - { - private static readonly int[] Lookup; - - static Imperative() - { - Lookup = new int[256]; - for (int i = 1; i < 256; ++i) - { - Lookup[i] = (int)(Math.Log(i) / Math.Log(2)); - } - } - - /// - /// Returns the Leading Zero Count (lzc) of the for its binary representation. - /// - /// The value to find the number of leading zeros - /// The number of leading zeros. - public static int NumberOfLeadingZeros(long value) - { - //Optimisation for 32 bit values. So values under 00:16:41.0 when measuring with Stopwatch.GetTimestamp()*, we will hit a fast path. - // * as at writing on Win10 .NET 4.6 - if (value < int.MaxValue) - return 63 - Log2((int)value); - return NumberOfLeadingZerosLong(value); - } - - private static int NumberOfLeadingZerosLong(long value) - { - // Code from http://stackoverflow.com/questions/9543410/i-dont-think-numberofleadingzeroslong-i-in-long-java-is-based-floorlog2x/9543537#9543537 - - //--Already checked that values here are over int.MaxValue, i.e. !=0 - // HD, Figure 5-6 - //if (value == 0) - // return 64; - var n = 1; - // >>> in Java is a "unsigned bit shift", to do the same in C# we use >> (but it HAS to be an unsigned int) - var x = (uint)(value >> 32); - if (x == 0) { n += 32; x = (uint)value; } - if (x >> 16 == 0) { n += 16; x <<= 16; } - if (x >> 24 == 0) { n += 8; x <<= 8; } - if (x >> 28 == 0) { n += 4; x <<= 4; } - if (x >> 30 == 0) { n += 2; x <<= 2; } - n -= (int)(x >> 31); - return n; - } - - private static int Log2(int i) - { - if (i >= 0x1000000) { return Lookup[i >> 24] + 24; } - if (i >= 0x10000) { return Lookup[i >> 16] + 16; } - if (i >= 0x100) { return Lookup[i >> 8] + 8; } - return Lookup[i]; - } + return System.Numerics.BitOperations.LeadingZeroCount((ulong)value); } } } diff --git a/spec/tech-standards/build-system.md b/spec/tech-standards/build-system.md index 0792541..4a72e25 100644 --- a/spec/tech-standards/build-system.md +++ b/spec/tech-standards/build-system.md @@ -22,7 +22,7 @@ HdrHistogram.sln ### Main Library (HdrHistogram.csproj) ```xml -net10.0;net9.0;net8.0;netstandard2.0 +net10.0;net9.0;net8.0 ``` | Target | Description | @@ -30,7 +30,6 @@ HdrHistogram.sln | `net10.0` | Modern .NET (current LTS target) | | `net9.0` | Modern .NET (STS target) | | `net8.0` | Modern .NET (LTS target) | -| `netstandard2.0` | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+) | ### Test Project