Skip to content

Commit ddc4c75

Browse files
leecampbell-codeagentLeeCampbell
authored andcommitted
feat(#161): implement tasks
1 parent 43b4cdb commit ddc4c75

8 files changed

Lines changed: 63 additions & 131 deletions

File tree

HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ public void OneOffValidationOfImplementations()
5353
var functions = new Dictionary<string, Func<long, int>>
5454
{
5555
{"CurrentImpl", Bitwise.NumberOfLeadingZeros},
56-
{"Imperative", Bitwise.Imperative.NumberOfLeadingZeros},
5756
{"IfAndShift", LeadingZeroCount.IfAndShift.GetLeadingZeroCount},
5857
//{"MathLog", LeadingZeroCount.MathLog.GetLeadingZeroCount},
5958
{"StringManipulation", LeadingZeroCount.StringManipulation.GetLeadingZeroCount},
@@ -121,17 +120,6 @@ public int CurrentImplementation()
121120
return sum;
122121
}
123122

124-
[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
125-
public int ImperativeImplementation()
126-
{
127-
var sum = 0;
128-
for (int i = 0; i < _testValues.Length; i++)
129-
{
130-
sum += Bitwise.Imperative.NumberOfLeadingZeros(_testValues[i]);
131-
}
132-
return sum;
133-
}
134-
135123
[Benchmark(OperationsPerInvoke = TEST_VALUE_LENGTH)]
136124
public int IfAndShift()
137125
{
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* This is a .NET port of the original Java version, which was written by
3+
* Gil Tene as described in
4+
* https://github.com/HdrHistogram/HdrHistogram
5+
* and released to the public domain, as explained at
6+
* http://creativecommons.org/publicdomain/zero/1.0/
7+
*/
8+
9+
using HdrHistogram.Utilities;
10+
using Xunit;
11+
12+
namespace HdrHistogram.UnitTests.Utilities
13+
{
14+
public class BitwiseTests
15+
{
16+
[Theory]
17+
[InlineData(0L, 64)]
18+
[InlineData(1L, 63)]
19+
[InlineData(2L, 62)]
20+
[InlineData(4L, 61)]
21+
[InlineData(8L, 60)]
22+
[InlineData(16L, 59)]
23+
[InlineData(32L, 58)]
24+
[InlineData(64L, 57)]
25+
[InlineData(128L, 56)]
26+
[InlineData(256L, 55)]
27+
[InlineData(512L, 54)]
28+
[InlineData(1024L, 53)]
29+
[InlineData(2048L, 52)]
30+
[InlineData(4096L, 51)]
31+
[InlineData(8192L, 50)]
32+
[InlineData(16384L, 49)]
33+
[InlineData(32768L, 48)]
34+
[InlineData(65536L, 47)]
35+
[InlineData(1L << 30, 33)]
36+
[InlineData(1L << 31, 32)]
37+
[InlineData(1L << 32, 31)]
38+
[InlineData(1L << 62, 1)]
39+
[InlineData(long.MaxValue, 1)]
40+
public void NumberOfLeadingZeros_ReturnsCorrectValue(long value, int expected)
41+
{
42+
Assert.Equal(expected, Bitwise.NumberOfLeadingZeros(value));
43+
}
44+
}
45+
}

HdrHistogram/HdrHistogram.csproj

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>
4+
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
55
<Description>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.</Description>
66
<Authors>Gil Tene, Lee Campbell</Authors>
77
<PackageReleaseNotes>Net 8.0 release</PackageReleaseNotes>
@@ -21,21 +21,8 @@
2121
<None Include="../README.md" Pack="true" PackagePath="" />
2222
</ItemGroup>
2323

24-
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
25-
<DocumentationFile>bin\Release\net8.0\HdrHistogram.xml</DocumentationFile>
24+
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
25+
<DocumentationFile>bin\Release\$(TargetFramework)\HdrHistogram.xml</DocumentationFile>
2626
</PropertyGroup>
2727

28-
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net9.0|AnyCPU'">
29-
<DocumentationFile>bin\Release\net9.0\HdrHistogram.xml</DocumentationFile>
30-
</PropertyGroup>
31-
32-
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net10.0|AnyCPU'">
33-
<DocumentationFile>bin\Release\net10.0\HdrHistogram.xml</DocumentationFile>
34-
</PropertyGroup>
35-
36-
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netstandard2.0|AnyCPU'">
37-
<DocumentationFile>bin\Release\netstandard2.0\HdrHistogram.xml</DocumentationFile>
38-
<DefineConstants>RELEASE;NETSTANDARD2_0</DefineConstants>
39-
</PropertyGroup>
40-
41-
</Project>
28+
</Project>

HdrHistogram/HistogramLogReader.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,11 +240,7 @@ private IEnumerable<string> ReadLines()
240240

241241
private static bool IsComment(string line)
242242
{
243-
#if NETSTANDARD2_0
244-
return line.StartsWith("#", StringComparison.Ordinal);
245-
#else
246243
return line.StartsWith('#');
247-
#endif
248244
}
249245

250246
private static bool IsStartTime(string line)

HdrHistogram/Utilities/Bitwise.cs

Lines changed: 1 addition & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -22,90 +22,7 @@ public static class Bitwise
2222
/// <returns>The number of leading zeros.</returns>
2323
public static int NumberOfLeadingZeros(long value)
2424
{
25-
#if NET5_0_OR_GREATER
26-
return IntrinsicNumberOfLeadingZeros(value);
27-
#else
28-
return Imperative.NumberOfLeadingZeros(value);
29-
#endif
30-
}
31-
32-
#if NET5_0_OR_GREATER
33-
/// <summary>
34-
/// Returns the Leading Zero Count (lzc) of the <paramref name="value"/> for its binary representation.
35-
/// </summary>
36-
/// <param name="value">The value to find the number of leading zeros</param>
37-
/// <returns>The number of leading zeros.</returns>
38-
private static int IntrinsicNumberOfLeadingZeros(long value)
39-
{
40-
ulong testValue = (ulong)value;
41-
return System.Numerics.BitOperations.LeadingZeroCount(testValue);
42-
43-
}
44-
#endif
45-
46-
//Code has been tested and taken from :
47-
//http://stackoverflow.com/questions/9543410/i-dont-think-numberofleadingzeroslong-i-in-long-java-is-based-floorlog2x/9543537#9543537
48-
//http://stackoverflow.com/questions/21888140/de-bruijn-algorithm-binary-digit-count-64bits-c-sharp/21888542#21888542
49-
//http://stackoverflow.com/questions/15967240/fastest-implementation-of-log2int-and-log2float
50-
//http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
51-
52-
/// <summary>
53-
/// Imperative implementation of the LeadingZeroCount, when access to the <c>System.Numerics.BitOperations.LeadingZeroCount(ulong)</c> is not available.
54-
/// </summary>
55-
public static class Imperative
56-
{
57-
private static readonly int[] Lookup;
58-
59-
static Imperative()
60-
{
61-
Lookup = new int[256];
62-
for (int i = 1; i < 256; ++i)
63-
{
64-
Lookup[i] = (int)(Math.Log(i) / Math.Log(2));
65-
}
66-
}
67-
68-
/// <summary>
69-
/// Returns the Leading Zero Count (lzc) of the <paramref name="value"/> for its binary representation.
70-
/// </summary>
71-
/// <param name="value">The value to find the number of leading zeros</param>
72-
/// <returns>The number of leading zeros.</returns>
73-
public static int NumberOfLeadingZeros(long value)
74-
{
75-
//Optimisation for 32 bit values. So values under 00:16:41.0 when measuring with Stopwatch.GetTimestamp()*, we will hit a fast path.
76-
// * as at writing on Win10 .NET 4.6
77-
if (value < int.MaxValue)
78-
return 63 - Log2((int)value);
79-
return NumberOfLeadingZerosLong(value);
80-
}
81-
82-
private static int NumberOfLeadingZerosLong(long value)
83-
{
84-
// Code from http://stackoverflow.com/questions/9543410/i-dont-think-numberofleadingzeroslong-i-in-long-java-is-based-floorlog2x/9543537#9543537
85-
86-
//--Already checked that values here are over int.MaxValue, i.e. !=0
87-
// HD, Figure 5-6
88-
//if (value == 0)
89-
// return 64;
90-
var n = 1;
91-
// >>> in Java is a "unsigned bit shift", to do the same in C# we use >> (but it HAS to be an unsigned int)
92-
var x = (uint)(value >> 32);
93-
if (x == 0) { n += 32; x = (uint)value; }
94-
if (x >> 16 == 0) { n += 16; x <<= 16; }
95-
if (x >> 24 == 0) { n += 8; x <<= 8; }
96-
if (x >> 28 == 0) { n += 4; x <<= 4; }
97-
if (x >> 30 == 0) { n += 2; x <<= 2; }
98-
n -= (int)(x >> 31);
99-
return n;
100-
}
101-
102-
private static int Log2(int i)
103-
{
104-
if (i >= 0x1000000) { return Lookup[i >> 24] + 24; }
105-
if (i >= 0x10000) { return Lookup[i >> 16] + 16; }
106-
if (i >= 0x100) { return Lookup[i >> 8] + 8; }
107-
return Lookup[i];
108-
}
25+
return System.Numerics.BitOperations.LeadingZeroCount((ulong)value);
10926
}
11027
}
11128
}
File renamed without changes.
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,51 +2,51 @@
22

33
## Implementation Changes
44

5-
- [ ] **`HdrHistogram/HdrHistogram.csproj` line 4** — Remove `netstandard2.0` from `<TargetFrameworks>`, leaving `net10.0;net9.0;net8.0`.
5+
- [x] **`HdrHistogram/HdrHistogram.csproj` line 4** — Remove `netstandard2.0` from `<TargetFrameworks>`, leaving `net10.0;net9.0;net8.0`.
66
- **Why:** Drops the legacy target entirely.
77
- **Verify:** `<TargetFrameworks>` value contains no `netstandard2.0` token.
88

9-
- [ ] **`HdrHistogram/HdrHistogram.csproj` lines 24–34** — Collapse the three per-framework Release `PropertyGroup` blocks (one each for `net8.0`, `net9.0`, `net10.0`) into a single `PropertyGroup Condition="'$(Configuration)' == 'Release'"` block with a single `<DocumentationFile>` element that resolves via `$(TargetFramework)`.
9+
- [x] **`HdrHistogram/HdrHistogram.csproj` lines 24–34** — Collapse the three per-framework Release `PropertyGroup` blocks (one each for `net8.0`, `net9.0`, `net10.0`) into a single `PropertyGroup Condition="'$(Configuration)' == 'Release'"` block with a single `<DocumentationFile>` element that resolves via `$(TargetFramework)`.
1010
- **Why:** Eliminates duplicated XML and the framework-specific condition strings.
1111
- **Verify:** Only one Release `PropertyGroup` exists; it contains no `$(TargetFramework)` literals in the condition string.
1212

13-
- [ ] **`HdrHistogram/HdrHistogram.csproj` lines 36–39** — Delete the `netstandard2.0` `PropertyGroup` block (the one setting `DefineConstants` to `RELEASE;NETSTANDARD2_0`).
13+
- [x] **`HdrHistogram/HdrHistogram.csproj` lines 36–39** — Delete the `netstandard2.0` `PropertyGroup` block (the one setting `DefineConstants` to `RELEASE;NETSTANDARD2_0`).
1414
- **Why:** The constant `NETSTANDARD2_0` is no longer needed once the target is removed.
1515
- **Verify:** No `PropertyGroup` referencing `netstandard2.0` or `NETSTANDARD2_0` remains in the file.
1616

17-
- [ ] **`HdrHistogram/Utilities/Bitwise.cs` lines 23–44** — Simplify `NumberOfLeadingZeros(long)` to call `System.Numerics.BitOperations.LeadingZeroCount((ulong)value)` directly; remove the `#if NET5_0_OR_GREATER` / `#else` / `#endif` guards and delete the private `IntrinsicNumberOfLeadingZeros` helper.
17+
- [x] **`HdrHistogram/Utilities/Bitwise.cs` lines 23–44** — Simplify `NumberOfLeadingZeros(long)` to call `System.Numerics.BitOperations.LeadingZeroCount((ulong)value)` directly; remove the `#if NET5_0_OR_GREATER` / `#else` / `#endif` guards and delete the private `IntrinsicNumberOfLeadingZeros` helper.
1818
- **Why:** All supported targets (net8.0+) provide `BitOperations.LeadingZeroCount`; the conditional dispatch is dead code.
1919
- **Verify:** `NumberOfLeadingZeros` body is a single `return System.Numerics.BitOperations.LeadingZeroCount((ulong)value);` statement; no `#if` directives remain in the method or immediately around it.
2020

21-
- [ ] **`HdrHistogram/Utilities/Bitwise.cs` lines 55–109** — Delete the entire `Bitwise.Imperative` nested public static class (including the `Lookup` table, `NumberOfLeadingZeros`, `NumberOfLeadingZerosLong`, and `Log2` methods).
21+
- [x] **`HdrHistogram/Utilities/Bitwise.cs` lines 55–109** — Delete the entire `Bitwise.Imperative` nested public static class (including the `Lookup` table, `NumberOfLeadingZeros`, `NumberOfLeadingZerosLong`, and `Log2` methods).
2222
- **Why:** The imperative fallback path is unreachable on net8.0+; removing it eliminates dead code and the public surface that the benchmark references.
2323
- **Verify:** No `class Imperative` or `Bitwise.Imperative` identifier exists anywhere in the solution.
2424

25-
- [ ] **`HdrHistogram/HistogramLogReader.cs` lines 241–248** — Remove the `#if NETSTANDARD2_0` / `#else` / `#endif` block inside `IsComment(string line)`, keeping only `return line.StartsWith('#');`.
25+
- [x] **`HdrHistogram/HistogramLogReader.cs` lines 241–248** — Remove the `#if NETSTANDARD2_0` / `#else` / `#endif` block inside `IsComment(string line)`, keeping only `return line.StartsWith('#');`.
2626
- **Why:** The `char` overload of `StartsWith` is available on all net8.0+ targets; the string-overload fallback is dead code.
2727
- **Verify:** `IsComment` contains no `#if` directives; the method body is `return line.StartsWith('#');`.
2828

29-
- [ ] **`HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs`** — Remove the `"Imperative"` entry from the validation dictionary (line 56) and delete the `ImperativeImplementation()` benchmark method (lines 124–133).
29+
- [x] **`HdrHistogram.Benchmarking/LeadingZeroCount/LeadingZeroCountBenchmarkBase.cs`** — Remove the `"Imperative"` entry from the validation dictionary (line 56) and delete the `ImperativeImplementation()` benchmark method (lines 124–133).
3030
- **Why:** Both reference `Bitwise.Imperative` which will no longer exist; leaving them causes a compile error.
3131
- **Verify:** `dotnet build HdrHistogram.Benchmarking/ -c Release` exits with code 0; no reference to `Bitwise.Imperative` remains in the file.
3232

3333
## Unit Tests
3434

35-
- [ ] **`HdrHistogram.UnitTests/`** — Add a focused unit test class `BitwiseTests` (e.g. `HdrHistogram.UnitTests/Utilities/BitwiseTests.cs`) that asserts `Bitwise.NumberOfLeadingZeros` returns correct results for representative inputs: `0`, `1`, `2`, powers of two up to 2⁶², and `long.MaxValue`.
35+
- [x] **`HdrHistogram.UnitTests/`** — Add a focused unit test class `BitwiseTests` (e.g. `HdrHistogram.UnitTests/Utilities/BitwiseTests.cs`) that asserts `Bitwise.NumberOfLeadingZeros` returns correct results for representative inputs: `0`, `1`, `2`, powers of two up to 2⁶², and `long.MaxValue`.
3636
- **Why:** No existing test directly covers `Bitwise`; this provides a regression anchor if the method is ever touched again.
3737
- **Verify:** Test class exists; `dotnet test -c Release` reports the new tests as passing on all three target frameworks.
3838

39-
- [ ] **Run the full unit-test suite** — Execute `dotnet test -c Release` across all three target frameworks (net8.0, net9.0, net10.0).
39+
- [x] **Run the full unit-test suite** — Execute `dotnet test -c Release` across all three target frameworks (net8.0, net9.0, net10.0).
4040
- **Why:** Confirms that removing the netstandard2.0 conditional paths has not broken any indirect consumer of `Bitwise` or `HistogramLogReader`.
4141
- **Verify:** Zero test failures; zero skipped tests that were previously passing.
4242

4343
## Documentation
4444

45-
- [ ] **`spec/tech-standards/build-system.md` line 25** — Remove `netstandard2.0` from the `<TargetFrameworks>` code block example.
45+
- [x] **`spec/tech-standards/build-system.md` line 25** — Remove `netstandard2.0` from the `<TargetFrameworks>` code block example.
4646
- **Why:** The spec must reflect the actual supported targets.
4747
- **Verify:** The code block contains only `net10.0;net9.0;net8.0`.
4848

49-
- [ ] **`spec/tech-standards/build-system.md` line 33** — Delete the `| \`netstandard2.0\` | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+) |` row from the target table.
49+
- [x] **`spec/tech-standards/build-system.md` line 33** — Delete the `| \`netstandard2.0\` | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+) |` row from the target table.
5050
- **Why:** The target no longer exists; the row is misleading.
5151
- **Verify:** No mention of `netstandard2.0` remains anywhere in `build-system.md`.
5252

spec/tech-standards/build-system.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,14 @@ HdrHistogram.sln
2222
### Main Library (HdrHistogram.csproj)
2323

2424
```xml
25-
<TargetFrameworks>net10.0;net9.0;net8.0;netstandard2.0</TargetFrameworks>
25+
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
2626
```
2727

2828
| Target | Description |
2929
|--------|-------------|
3030
| `net10.0` | Modern .NET (current LTS target) |
3131
| `net9.0` | Modern .NET (STS target) |
3232
| `net8.0` | Modern .NET (LTS target) |
33-
| `netstandard2.0` | Broad compatibility (.NET Framework 4.6.1+, .NET Core 2.0+) |
3433

3534
### Test Project
3635

0 commit comments

Comments
 (0)