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 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; } }