Various optimizations and cleanups. "in" removed from GpuUInt128 to avoid defensive copies from IL.
This commit is contained in:
1 parent
70eca5126b
commit
ca0cadc8a3
18 files changed
+565
-395
No files matched your search
@@ -1,31 +1,20 @@
|
||||
namespace PerfectNumbers.Core;
|
||||
|
||||
internal struct ExponentRemainderStepper
|
||||
internal struct ExponentRemainderStepper(in MontgomeryDivisorData divisor)
|
||||
{
|
||||
private readonly MontgomeryDivisorData _divisor;
|
||||
private readonly ulong _modulus;
|
||||
private readonly ulong _nPrime;
|
||||
private readonly ulong _montgomeryOne;
|
||||
private ulong _previousExponent;
|
||||
private ulong _currentMontgomery;
|
||||
private bool _hasState;
|
||||
private readonly MontgomeryDivisorData _divisor = divisor;
|
||||
private readonly ulong _modulus = divisor.Modulus;
|
||||
private readonly ulong _nPrime = divisor.NPrime;
|
||||
private readonly ulong _montgomeryOne = divisor.MontgomeryOne;
|
||||
private ulong _previousExponent = 0UL;
|
||||
private ulong _currentMontgomery = divisor.MontgomeryOne;
|
||||
private bool _hasState = false;
|
||||
|
||||
public ExponentRemainderStepper(in MontgomeryDivisorData divisor)
|
||||
{
|
||||
_divisor = divisor;
|
||||
_modulus = divisor.Modulus;
|
||||
_nPrime = divisor.NPrime;
|
||||
_montgomeryOne = divisor.MontgomeryOne;
|
||||
_previousExponent = 0UL;
|
||||
_currentMontgomery = divisor.MontgomeryOne;
|
||||
_hasState = false;
|
||||
}
|
||||
public readonly bool IsValidModulus => _modulus > 1UL && (_modulus & 1UL) != 0UL;
|
||||
|
||||
public bool IsValidModulus => _modulus > 1UL && (_modulus & 1UL) != 0UL;
|
||||
public readonly bool HasState => _hasState;
|
||||
|
||||
public bool HasState => _hasState;
|
||||
|
||||
public ulong PreviousExponent => _previousExponent;
|
||||
public readonly ulong PreviousExponent => _previousExponent;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
@@ -47,7 +36,7 @@ internal struct ExponentRemainderStepper
|
||||
// TODO: Route these state resets through the ProcessEightBitWindows helper once the scalar
|
||||
// Pow2MontgomeryMod implementation adopts it so delta stepping inherits the benchmarked
|
||||
// 2× gains for large exponents.
|
||||
_currentMontgomery = exponent.Pow2MontgomeryModWindowed(_divisor, keepMontgomery: true);
|
||||
_currentMontgomery = exponent.Pow2MontgomeryModWindowedCpu(_divisor, keepMontgomery: true);
|
||||
_previousExponent = exponent;
|
||||
_hasState = true;
|
||||
return ReduceCurrent();
|
||||
@@ -59,7 +48,7 @@ internal struct ExponentRemainderStepper
|
||||
// cached Montgomery residue ladder highlighted in MersenneDivisorCycleLengthGpuBenchmarks.
|
||||
// TODO: Replace this per-delta powmod with the upcoming windowed ladder so incremental
|
||||
// updates stop paying the single-bit cost highlighted in GpuPow2ModBenchmarks.
|
||||
ulong multiplier = delta.Pow2MontgomeryModWindowed(_divisor, keepMontgomery: true);
|
||||
ulong multiplier = delta.Pow2MontgomeryModWindowedCpu(_divisor, keepMontgomery: true);
|
||||
_currentMontgomery = _currentMontgomery.MontgomeryMultiply(multiplier, _modulus, _nPrime);
|
||||
_previousExponent = exponent;
|
||||
return ReduceCurrent();
|
||||
@@ -77,7 +66,7 @@ internal struct ExponentRemainderStepper
|
||||
{
|
||||
// TODO: Switch this reload to the shared windowed pow2 helper once available so CPU
|
||||
// residue checks align with the optimized ProcessEightBitWindows timings.
|
||||
_currentMontgomery = exponent.Pow2MontgomeryModWindowed(_divisor, keepMontgomery: true);
|
||||
_currentMontgomery = exponent.Pow2MontgomeryModWindowedCpu(_divisor, keepMontgomery: true);
|
||||
_previousExponent = exponent;
|
||||
_hasState = true;
|
||||
return _currentMontgomery == _montgomeryOne;
|
||||
@@ -88,7 +77,7 @@ internal struct ExponentRemainderStepper
|
||||
// lookups so this branch also avoids recomputing powmods when the snapshot lacks the divisor.
|
||||
// TODO: Use the windowed delta pow2 helper here as well to avoid the single-bit ladder that
|
||||
// currently lags behind the benchmarked implementation for huge divisor cycles.
|
||||
ulong multiplier = delta.Pow2MontgomeryModWindowed(_divisor, keepMontgomery: true);
|
||||
ulong multiplier = delta.Pow2MontgomeryModWindowedCpu(_divisor, keepMontgomery: true);
|
||||
_currentMontgomery = _currentMontgomery.MontgomeryMultiply(multiplier, _modulus, _nPrime);
|
||||
_previousExponent = exponent;
|
||||
return _currentMontgomery == _montgomeryOne;
|
||||
@@ -123,7 +112,7 @@ internal struct ExponentRemainderStepper
|
||||
{
|
||||
// TODO: Replace this fallback path with the upcoming ProcessEightBitWindows helper so
|
||||
// fresh Montgomery states also benefit from the faster pow2 ladder measured on CPUs.
|
||||
_currentMontgomery = exponent.Pow2MontgomeryModWindowed(_divisor, keepMontgomery: true);
|
||||
_currentMontgomery = exponent.Pow2MontgomeryModWindowedCpu(_divisor, keepMontgomery: true);
|
||||
_previousExponent = exponent;
|
||||
_hasState = true;
|
||||
isUnity = _currentMontgomery == _montgomeryOne;
|
||||
|
||||
Reference in new issue
Block a user