56 lines
1.5 KiB
C#
56 lines
1.5 KiB
C#
using System.Runtime.CompilerServices;
|
|
|
|
namespace PerfectNumbers.Core;
|
|
|
|
public struct CycleRemainderStepper(ulong cycleLength)
|
|
{
|
|
public ulong CycleLength = cycleLength;
|
|
private ulong _previousPrime = 0UL;
|
|
private ulong _currentRemainder = 0UL;
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void Reset()
|
|
{
|
|
_previousPrime = 0UL;
|
|
_currentRemainder = 0UL;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public ulong Initialize(ulong prime)
|
|
{
|
|
ulong cycleLength = CycleLength;
|
|
ulong remainder = prime.ReduceCycleRemainder(cycleLength);
|
|
|
|
_previousPrime = prime;
|
|
_currentRemainder = remainder;
|
|
return remainder;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public ulong ComputeNext(ulong prime)
|
|
{
|
|
ulong cycleLength = CycleLength;
|
|
ulong delta = prime - _previousPrime;
|
|
_previousPrime = prime;
|
|
|
|
if (ulong.MaxValue - _currentRemainder < delta)
|
|
{
|
|
UInt128 extended = (UInt128)_currentRemainder + delta;
|
|
_currentRemainder = ((ulong)(extended % cycleLength)).ReduceCycleRemainder(cycleLength);
|
|
return _currentRemainder;
|
|
}
|
|
|
|
_currentRemainder += delta;
|
|
|
|
if (_currentRemainder >= cycleLength)
|
|
{
|
|
_currentRemainder -= cycleLength;
|
|
if (_currentRemainder >= cycleLength)
|
|
{
|
|
_currentRemainder = _currentRemainder.ReduceCycleRemainder(cycleLength);
|
|
}
|
|
}
|
|
return _currentRemainder;
|
|
}
|
|
}
|