Align bit transform comments with original implementation

This commit is contained in:
Marek Lemańczyk committed 2025-10-19 00:54:58 +02:00
1 parent 7f468de485
commit 56c8e84c19
8 files changed
+417 -370

No files matched your search

@@ -0,0 +1,79 @@
using System.Runtime.CompilerServices;
using System.Threading;
using EvenPerfectBitScanner.Candidates;
using Open.Numeric.Primes;
namespace EvenPerfectBitScanner.Candidates.Transforms;
internal static class CandidateAddPrimesTransform
{
private static readonly Optimized PrimeIterator = new();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ulong Transform(ulong value, ref ulong remainder, ref bool limitReached)
{
ulong originalRemainder = remainder;
ulong addRemainder = remainder;
ulong candidate = value;
ulong primeCandidate = value;
bool advanceAdd = true;
bool advancePrime = true;
ulong diff;
ulong nextPrime;
while (true)
{
if (advanceAdd)
{
diff = addRemainder.GetNextAddDiff();
if (candidate > ulong.MaxValue - diff)
{
Volatile.Write(ref limitReached, true);
remainder = originalRemainder;
return candidate;
}
candidate += diff;
addRemainder += diff;
// Skip the Mod6 lookup: benchmarked `%` stays ahead for these prime increments.
// benchmarked fastest remainder updates instead of looping subtraction.
while (addRemainder >= 6UL)
{
addRemainder -= 6UL;
}
}
if (advancePrime)
{
try
{
nextPrime = PrimeIterator.Next(in primeCandidate);
}
catch (InvalidOperationException)
{
Volatile.Write(ref limitReached, true);
remainder = originalRemainder;
return value;
}
if (nextPrime <= primeCandidate)
{
Volatile.Write(ref limitReached, true);
remainder = originalRemainder;
return value;
}
primeCandidate = nextPrime;
}
if (candidate == primeCandidate)
{
remainder = addRemainder;
return candidate;
}
advanceAdd = candidate < primeCandidate;
advancePrime = candidate > primeCandidate;
}
}
}
@@ -0,0 +1,30 @@
using System.Runtime.CompilerServices;
using System.Threading;
using EvenPerfectBitScanner.Candidates;
namespace EvenPerfectBitScanner.Candidates.Transforms;
internal static class CandidateAddTransform
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ulong Transform(ulong value, ref ulong remainder, ref bool limitReached)
{
ulong next = value;
ulong diff = remainder.GetNextAddDiff();
if (next > ulong.MaxValue - diff)
{
Volatile.Write(ref limitReached, true);
return next;
}
remainder += diff;
// Retain direct modulo because the Mod6 helper underperforms on 64-bit operands.
while (remainder >= 6UL)
{
remainder -= 6UL;
}
return next + diff;
}
}
@@ -0,0 +1,51 @@
using System.Runtime.CompilerServices;
using System.Threading;
namespace EvenPerfectBitScanner.Candidates.Transforms;
internal static class CandidateBitTransform
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static ulong Transform(ulong value, ref ulong remainder, ref bool limitReached)
{
ulong original = value;
if (value > (ulong.MaxValue >> 1))
{
Volatile.Write(ref limitReached, true);
return value;
}
ulong next = (value << 1) | 1UL;
remainder = (remainder << 1) + 1UL;
// Mod6 lookup loses to `%` in the benches; stick with subtraction + modulo for correctness and speed.
while (remainder >= 6UL)
{
remainder -= 6UL;
}
value = remainder switch
{
0UL => 1UL,
1UL => 0UL,
2UL => 5UL,
3UL => 4UL,
4UL => 3UL,
_ => 2UL,
}; // 'value' now holds diff
if (next > ulong.MaxValue - value)
{
Volatile.Write(ref limitReached, true);
return original;
}
remainder += value;
// `% 6` remains faster per Mod6ComparisonBenchmarks; keep this modulo fold and continue using subtraction.
while (remainder >= 6UL)
{
remainder -= 6UL;
}
return next + value;
}
}