ExponentRemainderStepperCpu local variables optimized. Cache is now driven by manually calculated key to avoid unnecessary allocations.
This commit is contained in:
1 parent
131b3265bc
commit
547d43de84
1 file changed
+31
-26
@@ -16,7 +16,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
private readonly ulong _cycleLength = cycleLength;
|
private readonly ulong _cycleLength = cycleLength;
|
||||||
private ulong PreviousExponent = 0UL;
|
private ulong PreviousExponent = 0UL;
|
||||||
private ulong _currentMontgomery = divisor.MontgomeryOne;
|
private ulong _currentMontgomery = divisor.MontgomeryOne;
|
||||||
private static readonly ConcurrentDictionary<(ulong Cycle, ulong Delta), ulong> _cycleDeltaCache = new();
|
private static readonly ConcurrentDictionary<int, ulong> _cycleDeltaCache = new(20_480, PerfectNumberConstants.MaxQForDivisorCycles);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public readonly bool MatchesDivisor(in MontgomeryDivisorData divisor, ulong cycleLength)
|
public readonly bool MatchesDivisor(in MontgomeryDivisorData divisor, ulong cycleLength)
|
||||||
@@ -68,11 +68,11 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
public ulong ComputeNextCpu(ulong exponent)
|
public ulong ComputeNextCpu(ulong exponent)
|
||||||
{
|
{
|
||||||
ulong delta = exponent - PreviousExponent;
|
ulong delta = exponent - PreviousExponent;
|
||||||
ulong reducedDelta = ReduceDelta(delta);
|
delta = ReduceDelta(delta);
|
||||||
ulong multiplier = reducedDelta == 0UL
|
delta = delta == 0UL
|
||||||
? _montgomeryOne
|
? _montgomeryOne
|
||||||
: reducedDelta.Pow2MontgomeryModWindowedKeepMontgomeryCpu(_divisor);
|
: delta.Pow2MontgomeryModWindowedKeepMontgomeryCpu(_divisor);
|
||||||
_currentMontgomery = _currentMontgomery.MontgomeryMultiplyCpu(multiplier, _modulus, _nPrime);
|
_currentMontgomery = _currentMontgomery.MontgomeryMultiplyCpu(delta, _modulus, _nPrime);
|
||||||
PreviousExponent = exponent;
|
PreviousExponent = exponent;
|
||||||
return ReduceCurrent();
|
return ReduceCurrent();
|
||||||
}
|
}
|
||||||
@@ -88,13 +88,14 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
public bool ComputeNextIsUnity(ulong exponent)
|
public bool ComputeNextIsUnity(ulong exponent)
|
||||||
{
|
{
|
||||||
ulong delta = exponent - PreviousExponent;
|
ulong delta = exponent - PreviousExponent;
|
||||||
ulong reducedDelta = ReduceDelta(delta);
|
|
||||||
ulong multiplier = reducedDelta == 0UL
|
|
||||||
? _montgomeryOne
|
|
||||||
: reducedDelta.Pow2MontgomeryModWindowedKeepMontgomeryCpu(_divisor);
|
|
||||||
_currentMontgomery = _currentMontgomery.MontgomeryMultiplyCpu(multiplier, _modulus, _nPrime);
|
|
||||||
PreviousExponent = exponent;
|
PreviousExponent = exponent;
|
||||||
return _currentMontgomery == _montgomeryOne;
|
delta = ReduceDelta(delta);
|
||||||
|
delta = delta == 0UL
|
||||||
|
? _montgomeryOne
|
||||||
|
: delta.Pow2MontgomeryModWindowedKeepMontgomeryCpu(_divisor);
|
||||||
|
delta = _currentMontgomery.MontgomeryMultiplyCpu(delta, _modulus, _nPrime);
|
||||||
|
_currentMontgomery = delta;
|
||||||
|
return delta == _montgomeryOne;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -126,26 +127,22 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
public bool TryAdvanceWithMontgomeryDelta(ulong exponent, ulong montgomeryDelta, out bool isUnity)
|
public bool TryAdvanceWithMontgomeryDelta(ulong exponent, ulong montgomeryDelta, out bool isUnity)
|
||||||
{
|
{
|
||||||
ulong delta = exponent - PreviousExponent;
|
ulong delta = exponent - PreviousExponent;
|
||||||
ulong reducedDelta = ReduceDelta(delta);
|
delta = ReduceDelta(delta);
|
||||||
|
|
||||||
// Prefer a cycle-reduced powmod so stepping stays aligned with the divisor-cycle cache.
|
// Prefer a cycle-reduced powmod so stepping stays aligned with the divisor-cycle cache.
|
||||||
ulong multiplier;
|
if (delta == 0UL)
|
||||||
if (reducedDelta == 0UL)
|
|
||||||
{
|
{
|
||||||
multiplier = _montgomeryOne;
|
montgomeryDelta = _montgomeryOne;
|
||||||
}
|
}
|
||||||
else if (_cycleLength != 0UL)
|
else if (_cycleLength != 0UL)
|
||||||
{
|
{
|
||||||
multiplier = reducedDelta.Pow2MontgomeryModWindowedKeepMontgomeryCpu(_divisor);
|
montgomeryDelta = delta.Pow2MontgomeryModWindowedKeepMontgomeryCpu(_divisor);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
multiplier = montgomeryDelta;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_currentMontgomery = _currentMontgomery.MontgomeryMultiplyCpu(multiplier, _modulus, _nPrime);
|
delta = _currentMontgomery.MontgomeryMultiplyCpu(montgomeryDelta, _modulus, _nPrime);
|
||||||
PreviousExponent = exponent;
|
PreviousExponent = exponent;
|
||||||
isUnity = _currentMontgomery == _montgomeryOne;
|
isUnity = delta == _montgomeryOne;
|
||||||
|
_currentMontgomery = delta;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,14 +168,22 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
var key = (cycleLength, delta);
|
int key = BuildKey(delta, cycleLength);
|
||||||
if (_cycleDeltaCache.TryGetValue(key, out ulong cached))
|
if (_cycleDeltaCache.TryGetValue(key, out ulong cached))
|
||||||
{
|
{
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong reduced = delta.ReduceCycleRemainder(cycleLength);
|
cycleLength = delta.ReduceCycleRemainder(cycleLength);
|
||||||
_cycleDeltaCache.TryAdd(key, reduced);
|
_ = _cycleDeltaCache.TryAdd(key, cycleLength);
|
||||||
return reduced;
|
return cycleLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
private static int BuildKey(ulong delta, ulong cycleLength)
|
||||||
|
{
|
||||||
|
int h1 = delta.GetHashCode();
|
||||||
|
int h2 = cycleLength.GetHashCode();
|
||||||
|
return h1 * 33 ^ h2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user