79 lines
2.0 KiB
C#
79 lines
2.0 KiB
C#
using PerfectNumbers.Core.Gpu.Accelerators;
|
|
|
|
namespace PerfectNumbers.Core;
|
|
|
|
internal static partial class PrimeOrderCalculator
|
|
{
|
|
public static ulong CalculateHybrid(
|
|
PrimeOrderCalculatorAccelerator gpu,
|
|
ulong prime,
|
|
ulong? previousOrder,
|
|
in MontgomeryDivisorData divisorData,
|
|
in PrimeOrderSearchConfig config)
|
|
{
|
|
// TODO: Is this condition ever met on EvenPerfectBitScanner's execution path? If not, we can add a clarification comment and comment out the entire block. We want to support p candidates at least greater or equal to 31.
|
|
if (prime <= 3UL)
|
|
{
|
|
return prime == 3UL ? 2UL : 1UL;
|
|
}
|
|
|
|
ulong phi = prime - 1UL;
|
|
|
|
PartialFactorResult phiFactors = PartialFactorHybrid(gpu, phi, config);
|
|
|
|
ulong result;
|
|
if (phiFactors.Factors is null)
|
|
{
|
|
result = CalculateByFactorizationCpu(prime, divisorData);
|
|
|
|
phiFactors.Dispose();
|
|
return result;
|
|
}
|
|
|
|
result = RunHeuristicPipelineHybrid(gpu, prime, previousOrder, config, divisorData, phi, phiFactors);
|
|
|
|
phiFactors.Dispose();
|
|
return result;
|
|
}
|
|
|
|
public static UInt128 CalculateHybrid(
|
|
PrimeOrderCalculatorAccelerator gpu,
|
|
in UInt128 prime,
|
|
in UInt128? previousOrder,
|
|
in PrimeOrderSearchConfig config)
|
|
{
|
|
MontgomeryDivisorData divisorData;
|
|
UInt128 result;
|
|
if (prime <= ulong.MaxValue)
|
|
{
|
|
ulong? previous = null;
|
|
if (previousOrder.HasValue)
|
|
{
|
|
UInt128 previousValue = previousOrder.Value;
|
|
if (previousValue <= ulong.MaxValue)
|
|
{
|
|
previous = (ulong)previousValue;
|
|
}
|
|
else
|
|
{
|
|
previous = ulong.MaxValue;
|
|
}
|
|
}
|
|
|
|
ulong prime64 = (ulong)prime;
|
|
Queue<MontgomeryDivisorData> divisorPool = MontgomeryDivisorDataPool.Shared;
|
|
divisorData = divisorPool.FromModulus(prime64);
|
|
ulong order64 = CalculateHybrid(gpu, prime64, previous, divisorData, config);
|
|
divisorPool.Return(divisorData);
|
|
result = order64 == 0UL ? UInt128.Zero : (UInt128)order64;
|
|
}
|
|
else
|
|
{
|
|
divisorData = MontgomeryDivisorData.Empty;
|
|
result = CalculateWideInternalCpu(prime, previousOrder, divisorData, config);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|