MethodImplOptions.AggressiveOptimization & MethodImplOptions.AggressiveInlining optimized. Small optimizations.
This commit is contained in:
1 parent
7a242b3bfa
commit
05d3061c47
23 files changed
+284
-215
No files matched your search
@@ -12,10 +12,7 @@ public class HeuristicCombinedPrimeTesterTests
|
|||||||
[InlineData((byte)9)]
|
[InlineData((byte)9)]
|
||||||
public void Enumerator_uses_one_a_one_b_schedule_by_default(byte lastDigit)
|
public void Enumerator_uses_one_a_one_b_schedule_by_default(byte lastDigit)
|
||||||
{
|
{
|
||||||
Span<HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState> groupBState =
|
var enumerator = HeuristicCombinedPrimeTester.CreateHeuristicDivisorEnumerator(500UL * 500UL, lastDigit);
|
||||||
stackalloc HeuristicCombinedPrimeTester.HeuristicGroupBSequenceState[4];
|
|
||||||
|
|
||||||
var enumerator = HeuristicCombinedPrimeTester.CreateHeuristicDivisorEnumerator(500UL * 500UL, lastDigit, groupBState);
|
|
||||||
var results = new List<HeuristicCombinedPrimeTester.HeuristicDivisorCandidate>(32);
|
var results = new List<HeuristicCombinedPrimeTester.HeuristicDivisorCandidate>(32);
|
||||||
|
|
||||||
while (results.Count < 20 && enumerator.TryGetNext(out var candidate))
|
while (results.Count < 20 && enumerator.TryGetNext(out var candidate))
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ public struct AscendingDivisorRemainderStepper
|
|||||||
private readonly ulong _dividend;
|
private readonly ulong _dividend;
|
||||||
private ulong _maxDivisor;
|
private ulong _maxDivisor;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
|
||||||
public AscendingDivisorRemainderStepper(ulong value)
|
public AscendingDivisorRemainderStepper(ulong value)
|
||||||
{
|
{
|
||||||
_dividend = value;
|
_dividend = value;
|
||||||
@@ -20,10 +20,10 @@ public struct AscendingDivisorRemainderStepper
|
|||||||
_maxDivisor = root;
|
_maxDivisor = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public readonly bool ShouldContinue(ulong divisor) => divisor <= _maxDivisor;
|
public readonly bool ShouldContinue(ulong divisor) => divisor <= _maxDivisor;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public bool Divides(ulong divisor)
|
public bool Divides(ulong divisor)
|
||||||
{
|
{
|
||||||
ulong remainder = _dividend;
|
ulong remainder = _dividend;
|
||||||
|
|||||||
@@ -10,21 +10,21 @@ public struct BidirectionalCycleRemainderStepper(ulong modulus)
|
|||||||
|
|
||||||
public readonly ulong Modulus
|
public readonly ulong Modulus
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
return _modulus;
|
return _modulus;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public void Initialize(ulong value)
|
public void Initialize(ulong value)
|
||||||
{
|
{
|
||||||
_remainder = value.ReduceCycleRemainder(_modulus);
|
_remainder = value.ReduceCycleRemainder(_modulus);
|
||||||
_previous = value;
|
_previous = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public ulong Step(ulong value)
|
public ulong Step(ulong value)
|
||||||
{
|
{
|
||||||
long delta = unchecked((long)value - (long)_previous);
|
long delta = unchecked((long)value - (long)_previous);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace PerfectNumbers.Core.Cpu;
|
namespace PerfectNumbers.Core.Cpu;
|
||||||
|
|
||||||
internal static class DeterministicRandomCpu
|
internal static class DeterministicRandomCpu
|
||||||
@@ -7,6 +9,7 @@ internal static class DeterministicRandomCpu
|
|||||||
|
|
||||||
private static long s_seedCounter;
|
private static long s_seedCounter;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong NextUInt64()
|
public static ulong NextUInt64()
|
||||||
{
|
{
|
||||||
ulong state = s_threadState;
|
ulong state = s_threadState;
|
||||||
@@ -22,6 +25,7 @@ internal static class DeterministicRandomCpu
|
|||||||
return state * 2685821657736338717UL;
|
return state * 2685821657736338717UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static UInt128 NextUInt128()
|
public static UInt128 NextUInt128()
|
||||||
{
|
{
|
||||||
UInt128 high = (UInt128)NextUInt64();
|
UInt128 high = (UInt128)NextUInt64();
|
||||||
@@ -29,6 +33,7 @@ internal static class DeterministicRandomCpu
|
|||||||
return (high << 64) | low;
|
return (high << 64) | low;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong InitializeThreadState()
|
private static ulong InitializeThreadState()
|
||||||
{
|
{
|
||||||
ulong seed = (ulong)Interlocked.Increment(ref s_seedCounter);
|
ulong seed = (ulong)Interlocked.Increment(ref s_seedCounter);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
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<(ulong Cycle, ulong Delta), ulong> _cycleDeltaCache = new();
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public readonly bool MatchesDivisor(in MontgomeryDivisorData divisor, ulong cycleLength)
|
public readonly bool MatchesDivisor(in MontgomeryDivisorData divisor, ulong cycleLength)
|
||||||
=> _modulus == divisor.Modulus && _nPrime == divisor.NPrime && _montgomeryOne == divisor.MontgomeryOne && _cycleLength == cycleLength;
|
=> _modulus == divisor.Modulus && _nPrime == divisor.NPrime && _montgomeryOne == divisor.MontgomeryOne && _cycleLength == cycleLength;
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// Clears the cached Montgomery residue so the stepper can be reused for another divisor.
|
/// Clears the cached Montgomery residue so the stepper can be reused for another divisor.
|
||||||
/// Callers must reinitialize the stepper before consuming any residues after a reset.
|
/// Callers must reinitialize the stepper before consuming any residues after a reset.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
PreviousExponent = 0UL;
|
PreviousExponent = 0UL;
|
||||||
@@ -39,7 +39,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exponent">First exponent evaluated for the current divisor. The caller must reuse the same divisor metadata.</param>
|
/// <param name="exponent">First exponent evaluated for the current divisor. The caller must reuse the same divisor metadata.</param>
|
||||||
/// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns>
|
/// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public ulong InitializeCpu(ulong exponent)
|
public ulong InitializeCpu(ulong exponent)
|
||||||
{
|
{
|
||||||
InitializeCpuState(exponent);
|
InitializeCpuState(exponent);
|
||||||
@@ -51,7 +51,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exponent">First exponent evaluated for the current divisor. Must match the divisor passed to the constructor.</param>
|
/// <param name="exponent">First exponent evaluated for the current divisor. Must match the divisor passed to the constructor.</param>
|
||||||
/// <returns><see langword="true"/> when the seed exponent produces a Montgomery residue equal to one.</returns>
|
/// <returns><see langword="true"/> when the seed exponent produces a Montgomery residue equal to one.</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public bool InitializeCpuIsUnity(ulong exponent)
|
public bool InitializeCpuIsUnity(ulong exponent)
|
||||||
{
|
{
|
||||||
InitializeCpuState(exponent);
|
InitializeCpuState(exponent);
|
||||||
@@ -64,7 +64,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exponent">Next exponent in the ascending sequence. Callers must never move backwards or reuse an older exponent.</param>
|
/// <param name="exponent">Next exponent in the ascending sequence. Callers must never move backwards or reuse an older exponent.</param>
|
||||||
/// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns>
|
/// <returns>The canonical residue produced by <c>2^exponent mod divisor</c>.</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public ulong ComputeNextCpu(ulong exponent)
|
public ulong ComputeNextCpu(ulong exponent)
|
||||||
{
|
{
|
||||||
ulong delta = exponent - PreviousExponent;
|
ulong delta = exponent - PreviousExponent;
|
||||||
@@ -84,7 +84,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="exponent">Next exponent in the ascending sequence.</param>
|
/// <param name="exponent">Next exponent in the ascending sequence.</param>
|
||||||
/// <returns><see langword="true"/> when the canonical residue equals one.</returns>
|
/// <returns><see langword="true"/> when the canonical residue equals one.</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public bool ComputeNextIsUnity(ulong exponent)
|
public bool ComputeNextIsUnity(ulong exponent)
|
||||||
{
|
{
|
||||||
ulong delta = exponent - PreviousExponent;
|
ulong delta = exponent - PreviousExponent;
|
||||||
@@ -105,7 +105,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// <param name="montgomeryResult">Residue in Montgomery form produced externally for the configured divisor.</param>
|
/// <param name="montgomeryResult">Residue in Montgomery form produced externally for the configured divisor.</param>
|
||||||
/// <param name="isUnity">Outputs whether the supplied residue equals Montgomery one.</param>
|
/// <param name="isUnity">Outputs whether the supplied residue equals Montgomery one.</param>
|
||||||
/// <returns><see langword="true"/> when the residue is accepted and cached.</returns>
|
/// <returns><see langword="true"/> when the residue is accepted and cached.</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public bool TryInitializeFromMontgomeryResult(ulong exponent, ulong montgomeryResult, out bool isUnity)
|
public bool TryInitializeFromMontgomeryResult(ulong exponent, ulong montgomeryResult, out bool isUnity)
|
||||||
{
|
{
|
||||||
_currentMontgomery = montgomeryResult;
|
_currentMontgomery = montgomeryResult;
|
||||||
@@ -122,7 +122,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
/// <param name="montgomeryDelta">Montgomery residue delta corresponding to the exponent gap.</param>
|
/// <param name="montgomeryDelta">Montgomery residue delta corresponding to the exponent gap.</param>
|
||||||
/// <param name="isUnity">Outputs whether the resulting residue equals Montgomery one.</param>
|
/// <param name="isUnity">Outputs whether the resulting residue equals Montgomery one.</param>
|
||||||
/// <returns><see langword="true"/> when the advance succeeds.</returns>
|
/// <returns><see langword="true"/> when the advance succeeds.</returns>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
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;
|
||||||
@@ -149,7 +149,7 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private void InitializeCpuState(ulong exponent)
|
private void InitializeCpuState(ulong exponent)
|
||||||
{
|
{
|
||||||
ulong rotation = ReduceDelta(exponent);
|
ulong rotation = ReduceDelta(exponent);
|
||||||
@@ -159,10 +159,10 @@ internal struct ExponentRemainderStepperCpu(in MontgomeryDivisorData divisor, ul
|
|||||||
PreviousExponent = exponent;
|
PreviousExponent = exponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private readonly ulong ReduceCurrent() => _currentMontgomery.MontgomeryMultiplyCpu(1UL, _modulus, _nPrime);
|
private readonly ulong ReduceCurrent() => _currentMontgomery.MontgomeryMultiplyCpu(1UL, _modulus, _nPrime);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private readonly ulong ReduceDelta(ulong delta)
|
private readonly ulong ReduceDelta(ulong delta)
|
||||||
{
|
{
|
||||||
ulong cycleLength = _cycleLength;
|
ulong cycleLength = _cycleLength;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
|
|
||||||
@@ -9,10 +10,13 @@ internal readonly struct HeuristicCombinedGpuTables
|
|||||||
|
|
||||||
private static readonly HeuristicCombinedGpuTables[] _sharedTables = new HeuristicCombinedGpuTables[PerfectNumberConstants.RollingAccelerators];
|
private static readonly HeuristicCombinedGpuTables[] _sharedTables = new HeuristicCombinedGpuTables[PerfectNumberConstants.RollingAccelerators];
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new(_accelerators[acceleratorIndex], stream);
|
internal static void WarmUp(int acceleratorIndex, AcceleratorStream stream) => _sharedTables[acceleratorIndex] = new(_accelerators[acceleratorIndex], stream);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static HeuristicCombinedGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex];
|
internal static HeuristicCombinedGpuTables GetStaticTables(int acceleratorIndex) => _sharedTables[acceleratorIndex];
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal HeuristicCombinedGpuTables(Accelerator accelerator, AcceleratorStream stream)
|
internal HeuristicCombinedGpuTables(Accelerator accelerator, AcceleratorStream stream)
|
||||||
{
|
{
|
||||||
var combinedEnding1 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding1;
|
var combinedEnding1 = HeuristicCombinedPrimeTester.CombinedDivisorsEnding1;
|
||||||
@@ -45,6 +49,7 @@ internal readonly struct HeuristicCombinedGpuTables
|
|||||||
internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9;
|
internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorsEnding9;
|
||||||
internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding9;
|
internal readonly MemoryBuffer1D<ulong, Stride1D.Dense> HeuristicCombinedDivisorSquaresEnding9;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal HeuristicCombinedGpuViews CreateViews() => new(
|
internal HeuristicCombinedGpuViews CreateViews() => new(
|
||||||
HeuristicCombinedDivisorsEnding1.View,
|
HeuristicCombinedDivisorsEnding1.View,
|
||||||
HeuristicCombinedDivisorsEnding3.View,
|
HeuristicCombinedDivisorsEnding3.View,
|
||||||
@@ -55,6 +60,7 @@ internal readonly struct HeuristicCombinedGpuTables
|
|||||||
HeuristicCombinedDivisorSquaresEnding7.View,
|
HeuristicCombinedDivisorSquaresEnding7.View,
|
||||||
HeuristicCombinedDivisorSquaresEnding9.View);
|
HeuristicCombinedDivisorSquaresEnding9.View);
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal void Dispose()
|
internal void Dispose()
|
||||||
{
|
{
|
||||||
HeuristicCombinedDivisorsEnding1.Dispose();
|
HeuristicCombinedDivisorsEnding1.Dispose();
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<uint>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> SmallPrimeSieveKernelLauncher;
|
||||||
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher;
|
public readonly Action<AcceleratorStream, Index1D, ulong, ArrayView<ulong>, int, ulong, ArrayView<ulong>> SpecialMaxKernelLauncher;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public void EnsureCalculateOrderWideCapacity(int newSize)
|
public void EnsureCalculateOrderWideCapacity(int newSize)
|
||||||
{
|
{
|
||||||
if (newSize > Input.Length)
|
if (newSize > Input.Length)
|
||||||
@@ -213,6 +214,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
public void EnsureCapacity(int factorsCount, int primeTesterCapacity)
|
||||||
{
|
{
|
||||||
Accelerator accelerator = Accelerator;
|
Accelerator accelerator = Accelerator;
|
||||||
@@ -325,6 +327,7 @@ public sealed class PrimeOrderCalculatorAccelerator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public void EnsureUlongInputOutputCapacity(int newSize)
|
public void EnsureUlongInputOutputCapacity(int newSize)
|
||||||
{
|
{
|
||||||
var accelerator = Accelerator;
|
var accelerator = Accelerator;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
@@ -74,6 +75,7 @@ public class GpuKernelPool
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
static void InitPow2ModKernelScan(Accelerator accelerator, KernelContainer kernels)
|
static void InitPow2ModKernelScan(Accelerator accelerator, KernelContainer kernels)
|
||||||
{
|
{
|
||||||
InitOnce(ref kernels.Pow2Mod, () =>
|
InitOnce(ref kernels.Pow2Mod, () =>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
|
|
||||||
@@ -6,6 +7,7 @@ namespace PerfectNumbers.Core.Gpu;
|
|||||||
internal static class Pow2ModKernels
|
internal static class Pow2ModKernels
|
||||||
{
|
{
|
||||||
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
|
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void Pow2ModKernelScan(
|
public static void Pow2ModKernelScan(
|
||||||
Index1D index,
|
Index1D index,
|
||||||
ulong exponent,
|
ulong exponent,
|
||||||
@@ -107,6 +109,7 @@ internal static class Pow2ModKernels
|
|||||||
|
|
||||||
/// This kernel doesn't always set the result of the found array. It sets the value only when it needs to. The callers
|
/// This kernel doesn't always set the result of the found array. It sets the value only when it needs to. The callers
|
||||||
/// must clean the output buffer before the call to get a deterministic result.
|
/// must clean the output buffer before the call to get a deterministic result.
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void Pow2ModOrderKernelScan(
|
public static void Pow2ModOrderKernelScan(
|
||||||
Index1D index,
|
Index1D index,
|
||||||
ulong exponent,
|
ulong exponent,
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ public static class Pow2MontgomeryKernels
|
|||||||
return sumHigh;
|
return sumHigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
|
||||||
private static void MultiplyPartsGpu(ulong left, ulong right, out ulong high, out ulong low)
|
private static void MultiplyPartsGpu(ulong left, ulong right, out ulong high, out ulong low)
|
||||||
{
|
{
|
||||||
ulong leftLow = (uint)left;
|
ulong leftLow = (uint)left;
|
||||||
@@ -135,13 +135,13 @@ public static class Pow2MontgomeryKernels
|
|||||||
high = unchecked(highProduct + (cross1 >> 32) + (cross2 >> 32) + (carry >> 32));
|
high = unchecked(highProduct + (cross1 >> 32) + (cross2 >> 32) + (carry >> 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static ulong Pow2MontgomeryModWindowedGpuKeepMontgomery(in MontgomeryDivisorDataGpu divisor, ulong exponent)
|
internal static ulong Pow2MontgomeryModWindowedGpuKeepMontgomery(in MontgomeryDivisorDataGpu divisor, ulong exponent)
|
||||||
{
|
{
|
||||||
return Pow2MontgomeryModWindowedGpuMontgomeryResult(divisor, exponent);
|
return Pow2MontgomeryModWindowedGpuMontgomeryResult(divisor, exponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWindowedGpuConvertToStandard(this MontgomeryDivisorDataGpu divisor, ulong exponent)
|
public static ulong Pow2MontgomeryModWindowedGpuConvertToStandard(this MontgomeryDivisorDataGpu divisor, ulong exponent)
|
||||||
{
|
{
|
||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
@@ -150,7 +150,7 @@ public static class Pow2MontgomeryKernels
|
|||||||
return MontgomeryMultiplyGpu(montgomeryResult, 1UL, modulus, nPrime);
|
return MontgomeryMultiplyGpu(montgomeryResult, 1UL, modulus, nPrime);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong Pow2MontgomeryModWindowedGpuMontgomeryResult(in MontgomeryDivisorDataGpu divisor, ulong exponent)
|
private static ulong Pow2MontgomeryModWindowedGpuMontgomeryResult(in MontgomeryDivisorDataGpu divisor, ulong exponent)
|
||||||
{
|
{
|
||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
|
|||||||
@@ -1182,6 +1182,7 @@ internal static partial class PrimeOrderKernels
|
|||||||
return divisor.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent) == 1UL;
|
return divisor.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent) == 1UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong CalculateByDoublingKernel(ulong prime)
|
private static ulong CalculateByDoublingKernel(ulong prime)
|
||||||
{
|
{
|
||||||
ulong order = 1UL;
|
ulong order = 1UL;
|
||||||
@@ -1203,6 +1204,7 @@ internal static partial class PrimeOrderKernels
|
|||||||
|
|
||||||
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
|
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void Pow2ModKernel(Index1D index, ArrayView1D<ulong, Stride1D.Dense> exponents, ulong divisorModulus, ulong divisorNPrime, ulong divisorMontgomeryOne, ulong divisorMontgomeryTwo, ulong divisorMontgomeryTwoSquared, ArrayView1D<ulong, Stride1D.Dense> remainders)
|
internal static void Pow2ModKernel(Index1D index, ArrayView1D<ulong, Stride1D.Dense> exponents, ulong divisorModulus, ulong divisorNPrime, ulong divisorMontgomeryOne, ulong divisorMontgomeryTwo, ulong divisorMontgomeryTwoSquared, ArrayView1D<ulong, Stride1D.Dense> remainders)
|
||||||
{
|
{
|
||||||
ulong exponent = exponents[index];
|
ulong exponent = exponents[index];
|
||||||
@@ -1211,12 +1213,14 @@ internal static partial class PrimeOrderKernels
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
|
/// This kernel always sets the result of the corresponding element. Callers don't need to clear the output buffers.
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void Pow2ModKernelWide(Index1D index, ArrayView1D<GpuUInt128, Stride1D.Dense> exponents, GpuUInt128 modulus, ArrayView1D<GpuUInt128, Stride1D.Dense> remainders)
|
internal static void Pow2ModKernelWide(Index1D index, ArrayView1D<GpuUInt128, Stride1D.Dense> exponents, GpuUInt128 modulus, ArrayView1D<GpuUInt128, Stride1D.Dense> remainders)
|
||||||
{
|
{
|
||||||
GpuUInt128 exponent = exponents[index];
|
GpuUInt128 exponent = exponents[index];
|
||||||
remainders[index] = Pow2ModKernelCore(exponent, modulus);
|
remainders[index] = Pow2ModKernelCore(exponent, modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static GpuUInt128[] InitializeOddPowersTable(GpuUInt128 baseValue, GpuUInt128 modulus, int oddPowerCount)
|
private static GpuUInt128[] InitializeOddPowersTable(GpuUInt128 baseValue, GpuUInt128 modulus, int oddPowerCount)
|
||||||
{
|
{
|
||||||
GpuUInt128[] result = new GpuUInt128[PerfectNumberConstants.MaxOddPowersCount];
|
GpuUInt128[] result = new GpuUInt128[PerfectNumberConstants.MaxOddPowersCount];
|
||||||
@@ -1242,6 +1246,7 @@ internal static partial class PrimeOrderKernels
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static GpuUInt128 Pow2ModKernelCore(GpuUInt128 exponent, GpuUInt128 modulus)
|
internal static GpuUInt128 Pow2ModKernelCore(GpuUInt128 exponent, GpuUInt128 modulus)
|
||||||
{
|
{
|
||||||
// This should never happen in production code.
|
// This should never happen in production code.
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
// requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched.
|
// requested by the caller, skip queuing additional block generation, and keep the snapshot cache untouched.
|
||||||
|
|
||||||
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
|
// GPU residue variant: check 2^p % q == 1 for q = 2*p*k + 1.
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public void Scan(PrimeOrderCalculatorAccelerator gpu, ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
public void Scan(PrimeOrderCalculatorAccelerator gpu, ulong exponent, UInt128 twoP, LastDigit lastDigit, UInt128 maxK, ref bool isPrime)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
@@ -114,6 +115,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
// GpuPrimeWorkLimiter.Release();
|
// GpuPrimeWorkLimiter.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetPow2ModKernel(Accelerator accelerator)
|
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> GetPow2ModKernel(Accelerator accelerator)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -128,6 +130,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> CreatePow2ModKernel(Accelerator accelerator)
|
private static Action<AcceleratorStream, Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> CreatePow2ModKernel(Accelerator accelerator)
|
||||||
{
|
{
|
||||||
var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModKernelScan);
|
var loaded = accelerator.LoadAutoGroupedStreamKernel<Index1D, ulong, GpuUInt128, GpuUInt128, byte, ulong, ResidueAutomatonArgs, ArrayView<ulong>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<uint, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(Pow2ModKernels.Pow2ModKernelScan);
|
||||||
@@ -140,6 +143,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ResidueResources RentResources(Accelerator accelerator, int capacity)
|
private static ResidueResources RentResources(Accelerator accelerator, int capacity)
|
||||||
{
|
{
|
||||||
var resourcePools = _resourcePools ??= new();
|
var resourcePools = _resourcePools ??= new();
|
||||||
@@ -152,6 +156,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
return new ResidueResources(accelerator, capacity);
|
return new ResidueResources(accelerator, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void ReturnResources(ResidueResources resources)
|
private static void ReturnResources(ResidueResources resources)
|
||||||
{
|
{
|
||||||
var resourcePools = _resourcePools ??= new();
|
var resourcePools = _resourcePools ??= new();
|
||||||
@@ -160,6 +165,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
|
|
||||||
private sealed class ResidueResources
|
private sealed class ResidueResources
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal ResidueResources(Accelerator accelerator, int capacity)
|
internal ResidueResources(Accelerator accelerator, int capacity)
|
||||||
{
|
{
|
||||||
Capacity = Math.Max(1, capacity);
|
Capacity = Math.Max(1, capacity);
|
||||||
@@ -171,6 +177,7 @@ public class MersenneNumberResidueGpuTester(bool useGpuOrder)
|
|||||||
OrderArray = ThreadStaticPools.UlongPool.Rent(Capacity);
|
OrderArray = ThreadStaticPools.UlongPool.Rent(Capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal void EnsureCapacity(Accelerator accelerator, int capacity)
|
internal void EnsureCapacity(Accelerator accelerator, int capacity)
|
||||||
{
|
{
|
||||||
if (OrderBuffer.Length >= capacity)
|
if (OrderBuffer.Length >= capacity)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace PerfectNumbers.Core.Gpu;
|
|||||||
|
|
||||||
public static class Pow2MontgomeryGpuCalculator
|
public static class Pow2MontgomeryGpuCalculator
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong CalculateKeep(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
public static ulong CalculateKeep(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
// GpuPrimeWorkLimiter.Acquire();
|
// GpuPrimeWorkLimiter.Acquire();
|
||||||
@@ -34,7 +34,7 @@ public static class Pow2MontgomeryGpuCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
public static ulong CalculateConvert(PrimeOrderCalculatorAccelerator gpu, ulong exponent, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
ulong result = 0UL;
|
ulong result = 0UL;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using PerfectNumbers.Core.Gpu.Accelerators;
|
using PerfectNumbers.Core.Gpu.Accelerators;
|
||||||
@@ -16,6 +17,7 @@ internal enum GpuPow2ModStatus
|
|||||||
|
|
||||||
internal static partial class PrimeOrderGpuHeuristics
|
internal static partial class PrimeOrderGpuHeuristics
|
||||||
{
|
{
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void PreloadStaticTables(AcceleratorStream stream)
|
internal static void PreloadStaticTables(AcceleratorStream stream)
|
||||||
{
|
{
|
||||||
// _ = GetSmallPrimeDeviceCache(stream);
|
// _ = GetSmallPrimeDeviceCache(stream);
|
||||||
@@ -31,16 +33,19 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
|
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
|
||||||
internal static ConcurrentDictionary<UInt128, byte> OverflowRegistryWide => OverflowedPrimesWide;
|
internal static ConcurrentDictionary<UInt128, byte> OverflowRegistryWide => OverflowedPrimesWide;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void OverrideCapabilitiesForTesting(PrimeOrderGpuCapability capability)
|
internal static void OverrideCapabilitiesForTesting(PrimeOrderGpuCapability capability)
|
||||||
{
|
{
|
||||||
s_capability = capability;
|
s_capability = capability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static void ResetCapabilitiesForTesting()
|
internal static void ResetCapabilitiesForTesting()
|
||||||
{
|
{
|
||||||
s_capability = PrimeOrderGpuCapability.Default;
|
s_capability = PrimeOrderGpuCapability.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static bool TryPartialFactor(
|
public static bool TryPartialFactor(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong value,
|
ulong value,
|
||||||
@@ -88,6 +93,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
|
|
||||||
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
private static readonly Accelerator[] _accelerators = AcceleratorPool.Shared.Accelerators;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryLaunchPartialFactorKernel(
|
private static bool TryLaunchPartialFactorKernel(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong value,
|
ulong value,
|
||||||
@@ -156,6 +162,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, out ulong remainder, in MontgomeryDivisorData? divisorData)
|
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, out ulong remainder, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
Span<ulong> exponents = stackalloc ulong[1];
|
Span<ulong> exponents = stackalloc ulong[1];
|
||||||
@@ -167,6 +174,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<ulong> exponents, ulong prime, Span<ulong> remainders, in MontgomeryDivisorData? divisorData)
|
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<ulong> exponents, ulong prime, Span<ulong> remainders, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
// This will never occur in production code
|
// This will never occur in production code
|
||||||
@@ -222,6 +230,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return computed ? GpuPow2ModStatus.Success : GpuPow2ModStatus.Unavailable;
|
return computed ? GpuPow2ModStatus.Success : GpuPow2ModStatus.Unavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 prime, out UInt128 remainder)
|
public static GpuPow2ModStatus TryPow2Mod(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 prime, out UInt128 remainder)
|
||||||
{
|
{
|
||||||
Span<UInt128> exponents = stackalloc UInt128[1];
|
Span<UInt128> exponents = stackalloc UInt128[1];
|
||||||
@@ -233,11 +242,13 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
|
public static GpuPow2ModStatus TryPow2ModBatch(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
|
||||||
{
|
{
|
||||||
return TryPow2ModBatchInternal(gpu, exponents, prime, remainders);
|
return TryPow2ModBatchInternal(gpu, exponents, prime, remainders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static bool TryCalculateOrder(
|
internal static bool TryCalculateOrder(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
@@ -310,6 +321,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
return order != 0UL;
|
return order != 0UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static GpuPow2ModStatus TryPow2ModBatchInternal(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
|
private static GpuPow2ModStatus TryPow2ModBatchInternal(PrimeOrderCalculatorAccelerator gpu, ReadOnlySpan<UInt128> exponents, UInt128 prime, Span<UInt128> remainders)
|
||||||
{
|
{
|
||||||
if (exponents.Length == 0)
|
if (exponents.Length == 0)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
CombinedDivisorsEnding9Squares = CombinedDivisorsEnding9OneAOneBSquares;
|
CombinedDivisorsEnding9Squares = CombinedDivisorsEnding9OneAOneBSquares;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void EnsureInitialized()
|
public static void EnsureInitialized()
|
||||||
{
|
{
|
||||||
// Intentionally left blank. Accessing this method forces the static constructor to run.
|
// Intentionally left blank. Accessing this method forces the static constructor to run.
|
||||||
@@ -155,9 +156,10 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
|
|
||||||
public static HeuristicCombinedPrimeTester Exclusive => _tester ??= new();
|
public static HeuristicCombinedPrimeTester Exclusive => _tester ??= new();
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static bool IsPrimeCpu(ulong n)
|
public static bool IsPrimeCpu(ulong n)
|
||||||
{
|
{
|
||||||
byte nMod10 = (byte)n.Mod10();
|
byte nMod10 = n.Mod10();
|
||||||
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
||||||
|
|
||||||
if (maxDivisorSquare < 9UL)
|
if (maxDivisorSquare < 9UL)
|
||||||
@@ -168,13 +170,15 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return HeuristicTrialDivisionCpu(n, maxDivisorSquare, nMod10);
|
return HeuristicTrialDivisionCpu(n, maxDivisorSquare, nMod10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n)
|
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n)
|
||||||
{
|
{
|
||||||
byte nMod10 = (byte)n.Mod10();
|
byte nMod10 = n.Mod10();
|
||||||
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
ulong maxDivisorSquare = ComputeHeuristicDivisorSquareLimit(n);
|
||||||
return IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10);
|
return IsPrimeGpu(gpu, n, maxDivisorSquare, nMod10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
public static bool IsPrimeGpu(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
|
// TODO: Is this condition ever met on the execution path in EvenPerfectBitScanner?
|
||||||
@@ -187,6 +191,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return !compositeDetected;
|
return !compositeDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool HeuristicTrialDivisionCpu(ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicTrialDivisionCpu(ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<ulong> combinedDivisors = GetCombinedDivisors(nMod10);
|
ReadOnlySpan<ulong> combinedDivisors = GetCombinedDivisors(nMod10);
|
||||||
@@ -211,7 +216,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return EvaluateWithOpenNumericFallback(n);
|
return EvaluateWithOpenNumericFallback(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static int GetBatchSize(ulong n) => n switch
|
internal static int GetBatchSize(ulong n) => n switch
|
||||||
{
|
{
|
||||||
< 1_000 => 8,
|
< 1_000 => 8,
|
||||||
@@ -222,6 +227,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
private static bool HeuristicTrialDivisionGpuDetectsDivisor(PrimeOrderCalculatorAccelerator gpu, ulong n, ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
var acceleratorIndex = gpu.AcceleratorIndex;
|
var acceleratorIndex = gpu.AcceleratorIndex;
|
||||||
@@ -254,13 +260,13 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool EvaluateWithOpenNumericFallback(ulong n) => Prime.Numbers.IsPrime(n);
|
private static bool EvaluateWithOpenNumericFallback(ulong n) => Prime.Numbers.IsPrime(n);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n) => n;
|
internal static ulong ComputeHeuristicDivisorSquareLimit(ulong n) => n;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10) => nMod10 switch
|
private static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10) => nMod10 switch
|
||||||
{
|
{
|
||||||
1 => CombinedDivisorsEnding1,
|
1 => CombinedDivisorsEnding1,
|
||||||
@@ -270,7 +276,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
_ => throw new InvalidOperationException($"Unsupported combined divisor selector for digit {nMod10}."),
|
_ => throw new InvalidOperationException($"Unsupported combined divisor selector for digit {nMod10}."),
|
||||||
};
|
};
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10) => nMod10 switch
|
private static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10) => nMod10 switch
|
||||||
{
|
{
|
||||||
1 => CombinedDivisorsEnding1Squares,
|
1 => CombinedDivisorsEnding1Squares,
|
||||||
@@ -280,7 +286,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
_ => throw new InvalidOperationException($"Unsupported combined divisor square selector for digit {nMod10}."),
|
_ => throw new InvalidOperationException($"Unsupported combined divisor square selector for digit {nMod10}."),
|
||||||
};
|
};
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10, CombinedDivisorPattern pattern) => pattern switch
|
internal static ReadOnlySpan<ulong> GetCombinedDivisors(byte nMod10, CombinedDivisorPattern pattern) => pattern switch
|
||||||
{
|
{
|
||||||
CombinedDivisorPattern.TwoAOneB => nMod10 switch
|
CombinedDivisorPattern.TwoAOneB => nMod10 switch
|
||||||
@@ -318,7 +324,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
_ => throw new InvalidOperationException($"Unsupported combined divisor pattern: {pattern}."),
|
_ => throw new InvalidOperationException($"Unsupported combined divisor pattern: {pattern}."),
|
||||||
};
|
};
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10, CombinedDivisorPattern pattern) => pattern switch
|
internal static ReadOnlySpan<ulong> GetCombinedDivisorSquares(byte nMod10, CombinedDivisorPattern pattern) => pattern switch
|
||||||
{
|
{
|
||||||
CombinedDivisorPattern.TwoAOneB => nMod10 switch
|
CombinedDivisorPattern.TwoAOneB => nMod10 switch
|
||||||
@@ -428,6 +434,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static int GetGroupBStartIndex(ReadOnlySpan<uint> divisors)
|
private static int GetGroupBStartIndex(ReadOnlySpan<uint> divisors)
|
||||||
{
|
{
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@@ -439,8 +446,10 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool IsGroupAPrefixValue(ulong value) => value is 3UL or 7UL or 11UL or 13UL;
|
private static bool IsGroupAPrefixValue(ulong value) => value is 3UL or 7UL or 11UL or 13UL;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static HeuristicDivisorGroup ResolveGroup(ulong value) => value switch
|
private static HeuristicDivisorGroup ResolveGroup(ulong value) => value switch
|
||||||
{
|
{
|
||||||
3UL or 7UL or 11UL or 13UL => HeuristicDivisorGroup.GroupAConstant,
|
3UL or 7UL or 11UL or 13UL => HeuristicDivisorGroup.GroupAConstant,
|
||||||
@@ -448,6 +457,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
_ => HeuristicDivisorGroup.GroupB,
|
_ => HeuristicDivisorGroup.GroupB,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ReadOnlySpan<uint> GetGroupBDivisors(byte ending) => ending switch
|
private static ReadOnlySpan<uint> GetGroupBDivisors(byte ending) => ending switch
|
||||||
{
|
{
|
||||||
1 => DivisorGenerator.SmallPrimesLastOneWithoutLastThree,
|
1 => DivisorGenerator.SmallPrimesLastOneWithoutLastThree,
|
||||||
@@ -457,19 +467,19 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
_ => [],
|
_ => [],
|
||||||
};
|
};
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer)
|
internal static HeuristicDivisorEnumerator CreateHeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10)
|
||||||
=> new(maxDivisorSquare, nMod10, groupBBuffer);
|
=> new(maxDivisorSquare, nMod10);
|
||||||
|
|
||||||
internal struct HeuristicGroupBSequenceState
|
internal struct HeuristicGroupBSequenceState
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
internal static MersenneHeuristicDivisorEnumerator CreateMersenneDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
||||||
=> new(exponent, maxDivisor);
|
=> new(exponent, maxDivisor);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
|
internal static HeuristicDivisorPreparation PrepareHeuristicDivisor(in HeuristicDivisorCandidate candidate)
|
||||||
{
|
{
|
||||||
ulong divisor = candidate.Value;
|
ulong divisor = candidate.Value;
|
||||||
@@ -478,7 +488,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return new(candidate, divisorData, cycleLength, hasCycleHint);
|
return new(candidate, divisorData, cycleLength, hasCycleHint);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static ulong ResolveHeuristicCycleLengthCpu(
|
internal static ulong ResolveHeuristicCycleLengthCpu(
|
||||||
ulong exponent,
|
ulong exponent,
|
||||||
in HeuristicDivisorPreparation preparation,
|
in HeuristicDivisorPreparation preparation,
|
||||||
@@ -519,7 +529,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return resolvedCycle;
|
return resolvedCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static ulong ResolveHeuristicCycleLengthGpu(
|
internal static ulong ResolveHeuristicCycleLengthGpu(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong exponent,
|
ulong exponent,
|
||||||
@@ -561,7 +571,7 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return resolvedCycle;
|
return resolvedCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
internal static bool TryGetCycleLengthHint(ulong divisor, out ulong cycleLength)
|
internal static bool TryGetCycleLengthHint(ulong divisor, out ulong cycleLength)
|
||||||
{
|
{
|
||||||
ulong[] snapshot = HeuristicSmallCycleSnapshot;
|
ulong[] snapshot = HeuristicSmallCycleSnapshot;
|
||||||
@@ -578,35 +588,26 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ref struct HeuristicDivisorEnumerator
|
internal ref struct HeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10)
|
||||||
{
|
{
|
||||||
private readonly ulong maxDivisorSquare;
|
private readonly ulong _maxDivisorSquare = maxDivisorSquare;
|
||||||
private readonly ReadOnlySpan<ulong> combinedDivisors;
|
private readonly ReadOnlySpan<ulong> _combinedDivisors = GetCombinedDivisors(nMod10);
|
||||||
private readonly ReadOnlySpan<ulong> combinedDivisorSquares;
|
private readonly ReadOnlySpan<ulong> _combinedDivisorSquares = GetCombinedDivisorSquares(nMod10);
|
||||||
private int index;
|
private int index = 0;
|
||||||
|
|
||||||
public HeuristicDivisorEnumerator(ulong maxDivisorSquare, byte nMod10, Span<HeuristicGroupBSequenceState> groupBBuffer)
|
|
||||||
{
|
|
||||||
this.maxDivisorSquare = maxDivisorSquare;
|
|
||||||
_ = groupBBuffer;
|
|
||||||
combinedDivisors = GetCombinedDivisors(nMod10);
|
|
||||||
combinedDivisorSquares = GetCombinedDivisorSquares(nMod10);
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool TryGetNext(out HeuristicDivisorCandidate candidate)
|
public bool TryGetNext(out HeuristicDivisorCandidate candidate)
|
||||||
{
|
{
|
||||||
while (index < combinedDivisors.Length)
|
while (index < _combinedDivisors.Length)
|
||||||
{
|
{
|
||||||
int currentIndex = index;
|
int currentIndex = index;
|
||||||
ulong divisorSquare = combinedDivisorSquares[currentIndex];
|
ulong divisorSquare = _combinedDivisorSquares[currentIndex];
|
||||||
if (divisorSquare > maxDivisorSquare)
|
if (divisorSquare > _maxDivisorSquare)
|
||||||
{
|
{
|
||||||
index = combinedDivisors.Length;
|
index = _combinedDivisors.Length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong entry = combinedDivisors[currentIndex];
|
ulong entry = _combinedDivisors[currentIndex];
|
||||||
index = currentIndex + 1;
|
index = currentIndex + 1;
|
||||||
|
|
||||||
HeuristicDivisorGroup group = ResolveGroup(entry);
|
HeuristicDivisorGroup group = ResolveGroup(entry);
|
||||||
@@ -629,8 +630,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
private GpuUInt128 current;
|
private GpuUInt128 current;
|
||||||
private MersenneDivisorResidueStepper residueStepper;
|
private MersenneDivisorResidueStepper residueStepper;
|
||||||
private bool active;
|
private bool active;
|
||||||
private ulong processedCount;
|
|
||||||
private ulong lastDivisor;
|
|
||||||
|
|
||||||
public MersenneHeuristicDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
public MersenneHeuristicDivisorEnumerator(ulong exponent, ulong maxDivisor)
|
||||||
{
|
{
|
||||||
@@ -649,8 +648,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
current = hasCandidates ? firstDivisor : GpuUInt128.Zero;
|
current = hasCandidates ? firstDivisor : GpuUInt128.Zero;
|
||||||
residueStepper = hasCandidates ? new MersenneDivisorResidueStepper(exponent, stepLocal, firstDivisor) : default;
|
residueStepper = hasCandidates ? new MersenneDivisorResidueStepper(exponent, stepLocal, firstDivisor) : default;
|
||||||
active = hasCandidates;
|
active = hasCandidates;
|
||||||
processedCount = 0UL;
|
|
||||||
lastDivisor = 0UL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetNext(out HeuristicDivisorCandidate candidate)
|
public bool TryGetNext(out HeuristicDivisorCandidate candidate)
|
||||||
@@ -658,9 +655,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
while (active)
|
while (active)
|
||||||
{
|
{
|
||||||
ulong value = current.Low;
|
ulong value = current.Low;
|
||||||
processedCount++;
|
|
||||||
lastDivisor = value;
|
|
||||||
|
|
||||||
bool admissible = residueStepper.IsAdmissible();
|
bool admissible = residueStepper.IsAdmissible();
|
||||||
|
|
||||||
Advance();
|
Advance();
|
||||||
@@ -691,12 +685,6 @@ public sealed class HeuristicCombinedPrimeTester
|
|||||||
residueStepper.Advance();
|
residueStepper.Advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly ulong ProcessedCount => processedCount;
|
|
||||||
|
|
||||||
public readonly ulong LastDivisor => lastDivisor;
|
|
||||||
|
|
||||||
public readonly bool Exhausted => !active;
|
|
||||||
|
|
||||||
private static HeuristicDivisorCandidate CreateCandidate(ulong value)
|
private static HeuristicDivisorCandidate CreateCandidate(ulong value)
|
||||||
{
|
{
|
||||||
byte ending = (byte)(value % 10UL);
|
byte ending = (byte)(value % 10UL);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public static class MontgomeryDivisorDataPool
|
|||||||
montgomeryTwoSquared);
|
montgomeryTwoSquared);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static MontgomeryDivisorData Rent(this Queue<MontgomeryDivisorData> queue, ulong modulus, ulong nPrime, ulong montgomeryOne, ulong montgomeryTwo, ulong montgomeryTwoSquared)
|
public static MontgomeryDivisorData Rent(this Queue<MontgomeryDivisorData> queue, ulong modulus, ulong nPrime, ulong montgomeryOne, ulong montgomeryTwo, ulong montgomeryTwoSquared)
|
||||||
{
|
{
|
||||||
if (queue.TryDequeue(out var pooled))
|
if (queue.TryDequeue(out var pooled))
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
private static PendingEntry? _poolHead;
|
private static PendingEntry? _poolHead;
|
||||||
private PendingEntry? _next;
|
private PendingEntry? _next;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static PendingEntry Rent(ulong value, bool knownComposite)
|
public static PendingEntry Rent(ulong value, bool knownComposite)
|
||||||
{
|
{
|
||||||
var poolHead = _poolHead;
|
var poolHead = _poolHead;
|
||||||
@@ -35,7 +35,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return poolHead;
|
return poolHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static void Return(PendingEntry entry)
|
public static void Return(PendingEntry entry)
|
||||||
{
|
{
|
||||||
entry._next = _poolHead;
|
entry._next = _poolHead;
|
||||||
@@ -47,7 +47,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
public bool HasKnownPrimality = knownComposite;
|
public bool HasKnownPrimality = knownComposite;
|
||||||
public bool IsPrime = false;
|
public bool IsPrime = false;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public void WithPrimality(bool isPrime)
|
public void WithPrimality(bool isPrime)
|
||||||
{
|
{
|
||||||
KnownComposite = KnownComposite || !isPrime;
|
KnownComposite = KnownComposite || !isPrime;
|
||||||
@@ -125,6 +125,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 CalculateWideInternalCpu(in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
|
private static UInt128 CalculateWideInternalCpu(in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
|
||||||
{
|
{
|
||||||
if (prime <= UInt128.One)
|
if (prime <= UInt128.One)
|
||||||
@@ -152,6 +153,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong RunHeuristicPipelineCpu(
|
private static ulong RunHeuristicPipelineCpu(
|
||||||
ulong prime,
|
ulong prime,
|
||||||
ulong? previousOrder,
|
ulong? previousOrder,
|
||||||
@@ -179,7 +181,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return CalculateByFactorizationCpu(prime, divisorData);
|
return CalculateByFactorizationCpu(prime, divisorData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryHeuristicFinishCpu(prime, candidateOrder, previousOrder, divisorData, config, phiFactors, orderFactors, out ulong order))
|
if (TryHeuristicFinishCpu(prime, candidateOrder, previousOrder, divisorData, config, orderFactors, out ulong order))
|
||||||
{
|
{
|
||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
@@ -187,6 +189,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return candidateOrder;
|
return candidateOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong RunHeuristicPipelineHybrid(
|
private static ulong RunHeuristicPipelineHybrid(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
@@ -223,6 +226,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return candidateOrder;
|
return candidateOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 RunHeuristicPipelineWideCpu(
|
private static UInt128 RunHeuristicPipelineWideCpu(
|
||||||
in UInt128 prime,
|
in UInt128 prime,
|
||||||
in UInt128? previousOrder,
|
in UInt128? previousOrder,
|
||||||
@@ -257,6 +261,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return candidateOrder;
|
return candidateOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 FinishStrictlyWideCpu(in UInt128 prime, in MontgomeryDivisorData? divisorData)
|
private static UInt128 FinishStrictlyWideCpu(in UInt128 prime, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
UInt128 phi = prime - UInt128.One;
|
UInt128 phi = prime - UInt128.One;
|
||||||
@@ -303,6 +308,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TrySpecialMaxWideCpu(in UInt128 phi, in UInt128 prime, in MontgomeryDivisorData? divisorData, in PartialFactorResult128 factors)
|
private static bool TrySpecialMaxWideCpu(in UInt128 phi, in UInt128 prime, in MontgomeryDivisorData? divisorData, in PartialFactorResult128 factors)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<FactorEntry128> factorSpan = factors.Factors;
|
ReadOnlySpan<FactorEntry128> factorSpan = factors.Factors;
|
||||||
@@ -320,6 +326,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 InitializeStartingOrderWideCpu(in UInt128 prime, in UInt128 phi, in MontgomeryDivisorData? divisorData)
|
private static UInt128 InitializeStartingOrderWideCpu(in UInt128 prime, in UInt128 phi, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
UInt128 order = phi;
|
UInt128 order = phi;
|
||||||
@@ -336,6 +343,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 ExponentLoweringWideCpu(UInt128 order, in UInt128 prime, in MontgomeryDivisorData? divisorData, in PartialFactorResult128 factors)
|
private static UInt128 ExponentLoweringWideCpu(UInt128 order, in UInt128 prime, in MontgomeryDivisorData? divisorData, in PartialFactorResult128 factors)
|
||||||
{
|
{
|
||||||
ArrayPool<FactorEntry128> pool = ThreadStaticPools.FactorEntry128Pool;
|
ArrayPool<FactorEntry128> pool = ThreadStaticPools.FactorEntry128Pool;
|
||||||
@@ -382,6 +390,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryConfirmOrderWideCpu(in UInt128 prime, in UInt128 order, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
|
private static bool TryConfirmOrderWideCpu(in UInt128 prime, in UInt128 order, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
|
||||||
{
|
{
|
||||||
if (order == UInt128.Zero)
|
if (order == UInt128.Zero)
|
||||||
@@ -439,6 +448,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryHeuristicFinishWideCpu(
|
private static bool TryHeuristicFinishWideCpu(
|
||||||
in UInt128 prime,
|
in UInt128 prime,
|
||||||
in UInt128 order,
|
in UInt128 order,
|
||||||
@@ -474,7 +484,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
orderFactors = orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
orderFactors = orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks * 4;
|
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecksCapacity;
|
||||||
Queue<List<UInt128>> uInt128ListPool = ThreadStaticPools.UInt128ListPool;
|
Queue<List<UInt128>> uInt128ListPool = ThreadStaticPools.UInt128ListPool;
|
||||||
List<UInt128> candidates = uInt128ListPool.Rent(capacity);
|
List<UInt128> candidates = uInt128ListPool.Rent(capacity);
|
||||||
FactorEntry128[] factorArray = orderFactors.Factors!;
|
FactorEntry128[] factorArray = orderFactors.Factors!;
|
||||||
@@ -523,6 +533,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// private static ulong specialMaxHits;
|
// private static ulong specialMaxHits;
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TrySpecialMaxCpu(ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
private static bool TrySpecialMaxCpu(ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
int length = factors.Count;
|
int length = factors.Count;
|
||||||
@@ -539,6 +550,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return EvaluateSpecialMaxCandidatesCpu(stackBuffer, factorSpan, phi, prime, divisorData);
|
return EvaluateSpecialMaxCandidatesCpu(stackBuffer, factorSpan, phi, prime, divisorData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TrySpecialMaxHybrid(PrimeOrderCalculatorAccelerator gpu, ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
private static bool TrySpecialMaxHybrid(PrimeOrderCalculatorAccelerator gpu, ulong phi, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
int length = factors.Count;
|
int length = factors.Count;
|
||||||
@@ -560,6 +572,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return EvaluateSpecialMaxCandidatesGpu(gpu, factorSpan, phi, prime, divisorData);
|
return EvaluateSpecialMaxCandidatesGpu(gpu, factorSpan, phi, prime, divisorData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool EvaluateSpecialMaxCandidatesCpu(Span<ulong> buffer, ReadOnlySpan<ulong> factors, ulong phi, ulong prime, in MontgomeryDivisorData divisorData)
|
private static bool EvaluateSpecialMaxCandidatesCpu(Span<ulong> buffer, ReadOnlySpan<ulong> factors, ulong phi, ulong prime, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
int factorCount = factors.Length;
|
int factorCount = factors.Length;
|
||||||
@@ -604,13 +617,14 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong InitializeStartingOrderCpu(ulong prime, ulong phi, in MontgomeryDivisorData divisorData)
|
private static ulong InitializeStartingOrderCpu(ulong prime, ulong phi, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
ulong order = phi;
|
ulong order = phi;
|
||||||
if ((prime & 7UL) == 1UL || (prime & 7UL) == 7UL)
|
if ((prime & 7UL) == 1UL || (prime & 7UL) == 7UL)
|
||||||
{
|
{
|
||||||
ulong half = phi >> 1;
|
ulong half = phi >> 1;
|
||||||
if (Pow2EqualsOneCpu(half, prime, divisorData))
|
if (Pow2EqualsOneCpu(half, divisorData))
|
||||||
{
|
{
|
||||||
order = half;
|
order = half;
|
||||||
}
|
}
|
||||||
@@ -619,6 +633,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong InitializeStartingOrderHybrid(PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong phi, in MontgomeryDivisorData divisorData)
|
private static ulong InitializeStartingOrderHybrid(PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong phi, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
ulong order = phi;
|
ulong order = phi;
|
||||||
@@ -634,14 +649,16 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong ExponentLoweringCpu(ulong order, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
private static ulong ExponentLoweringCpu(ulong order, ulong prime, PartialFactorResult factors, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
ReadOnlySpan<ulong> factorSpan = factors.Factors;
|
ReadOnlySpan<ulong> factorSpan = factors.Factors;
|
||||||
ReadOnlySpan<int> exponentsSpan = factors.Exponents;
|
ReadOnlySpan<int> exponentsSpan = factors.Exponents;
|
||||||
|
|
||||||
int length = factors.Count;
|
int length = factors.Count;
|
||||||
ulong[] tempFactorsArray = Pools.ExclusiveUlongArray.Rent(length + 1);
|
int newLength = length + 1;
|
||||||
int[] tempExponentsArray = Pools.ExclusiveIntArray.Rent(length + 1);
|
ulong[] tempFactorsArray = Pools.ExclusiveUlongArray.Rent(newLength);
|
||||||
|
int[] tempExponentsArray = Pools.ExclusiveIntArray.Rent(newLength);
|
||||||
|
|
||||||
Span<ulong> ulongBuffer = tempFactorsArray;
|
Span<ulong> ulongBuffer = tempFactorsArray;
|
||||||
factorSpan.CopyTo(ulongBuffer);
|
factorSpan.CopyTo(ulongBuffer);
|
||||||
@@ -652,7 +669,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
{
|
{
|
||||||
ulongBuffer[length] = factors.Cofactor;
|
ulongBuffer[length] = factors.Cofactor;
|
||||||
intBuffer[length] = 1;
|
intBuffer[length] = 1;
|
||||||
length++;
|
length = newLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.Sort(tempFactorsArray, tempExponentsArray, 0, length);
|
Array.Sort(tempFactorsArray, tempExponentsArray, 0, length);
|
||||||
@@ -706,6 +723,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void ProcessExponentLoweringPrime(Span<ulong> candidateBuffer, Span<bool> evaluationBuffer, ref ulong order, ulong primeFactor, int exponent, ref ExponentRemainderStepperCpu stepper)
|
private static void ProcessExponentLoweringPrime(Span<ulong> candidateBuffer, Span<bool> evaluationBuffer, ref ulong order, ulong primeFactor, int exponent, ref ExponentRemainderStepperCpu stepper)
|
||||||
{
|
{
|
||||||
ulong working = order;
|
ulong working = order;
|
||||||
@@ -756,6 +774,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryConfirmOrderCpu(
|
private static bool TryConfirmOrderCpu(
|
||||||
ulong prime,
|
ulong prime,
|
||||||
ulong order,
|
ulong order,
|
||||||
@@ -765,12 +784,8 @@ internal static partial class PrimeOrderCalculator
|
|||||||
{
|
{
|
||||||
reusableFactorization = null;
|
reusableFactorization = null;
|
||||||
|
|
||||||
if (order == 0UL)
|
ArgumentOutOfRangeException.ThrowIfEqual(order, 0UL);
|
||||||
{
|
if (!Pow2EqualsOneCpu(order, divisorData))
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Pow2EqualsOneCpu(order, prime, divisorData))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -803,6 +818,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryConfirmOrderHybrid(
|
private static bool TryConfirmOrderHybrid(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
@@ -851,6 +867,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool ValidateOrderAgainstFactors(
|
private static bool ValidateOrderAgainstFactors(
|
||||||
ulong prime,
|
ulong prime,
|
||||||
ulong order,
|
ulong order,
|
||||||
@@ -916,6 +933,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return !violates;
|
return !violates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool ValidateOrderForFactor(Span<ulong> buffer, ulong primeFactor, int exponent, ulong order, ref ExponentRemainderStepperCpu stepper)
|
private static bool ValidateOrderForFactor(Span<ulong> buffer, ulong primeFactor, int exponent, ulong order, ref ExponentRemainderStepperCpu stepper)
|
||||||
{
|
{
|
||||||
ulong working = order;
|
ulong working = order;
|
||||||
@@ -964,13 +982,13 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryHeuristicFinishCpu(
|
private static bool TryHeuristicFinishCpu(
|
||||||
ulong prime,
|
ulong prime,
|
||||||
ulong order,
|
ulong order,
|
||||||
ulong? previousOrder,
|
ulong? previousOrder,
|
||||||
in MontgomeryDivisorData divisorData,
|
in MontgomeryDivisorData divisorData,
|
||||||
in PrimeOrderCalculatorConfig config,
|
in PrimeOrderCalculatorConfig config,
|
||||||
PartialFactorResult phiFactors,
|
|
||||||
PartialFactorResult? cachedOrderFactors,
|
PartialFactorResult? cachedOrderFactors,
|
||||||
out ulong result)
|
out ulong result)
|
||||||
{
|
{
|
||||||
@@ -1005,7 +1023,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks << 2;
|
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecksCapacity;
|
||||||
List<ulong> candidates = ThreadStaticPools.RentUlongList(capacity);
|
List<ulong> candidates = ThreadStaticPools.RentUlongList(capacity);
|
||||||
candidates.Clear();
|
candidates.Clear();
|
||||||
ulong[] factorArray = orderFactors.Factors!;
|
ulong[] factorArray = orderFactors.Factors!;
|
||||||
@@ -1025,29 +1043,11 @@ internal static partial class PrimeOrderCalculator
|
|||||||
int powUsed = 0;
|
int powUsed = 0;
|
||||||
Span<ulong> candidateSpan = CollectionsMarshal.AsSpan(candidates);
|
Span<ulong> candidateSpan = CollectionsMarshal.AsSpan(candidates);
|
||||||
ExponentRemainderStepperCpu powStepper = ThreadStaticPools.RentExponentStepperCpu(divisorData);
|
ExponentRemainderStepperCpu powStepper = ThreadStaticPools.RentExponentStepperCpu(divisorData);
|
||||||
bool powStepperInitialized = false;
|
|
||||||
|
|
||||||
int index = 0;
|
ulong candidate = candidateSpan[0];
|
||||||
while (index < candidateCount && powUsed < powBudget)
|
|
||||||
{
|
|
||||||
int remaining = candidateCount - index;
|
|
||||||
int budgetRemaining = powBudget - powUsed;
|
|
||||||
int batchSize = Math.Min(remaining, Math.Min(budgetRemaining, PrimeOrderConstants.MaxGpuBatchSize));
|
|
||||||
if (batchSize <= 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadOnlySpan<ulong> batch = candidateSpan.Slice(index, batchSize);
|
|
||||||
|
|
||||||
int startIndex = 0;
|
|
||||||
if (!powStepperInitialized)
|
|
||||||
{
|
|
||||||
ulong candidate = batch[0];
|
|
||||||
powUsed++;
|
powUsed++;
|
||||||
|
|
||||||
bool equalsOne = powStepper.InitializeCpuIsUnity(candidate);
|
bool equalsOne = powStepper.InitializeCpuIsUnity(candidate);
|
||||||
powStepperInitialized = true;
|
|
||||||
if (equalsOne && TryConfirmCandidateCpu(prime, candidate, divisorData, config, ref powUsed, powBudget))
|
if (equalsOne && TryConfirmCandidateCpu(prime, candidate, divisorData, config, ref powUsed, powBudget))
|
||||||
{
|
{
|
||||||
candidates.Clear();
|
candidates.Clear();
|
||||||
@@ -1057,15 +1057,19 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
startIndex = 1;
|
int index = 1;
|
||||||
|
while (index < candidateCount && powUsed < powBudget)
|
||||||
|
{
|
||||||
|
int budgetRemaining = powBudget - powUsed;
|
||||||
|
if (budgetRemaining <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = startIndex; i < batchSize && powUsed < powBudget; i++)
|
candidate = candidateSpan[index++];
|
||||||
{
|
|
||||||
ulong candidate = batch[i];
|
|
||||||
powUsed++;
|
powUsed++;
|
||||||
|
|
||||||
bool equalsOne = powStepper.ComputeNextIsUnity(candidate);
|
equalsOne = powStepper.ComputeNextIsUnity(candidate);
|
||||||
if (!equalsOne)
|
if (!equalsOne)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -1081,9 +1085,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
ThreadStaticPools.ReturnExponentStepperCpu(powStepper);
|
ThreadStaticPools.ReturnExponentStepperCpu(powStepper);
|
||||||
result = candidate;
|
result = candidate;
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
index += batchSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
candidates.Clear();
|
candidates.Clear();
|
||||||
@@ -1098,6 +1100,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryHeuristicFinishHybrid(
|
private static bool TryHeuristicFinishHybrid(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
@@ -1135,7 +1138,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks << 2;
|
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecksCapacity;
|
||||||
List<ulong> candidates = ThreadStaticPools.RentUlongList(capacity);
|
List<ulong> candidates = ThreadStaticPools.RentUlongList(capacity);
|
||||||
candidates.Clear();
|
candidates.Clear();
|
||||||
ulong[] factorArray = orderFactors.Factors!;
|
ulong[] factorArray = orderFactors.Factors!;
|
||||||
@@ -1230,6 +1233,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryHeuristicFinishGpu(
|
private static bool TryHeuristicFinishGpu(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ulong prime,
|
ulong prime,
|
||||||
@@ -1267,7 +1271,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks << 2;
|
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecksCapacity;
|
||||||
List<ulong> candidates = ThreadStaticPools.RentUlongList(capacity);
|
List<ulong> candidates = ThreadStaticPools.RentUlongList(capacity);
|
||||||
candidates.Clear();
|
candidates.Clear();
|
||||||
ulong[] factorArray = orderFactors.Factors!;
|
ulong[] factorArray = orderFactors.Factors!;
|
||||||
@@ -1428,6 +1432,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void SortCandidates(ulong prime, ulong? previousOrder, List<ulong> candidates)
|
private static void SortCandidates(ulong prime, ulong? previousOrder, List<ulong> candidates)
|
||||||
{
|
{
|
||||||
ulong previous = previousOrder ?? 0UL;
|
ulong previous = previousOrder ?? 0UL;
|
||||||
@@ -1437,56 +1442,73 @@ internal static partial class PrimeOrderCalculator
|
|||||||
ulong threshold3 = (prime * 3UL) >> 3;
|
ulong threshold3 = (prime * 3UL) >> 3;
|
||||||
int previousGroup = hasPrevious ? GetGroup(previous, threshold1, threshold2, threshold3) : 1;
|
int previousGroup = hasPrevious ? GetGroup(previous, threshold1, threshold2, threshold3) : 1;
|
||||||
|
|
||||||
candidates.Sort((x, y) =>
|
candidates.Sort((x, y) => CompareCandidates(x, y, previous, previousGroup, hasPrevious, threshold1, threshold2, threshold3));
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
|
private static int CompareCandidates(ulong left, ulong right, ulong previous, int previousGroup, bool hasPrevious, ulong threshold1, ulong threshold2, ulong threshold3)
|
||||||
{
|
{
|
||||||
CandidateKey keyX = BuildKey(x, previous, previousGroup, hasPrevious, threshold1, threshold2, threshold3);
|
int leftGroup = GetGroup(left, threshold1, threshold2, threshold3);
|
||||||
CandidateKey keyY = BuildKey(y, previous, previousGroup, hasPrevious, threshold1, threshold2, threshold3);
|
int rightGroup = GetGroup(right, threshold1, threshold2, threshold3);
|
||||||
int compare = keyX.Primary.CompareTo(keyY.Primary);
|
if (leftGroup == 0)
|
||||||
|
{
|
||||||
|
return rightGroup == 0 ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rightGroup == 0)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool leftIsGe = !hasPrevious || left >= previous;
|
||||||
|
bool rightIsGe = !hasPrevious || right >= previous;
|
||||||
|
int leftPrimary = ComputePrimary(leftGroup, leftIsGe, previousGroup);
|
||||||
|
int rightPrimary = ComputePrimary(rightGroup, rightIsGe, previousGroup);
|
||||||
|
|
||||||
|
int compare = leftPrimary.CompareTo(rightPrimary);
|
||||||
if (compare != 0)
|
if (compare != 0)
|
||||||
{
|
{
|
||||||
return compare;
|
return compare;
|
||||||
}
|
}
|
||||||
|
|
||||||
compare = keyX.Secondary.CompareTo(keyY.Secondary);
|
long leftSecondary;
|
||||||
if (compare != 0)
|
long leftTertiary;
|
||||||
|
if (leftGroup == 3)
|
||||||
{
|
{
|
||||||
return compare;
|
leftSecondary = -(long)left;
|
||||||
}
|
leftTertiary = -(long)left;
|
||||||
|
|
||||||
return keyX.Tertiary.CompareTo(keyY.Tertiary);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static CandidateKey BuildKey(ulong value, ulong previous, int previousGroup, bool hasPrevious, ulong threshold1, ulong threshold2, ulong threshold3)
|
|
||||||
{
|
|
||||||
int group = GetGroup(value, threshold1, threshold2, threshold3);
|
|
||||||
if (group == 0)
|
|
||||||
{
|
|
||||||
return CandidateKey.Max;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isGe = !hasPrevious || value >= previous;
|
|
||||||
int primary = ComputePrimary(group, isGe, previousGroup);
|
|
||||||
long secondary;
|
|
||||||
long tertiary;
|
|
||||||
|
|
||||||
if (group == 3)
|
|
||||||
{
|
|
||||||
secondary = -(long)value;
|
|
||||||
tertiary = -(long)value;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ulong reference = hasPrevious ? previous : 0UL;
|
ulong leftReference = hasPrevious ? (left > previous ? left - previous : previous - left) : left;
|
||||||
reference = hasPrevious ? (value > reference ? value - reference : reference - value) : value;
|
leftSecondary = (long)leftReference;
|
||||||
secondary = (long)reference;
|
leftTertiary = (long)left;
|
||||||
tertiary = (long)value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new CandidateKey(primary, secondary, tertiary);
|
long rightSecondary;
|
||||||
|
long rightTertiary;
|
||||||
|
if (rightGroup == 3)
|
||||||
|
{
|
||||||
|
rightSecondary = -(long)right;
|
||||||
|
rightTertiary = -(long)right;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ulong rightReference = hasPrevious ? (right > previous ? right - previous : previous - right) : right;
|
||||||
|
rightSecondary = (long)rightReference;
|
||||||
|
rightTertiary = (long)right;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
compare = leftSecondary.CompareTo(rightSecondary);
|
||||||
|
if (compare != 0)
|
||||||
|
{
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
|
||||||
|
return leftTertiary.CompareTo(rightTertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static int ComputePrimary(int group, bool isGe, int previousGroup)
|
private static int ComputePrimary(int group, bool isGe, int previousGroup)
|
||||||
{
|
{
|
||||||
int groupOffset = group switch
|
int groupOffset = group switch
|
||||||
@@ -1510,7 +1532,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return groupOffset + (isGe ? 0 : 1);
|
return groupOffset + (isGe ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static int GetGroup(ulong value, ulong threshold1, ulong threshold2, ulong threshold3)
|
private static int GetGroup(ulong value, ulong threshold1, ulong threshold2, ulong threshold3)
|
||||||
{
|
{
|
||||||
if (value <= threshold1)
|
if (value <= threshold1)
|
||||||
@@ -1531,6 +1553,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void BuildCandidates(ulong order, ulong[] factors, int[] exponents, int count, List<ulong> candidates, int limit)
|
private static void BuildCandidates(ulong order, ulong[] factors, int[] exponents, int count, List<ulong> candidates, int limit)
|
||||||
{
|
{
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@@ -1542,7 +1565,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
BuildCandidatesRecursive(order, factors, exponents, 0, 1UL, candidates, limit);
|
BuildCandidatesRecursive(order, factors, exponents, 0, 1UL, candidates, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// private static void BuildCandidatesRecursive(ulong order, in ReadOnlySpan<FactorEntry> factors, int index, ulong divisorProduct, List<ulong> candidates, int limit)
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void BuildCandidatesRecursive(ulong order, in ulong[] factors, in int[] exponents, int index, ulong divisorProduct, List<ulong> candidates, int limit)
|
private static void BuildCandidatesRecursive(ulong order, in ulong[] factors, in int[] exponents, int index, ulong divisorProduct, List<ulong> candidates, int limit)
|
||||||
{
|
{
|
||||||
if (candidates.Count >= limit)
|
if (candidates.Count >= limit)
|
||||||
@@ -1603,6 +1626,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryConfirmCandidateCpu(ulong prime, ulong candidate, in MontgomeryDivisorData divisorData, in PrimeOrderCalculatorConfig config, ref int powUsed, int powBudget)
|
private static bool TryConfirmCandidateCpu(ulong prime, ulong candidate, in MontgomeryDivisorData divisorData, in PrimeOrderCalculatorConfig config, ref int powUsed, int powBudget)
|
||||||
{
|
{
|
||||||
PartialFactorResult factorization = PartialFactorCpu(candidate, config);
|
PartialFactorResult factorization = PartialFactorCpu(candidate, config);
|
||||||
@@ -1682,6 +1706,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return !violates;
|
return !violates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryConfirmCandidateHybrid(PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong candidate, in MontgomeryDivisorData divisorData, in PrimeOrderCalculatorConfig config, ref int powUsed, int powBudget)
|
private static bool TryConfirmCandidateHybrid(PrimeOrderCalculatorAccelerator gpu, ulong prime, ulong candidate, in MontgomeryDivisorData divisorData, in PrimeOrderCalculatorConfig config, ref int powUsed, int powBudget)
|
||||||
{
|
{
|
||||||
PartialFactorResult factorization = PartialFactorHybrid(gpu, candidate, config);
|
PartialFactorResult factorization = PartialFactorHybrid(gpu, candidate, config);
|
||||||
@@ -1760,6 +1785,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return !violates;
|
return !violates;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool CheckCandidateViolation(Span<ulong> buffer, ulong primeFactor, int exponent, ulong candidate, ulong prime, ref int powUsed, int powBudget, ref ExponentRemainderStepperCpu stepper)
|
private static bool CheckCandidateViolation(Span<ulong> buffer, ulong primeFactor, int exponent, ulong candidate, ulong prime, ref int powUsed, int powBudget, ref ExponentRemainderStepperCpu stepper)
|
||||||
{
|
{
|
||||||
ulong working = candidate;
|
ulong working = candidate;
|
||||||
@@ -1841,10 +1867,11 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool Pow2EqualsOneCpu(ulong exponent, ulong prime, in MontgomeryDivisorData divisorData)
|
private static bool Pow2EqualsOneCpu(ulong exponent, in MontgomeryDivisorData divisorData)
|
||||||
=> exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
=> exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool Pow2EqualsOneHybrid(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, in MontgomeryDivisorData divisorData)
|
private static bool Pow2EqualsOneHybrid(PrimeOrderCalculatorAccelerator gpu, ulong exponent, ulong prime, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
// if (exponent >= PerfectNumberConstants.MaxQForDivisorCycles || prime >= PerfectNumberConstants.MaxQForDivisorCycles)
|
// if (exponent >= PerfectNumberConstants.MaxQForDivisorCycles || prime >= PerfectNumberConstants.MaxQForDivisorCycles)
|
||||||
@@ -1869,6 +1896,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
private static readonly ulong[] _emptyUlongArray = [];
|
private static readonly ulong[] _emptyUlongArray = [];
|
||||||
private static readonly int[] _emptyIntArray = [];
|
private static readonly int[] _emptyIntArray = [];
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static PartialFactorResult PartialFactorCpu(ulong value, in PrimeOrderCalculatorConfig config)
|
private static PartialFactorResult PartialFactorCpu(ulong value, in PrimeOrderCalculatorConfig config)
|
||||||
{
|
{
|
||||||
if (value <= 1UL)
|
if (value <= 1UL)
|
||||||
@@ -1884,8 +1912,8 @@ internal static partial class PrimeOrderCalculator
|
|||||||
// primeSlots.Clear();
|
// primeSlots.Clear();
|
||||||
// exponentSlots.Clear();
|
// exponentSlots.Clear();
|
||||||
|
|
||||||
|
ArgumentOutOfRangeException.ThrowIfEqual(config.SmallFactorLimit, 0U);
|
||||||
uint limit = config.SmallFactorLimit == 0 ? uint.MaxValue : config.SmallFactorLimit;
|
uint limit = config.SmallFactorLimit == 0 ? uint.MaxValue : config.SmallFactorLimit;
|
||||||
ulong remaining = value;
|
|
||||||
|
|
||||||
List<PendingEntry> pending = ThreadStaticPools.RentPrimeOrderPendingEntryList(PrimeOrderConstants.GpuSmallPrimeFactorSlots);
|
List<PendingEntry> pending = ThreadStaticPools.RentPrimeOrderPendingEntryList(PrimeOrderConstants.GpuSmallPrimeFactorSlots);
|
||||||
|
|
||||||
@@ -1895,7 +1923,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
primeSlots,
|
primeSlots,
|
||||||
exponentSlots,
|
exponentSlots,
|
||||||
out int factorCount,
|
out int factorCount,
|
||||||
out remaining);
|
out ulong remaining);
|
||||||
|
|
||||||
bool limitReached;
|
bool limitReached;
|
||||||
if (remaining > 1UL)
|
if (remaining > 1UL)
|
||||||
@@ -2033,6 +2061,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static PartialFactorResult PartialFactorHybrid(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderCalculatorConfig config)
|
private static PartialFactorResult PartialFactorHybrid(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderCalculatorConfig config)
|
||||||
{
|
{
|
||||||
if (value <= 1UL)
|
if (value <= 1UL)
|
||||||
@@ -2205,6 +2234,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static PartialFactorResult PartialFactorGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderCalculatorConfig config)
|
private static PartialFactorResult PartialFactorGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, in PrimeOrderCalculatorConfig config)
|
||||||
{
|
{
|
||||||
if (value <= 1UL)
|
if (value <= 1UL)
|
||||||
@@ -2382,7 +2412,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void CollectFactorsHybrid(PrimeOrderCalculatorAccelerator gpu, Span<ulong> primeSlots, Span<int> exponentSlots, ref ulong[] primeSlotArray, ref int[] exponentSlotArray, ref int factorCount, List<PendingEntry> pending, Stack<ulong> compositeStack, long deadlineTimestamp, out bool pollardRhoDeadlineReached)
|
private static void CollectFactorsHybrid(PrimeOrderCalculatorAccelerator gpu, Span<ulong> primeSlots, Span<int> exponentSlots, ref ulong[] primeSlotArray, ref int[] exponentSlotArray, ref int factorCount, List<PendingEntry> pending, Stack<ulong> compositeStack, long deadlineTimestamp, out bool pollardRhoDeadlineReached)
|
||||||
{
|
{
|
||||||
while (compositeStack.Count > 0)
|
while (compositeStack.Count > 0)
|
||||||
@@ -2417,7 +2447,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
pollardRhoDeadlineReached = false;
|
pollardRhoDeadlineReached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void CollectFactorsCpu(Span<ulong> primeSlots, Span<int> exponentSlots, ref int factorCount, List<PendingEntry> pending, Stack<ulong> compositeStack, long deadlineTimestamp, out bool pollardRhoDeadlineReached)
|
private static void CollectFactorsCpu(Span<ulong> primeSlots, Span<int> exponentSlots, ref int factorCount, List<PendingEntry> pending, Stack<ulong> compositeStack, long deadlineTimestamp, out bool pollardRhoDeadlineReached)
|
||||||
{
|
{
|
||||||
while (compositeStack.Count > 0)
|
while (compositeStack.Count > 0)
|
||||||
@@ -2452,7 +2482,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
pollardRhoDeadlineReached = false;
|
pollardRhoDeadlineReached = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void CollectFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ref Span<ulong> primeSlots, ref Span<int> exponentSlots, ref ulong[] primeSlotArray, ref int[] exponentSlotArray, ref int factorCount, List<PendingEntry> pending, Stack<ulong> compositeStack, long deadlineTimestamp, ref bool pollardRhoDeadlineReached)
|
private static void CollectFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ref Span<ulong> primeSlots, ref Span<int> exponentSlots, ref ulong[] primeSlotArray, ref int[] exponentSlotArray, ref int factorCount, List<PendingEntry> pending, Stack<ulong> compositeStack, long deadlineTimestamp, ref bool pollardRhoDeadlineReached)
|
||||||
{
|
{
|
||||||
while (compositeStack.Count > 0)
|
while (compositeStack.Count > 0)
|
||||||
@@ -2487,6 +2517,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool RunOnCpu()
|
private static bool RunOnCpu()
|
||||||
{
|
{
|
||||||
if (PerfectNumberConstants.GpuRatio == 0)
|
if (PerfectNumberConstants.GpuRatio == 0)
|
||||||
@@ -2525,6 +2556,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return cpuCount != PerfectNumberConstants.GpuRatio;
|
return cpuCount != PerfectNumberConstants.GpuRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void PopulateSmallPrimeFactorsCpu(
|
private static void PopulateSmallPrimeFactorsCpu(
|
||||||
ulong value,
|
ulong value,
|
||||||
uint limit,
|
uint limit,
|
||||||
@@ -2534,48 +2566,45 @@ internal static partial class PrimeOrderCalculator
|
|||||||
out ulong remaining)
|
out ulong remaining)
|
||||||
{
|
{
|
||||||
factorCount = 0;
|
factorCount = 0;
|
||||||
ulong remainingLocal = value;
|
|
||||||
|
|
||||||
if (value <= 1UL)
|
if (value <= 1UL)
|
||||||
{
|
{
|
||||||
remaining = remainingLocal;
|
remaining = value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint[] primes = PrimesGenerator.SmallPrimes;
|
uint[] primes = PrimesGenerator.SmallPrimes;
|
||||||
ulong[] squares = PrimesGenerator.SmallPrimesPow2;
|
ulong[] squares = PrimesGenerator.SmallPrimesPow2;
|
||||||
int primeCount = primes.Length;
|
int primeCount = primes.Length;
|
||||||
uint effectiveLimit = limit == 0 ? uint.MaxValue : limit;
|
|
||||||
|
|
||||||
for (int i = 0; i < primeCount && remainingLocal > 1UL; i++)
|
for (int i = 0; i < primeCount && value > 1UL; i++)
|
||||||
{
|
{
|
||||||
uint primeCandidate = primes[i];
|
uint primeCandidate = primes[i];
|
||||||
if (primeCandidate > effectiveLimit)
|
if (primeCandidate > limit)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong primeSquare = squares[i];
|
ulong primeValue = squares[i];
|
||||||
// primeSquare will never == 0 in production code
|
// primeSquare will never == 0 in production code
|
||||||
// if (primeSquare != 0 && primeSquare > remainingLocal)
|
// if (primeSquare != 0 && primeSquare > remainingLocal)
|
||||||
if (primeSquare > remainingLocal)
|
if (primeValue > value)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong primeValue = primeCandidate;
|
primeValue = primeCandidate;
|
||||||
// primeCandidate will never equal 0 in production code
|
// primeCandidate will never equal 0 in production code
|
||||||
// if (primeCandidate == 0UL)
|
// if (primeCandidate == 0UL)
|
||||||
// {
|
// {
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (remainingLocal.ReduceCycleRemainder(primeValue) != 0UL)
|
if (value.ReduceCycleRemainder(primeValue) != 0UL)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int exponent = ExtractSmallPrimeExponent(ref remainingLocal, primeValue);
|
int exponent = ExtractSmallPrimeExponent(ref value, primeValue);
|
||||||
if (exponent == 0)
|
if (exponent == 0)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -2590,10 +2619,10 @@ internal static partial class PrimeOrderCalculator
|
|||||||
factorCount++;
|
factorCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
remaining = remainingLocal;
|
remaining = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
// Unroll the initial divisions because small exponents dominate in practice.
|
// Unroll the initial divisions because small exponents dominate in practice.
|
||||||
private static int ExtractSmallPrimeExponent(ref ulong value, ulong primeValue)
|
private static int ExtractSmallPrimeExponent(ref ulong value, ulong primeValue)
|
||||||
{
|
{
|
||||||
@@ -2658,6 +2687,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return exponent;
|
return exponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static long CreateDeadlineTimestamp(int milliseconds)
|
private static long CreateDeadlineTimestamp(int milliseconds)
|
||||||
{
|
{
|
||||||
if (milliseconds <= 0)
|
if (milliseconds <= 0)
|
||||||
@@ -2665,9 +2695,9 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return long.MaxValue;
|
return long.MaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
long stopwatchTicks = ConvertMillisecondsToStopwatchTicks(milliseconds);
|
|
||||||
long startTimestamp = Stopwatch.GetTimestamp();
|
long startTimestamp = Stopwatch.GetTimestamp();
|
||||||
long deadline = startTimestamp + stopwatchTicks;
|
long deadline = ConvertMillisecondsToStopwatchTicks(milliseconds);
|
||||||
|
deadline += startTimestamp;
|
||||||
if (deadline < startTimestamp)
|
if (deadline < startTimestamp)
|
||||||
{
|
{
|
||||||
return long.MaxValue;
|
return long.MaxValue;
|
||||||
@@ -2676,7 +2706,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return deadline;
|
return deadline;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static long ConvertMillisecondsToStopwatchTicks(int milliseconds)
|
private static long ConvertMillisecondsToStopwatchTicks(int milliseconds)
|
||||||
{
|
{
|
||||||
long frequency = Stopwatch.Frequency;
|
long frequency = Stopwatch.Frequency;
|
||||||
@@ -2685,6 +2715,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return baseTicks + (remainder / 1000L);
|
return baseTicks + (remainder / 1000L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryPollardRhoCpu(ulong n, long deadlineTimestamp, out ulong factor)
|
private static bool TryPollardRhoCpu(ulong n, long deadlineTimestamp, out ulong factor)
|
||||||
{
|
{
|
||||||
factor = 0UL;
|
factor = 0UL;
|
||||||
@@ -2724,22 +2755,23 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong AdvancePolynomialCpu(ulong x, ulong c, ulong modulus)
|
private static ulong AdvancePolynomialCpu(ulong x, ulong c, ulong modulus)
|
||||||
{
|
{
|
||||||
UInt128 value = (UInt128)x * x + c;
|
UInt128 value = (UInt128)x * x + c;
|
||||||
return (ulong)value.ReduceCycleRemainder(modulus);
|
return (ulong)value.ReduceCycleRemainder(modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong AdvancePolynomialTwiceCpu(ulong x, ulong c, ulong modulus)
|
private static ulong AdvancePolynomialTwiceCpu(ulong x, ulong c, ulong modulus)
|
||||||
{
|
{
|
||||||
UInt128 value = (UInt128)x * x + c;
|
UInt128 value = (UInt128)x * x + c;
|
||||||
var remainder = (ulong)value.ReduceCycleRemainder(modulus);
|
x = (ulong)value.ReduceCycleRemainder(modulus);
|
||||||
value = (UInt128)remainder * remainder + c;
|
value = (UInt128)x * x + c;
|
||||||
return (ulong)value.ReduceCycleRemainder(modulus);
|
return (ulong)value.ReduceCycleRemainder(modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong BinaryGcd(ulong a, ulong b)
|
private static ulong BinaryGcd(ulong a, ulong b)
|
||||||
{
|
{
|
||||||
if (a == 0UL)
|
if (a == 0UL)
|
||||||
@@ -2771,6 +2803,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void AddFactor(Dictionary<ulong, int> counts, ulong prime, int exponent)
|
private static void AddFactor(Dictionary<ulong, int> counts, ulong prime, int exponent)
|
||||||
{
|
{
|
||||||
if (counts.TryGetValue(prime, out int existing))
|
if (counts.TryGetValue(prime, out int existing))
|
||||||
@@ -2783,6 +2816,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void AddFactorToCollector(
|
private static void AddFactorToCollector(
|
||||||
Span<ulong> primes,
|
Span<ulong> primes,
|
||||||
Span<int> exponents,
|
Span<int> exponents,
|
||||||
@@ -2813,7 +2847,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void EnsureCollectorCapacity(
|
private static void EnsureCollectorCapacity(
|
||||||
Span<ulong> primes,
|
Span<ulong> primes,
|
||||||
int requiredCapacity)
|
int requiredCapacity)
|
||||||
@@ -2821,6 +2855,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
ArgumentOutOfRangeException.ThrowIfGreaterThan(requiredCapacity, primes.Length);
|
ArgumentOutOfRangeException.ThrowIfGreaterThan(requiredCapacity, primes.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong CalculateByFactorizationCpu(ulong prime, in MontgomeryDivisorData divisorData)
|
private static ulong CalculateByFactorizationCpu(ulong prime, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
ulong phi = prime - 1UL;
|
ulong phi = prime - 1UL;
|
||||||
@@ -2868,6 +2903,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void FactorCompletelyCpu(ulong value, Dictionary<ulong, int> counts, bool knownComposite)
|
private static void FactorCompletelyCpu(ulong value, Dictionary<ulong, int> counts, bool knownComposite)
|
||||||
{
|
{
|
||||||
if (value <= 1UL)
|
if (value <= 1UL)
|
||||||
@@ -2927,6 +2963,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong PollardRhoStrict(ulong n)
|
private static ulong PollardRhoStrict(ulong n)
|
||||||
{
|
{
|
||||||
if ((n & 1UL) == 0UL)
|
if ((n & 1UL) == 0UL)
|
||||||
@@ -2944,8 +2981,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
while (d == 1UL)
|
while (d == 1UL)
|
||||||
{
|
{
|
||||||
x = AdvancePolynomialCpu(x, c, n);
|
x = AdvancePolynomialCpu(x, c, n);
|
||||||
y = AdvancePolynomialCpu(y, c, n);
|
y = AdvancePolynomialTwiceCpu(y, c, n);
|
||||||
y = AdvancePolynomialCpu(y, c, n);
|
|
||||||
ulong diff = x > y ? x - y : y - x;
|
ulong diff = x > y ? x - y : y - x;
|
||||||
d = BinaryGcd(diff, n);
|
d = BinaryGcd(diff, n);
|
||||||
}
|
}
|
||||||
@@ -2957,6 +2993,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 Pow2ModWideCpu(in UInt128 exponent, in UInt128 modulus, in MontgomeryDivisorData? divisorData)
|
private static UInt128 Pow2ModWideCpu(in UInt128 exponent, in UInt128 modulus, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
if (modulus == UInt128.One)
|
if (modulus == UInt128.One)
|
||||||
@@ -2967,6 +3004,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return exponent.Pow2MontgomeryModWindowed(modulus);
|
return exponent.Pow2MontgomeryModWindowed(modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryConfirmCandidateWideCpu(in UInt128 prime, in UInt128 candidate, in PrimeOrderCalculatorConfig config, ref int powUsed, int powBudget, in MontgomeryDivisorData? divisorData)
|
private static bool TryConfirmCandidateWideCpu(in UInt128 prime, in UInt128 candidate, in PrimeOrderCalculatorConfig config, ref int powUsed, int powBudget, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
PartialFactorResult128 factorization = PartialFactorWide(candidate, config);
|
PartialFactorResult128 factorization = PartialFactorWide(candidate, config);
|
||||||
@@ -3020,13 +3058,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly struct CandidateKey(int primary, long secondary, long tertiary)
|
|
||||||
{
|
|
||||||
public static readonly CandidateKey Max = new(int.MaxValue, long.MaxValue, long.MaxValue);
|
|
||||||
|
|
||||||
public readonly int Primary = primary;
|
|
||||||
public readonly long Secondary = secondary;
|
|
||||||
public readonly long Tertiary = tertiary;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using ILGPU;
|
using ILGPU;
|
||||||
using ILGPU.Runtime;
|
using ILGPU.Runtime;
|
||||||
using PerfectNumbers.Core.Gpu;
|
using PerfectNumbers.Core.Gpu;
|
||||||
@@ -86,6 +87,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 CalculateWideInternalGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
|
private static UInt128 CalculateWideInternalGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 prime, in UInt128? previousOrder, in MontgomeryDivisorData? divisorData, in PrimeOrderCalculatorConfig config)
|
||||||
{
|
{
|
||||||
if (prime <= UInt128.One)
|
if (prime <= UInt128.One)
|
||||||
@@ -361,7 +363,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
orderFactors = orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
orderFactors = orderFactors.WithAdditionalPrime(orderFactors.Cofactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecks * 4;
|
int capacity = config.MaxPowChecks <= 0 ? 64 : config.MaxPowChecksCapacity;
|
||||||
List<UInt128> candidates = new(capacity);
|
List<UInt128> candidates = new(capacity);
|
||||||
FactorEntry128[] factorArray = orderFactors.Factors!;
|
FactorEntry128[] factorArray = orderFactors.Factors!;
|
||||||
BuildCandidatesWide(order, factorArray, orderFactors.Count, candidates, capacity);
|
BuildCandidatesWide(order, factorArray, orderFactors.Count, candidates, capacity);
|
||||||
@@ -403,6 +405,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static ulong CalculateByFactorizationGpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, in MontgomeryDivisorData divisorData)
|
private static ulong CalculateByFactorizationGpu(PrimeOrderCalculatorAccelerator gpu, ulong prime, in MontgomeryDivisorData divisorData)
|
||||||
{
|
{
|
||||||
ulong phi = prime - 1UL;
|
ulong phi = prime - 1UL;
|
||||||
@@ -445,6 +448,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return order;
|
return order;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool TryPopulateSmallPrimeFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, uint limit, Dictionary<ulong, int> counts, out int factorCount, out ulong remaining)
|
private static bool TryPopulateSmallPrimeFactorsGpu(PrimeOrderCalculatorAccelerator gpu, ulong value, uint limit, Dictionary<ulong, int> counts, out int factorCount, out ulong remaining)
|
||||||
{
|
{
|
||||||
var primeBufferArray = ThreadStaticPools.UlongPool.Rent(GpuSmallPrimeFactorSlots);
|
var primeBufferArray = ThreadStaticPools.UlongPool.Rent(GpuSmallPrimeFactorSlots);
|
||||||
@@ -511,6 +515,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static bool EvaluateSpecialMaxCandidatesGpu(
|
private static bool EvaluateSpecialMaxCandidatesGpu(
|
||||||
PrimeOrderCalculatorAccelerator gpu,
|
PrimeOrderCalculatorAccelerator gpu,
|
||||||
ReadOnlySpan<ulong> factors,
|
ReadOnlySpan<ulong> factors,
|
||||||
@@ -548,6 +553,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
return result != 0;
|
return result != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
private static UInt128 Pow2ModWideGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 modulus, in MontgomeryDivisorData? divisorData)
|
private static UInt128 Pow2ModWideGpu(PrimeOrderCalculatorAccelerator gpu, in UInt128 exponent, in UInt128 modulus, in MontgomeryDivisorData? divisorData)
|
||||||
{
|
{
|
||||||
if (modulus == UInt128.One)
|
if (modulus == UInt128.One)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ internal static partial class PrimeOrderCalculator
|
|||||||
public readonly uint SmallFactorLimit = smallFactorLimit;
|
public readonly uint SmallFactorLimit = smallFactorLimit;
|
||||||
public readonly int PollardRhoMilliseconds = pollardRhoMilliseconds;
|
public readonly int PollardRhoMilliseconds = pollardRhoMilliseconds;
|
||||||
public readonly int MaxPowChecks = maxPowChecks;
|
public readonly int MaxPowChecks = maxPowChecks;
|
||||||
|
public readonly int MaxPowChecksCapacity = maxPowChecks << 2;
|
||||||
public readonly bool StrictMode = strictMode;
|
public readonly bool StrictMode = strictMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public sealed class PrimeTesterByLastDigit
|
|||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
private static bool _mod10Initialized;
|
private static bool _mod10Initialized;
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static byte GetMod10(ulong value)
|
private static byte GetMod10(ulong value)
|
||||||
{
|
{
|
||||||
if (!_mod10Initialized || _mod10Stepper.Modulus != 10UL)
|
if (!_mod10Initialized || _mod10Stepper.Modulus != 10UL)
|
||||||
@@ -24,6 +24,7 @@ public sealed class PrimeTesterByLastDigit
|
|||||||
return (byte)_mod10Stepper.Step(value);
|
return (byte)_mod10Stepper.Step(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||||
public static bool IsPrimeCpu(ulong n)
|
public static bool IsPrimeCpu(ulong n)
|
||||||
{
|
{
|
||||||
// The below IFs never trigger in production code of EvenPerfectBitScanner on --mersenne=bydivisor path.
|
// The below IFs never trigger in production code of EvenPerfectBitScanner on --mersenne=bydivisor path.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ namespace PerfectNumbers.Core;
|
|||||||
|
|
||||||
public static partial class ULongExtensions
|
public static partial class ULongExtensions
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWindowedKeepMontgomeryCpu(this ulong exponent, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModWindowedKeepMontgomeryCpu(this ulong exponent, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
@@ -75,7 +75,7 @@ public static partial class ULongExtensions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWindowedConvertToStandardCpu(this ulong exponent, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModWindowedConvertToStandardCpu(this ulong exponent, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
ulong modulus = divisor.Modulus;
|
ulong modulus = divisor.Modulus;
|
||||||
@@ -146,7 +146,7 @@ public static partial class ULongExtensions
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private static void InitializeMontgomeryOddPowersCpu(in MontgomeryDivisorData divisor, ulong modulus, ulong nPrime, Span<ulong> oddPowers)
|
private static void InitializeMontgomeryOddPowersCpu(in MontgomeryDivisorData divisor, ulong modulus, ulong nPrime, Span<ulong> oddPowers)
|
||||||
{
|
{
|
||||||
oddPowers[0] = divisor.MontgomeryTwo;
|
oddPowers[0] = divisor.MontgomeryTwo;
|
||||||
@@ -165,20 +165,20 @@ public static partial class ULongExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWithCycleConvertToStandardCpu(this ulong exponent, ulong cycleLength, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModWithCycleConvertToStandardCpu(this ulong exponent, ulong cycleLength, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
ulong rotationCount = exponent % cycleLength;
|
ulong rotationCount = exponent % cycleLength;
|
||||||
return Pow2MontgomeryModWindowedConvertToStandardCpu(rotationCount, divisor);
|
return Pow2MontgomeryModWindowedConvertToStandardCpu(rotationCount, divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModFromCycleRemainderCpu(this ulong reducedExponent, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModFromCycleRemainderCpu(this ulong reducedExponent, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
return Pow2MontgomeryModWindowedConvertToStandardCpu(reducedExponent, divisor);
|
return Pow2MontgomeryModWindowedConvertToStandardCpu(reducedExponent, divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong CalculateMersenneDivisorCycleLengthUnrolledHexCpu(this ulong divisor)
|
public static ulong CalculateMersenneDivisorCycleLengthUnrolledHexCpu(this ulong divisor)
|
||||||
{
|
{
|
||||||
// EvenPerfectBitScanner only routes odd divisors here; keep the guard commented out for benchmarks.
|
// EvenPerfectBitScanner only routes odd divisors here; keep the guard commented out for benchmarks.
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace PerfectNumbers.Core;
|
|||||||
|
|
||||||
public static partial class ULongExtensions
|
public static partial class ULongExtensions
|
||||||
{
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
[Obsolete("Use ULongExtensions.MulHighCpu or ULongExtensions.MulHighGpu.")]
|
[Obsolete("Use ULongExtensions.MulHighCpu or ULongExtensions.MulHighGpu.")]
|
||||||
public static ulong MulHighGpuCompatible(this ulong x, ulong y)
|
public static ulong MulHighGpuCompatible(this ulong x, ulong y)
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@ public static partial class ULongExtensions
|
|||||||
return product.High;
|
return product.High;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||||||
public static ulong MulMod64Gpu(this ulong a, ulong b, ulong modulus)
|
public static ulong MulMod64Gpu(this ulong a, ulong b, ulong modulus)
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,7 @@ public static partial class ULongExtensions
|
|||||||
return state.MulMod(b, modulus);
|
return state.MulMod(b, modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||||||
public static ulong MulMod64GpuDeferred(this ulong a, ulong b, ulong modulus)
|
public static ulong MulMod64GpuDeferred(this ulong a, ulong b, ulong modulus)
|
||||||
{
|
{
|
||||||
@@ -36,29 +36,29 @@ public static partial class ULongExtensions
|
|||||||
return state.MulModWithNativeModulo(b, modulus);
|
return state.MulModWithNativeModulo(b, modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong MulModGpu(this ulong left, ulong right, ulong modulus)
|
public static ulong MulModGpu(this ulong left, ulong right, ulong modulus)
|
||||||
{
|
{
|
||||||
GpuUInt128 state = new(left);
|
GpuUInt128 state = new(left);
|
||||||
return state.MulMod(right, modulus);
|
return state.MulMod(right, modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWindowedKeepGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModWindowedKeepGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
||||||
=> Pow2MontgomeryGpuCalculator.CalculateKeep(gpu, exponent, divisor);
|
=> Pow2MontgomeryGpuCalculator.CalculateKeep(gpu, exponent, divisor);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWindowedConvertGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModWindowedConvertGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
||||||
=> Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, exponent, divisor);
|
=> Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, exponent, divisor);
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModWithCycleGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, ulong cycleLength, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModWithCycleGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, ulong cycleLength, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
ulong rotationCount = exponent % cycleLength;
|
ulong rotationCount = exponent % cycleLength;
|
||||||
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, rotationCount, divisor);
|
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, rotationCount, divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong Pow2MontgomeryModFromCycleRemainderGpu(this ulong reducedExponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
public static ulong Pow2MontgomeryModFromCycleRemainderGpu(this ulong reducedExponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
||||||
{
|
{
|
||||||
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, reducedExponent, divisor);
|
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, reducedExponent, divisor);
|
||||||
|
|||||||
@@ -642,7 +642,7 @@ public static partial class ULongExtensions
|
|||||||
return (ulong)(((UInt128)a * b) % modulus);
|
return (ulong)(((UInt128)a * b) % modulus);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong MontgomeryMultiplyCpu(this ulong a, ulong b, ulong modulus, ulong nPrime)
|
public static ulong MontgomeryMultiplyCpu(this ulong a, ulong b, ulong modulus, ulong nPrime)
|
||||||
{
|
{
|
||||||
ulong tLow = unchecked(a * b);
|
ulong tLow = unchecked(a * b);
|
||||||
@@ -1133,7 +1133,7 @@ public static partial class ULongExtensions
|
|||||||
return x1;
|
return x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
public static ulong ReduceCycleRemainder(this ulong value, ulong modulus)
|
public static ulong ReduceCycleRemainder(this ulong value, ulong modulus)
|
||||||
{
|
{
|
||||||
// BigIntegerExtensions.Track(modulus);
|
// BigIntegerExtensions.Track(modulus);
|
||||||
|
|||||||
Reference in new issue
Block a user