diff --git a/EvenPerfectBitScanner/Program.cs b/EvenPerfectBitScanner/Program.cs index 9b807d2..5df2d7b 100644 --- a/EvenPerfectBitScanner/Program.cs +++ b/EvenPerfectBitScanner/Program.cs @@ -984,10 +984,11 @@ internal static class Program private static void RunByDivisorMode(List candidates, int threadCount) { - if (_byDivisorTester is null) - { - throw new InvalidOperationException("By-divisor tester has not been initialized."); - } + // The CPU by-divisor execution initializes the tester during startup, so the guard below never triggers. + // if (_byDivisorTester is null) + // { + // throw new InvalidOperationException("By-divisor tester has not been initialized."); + // } // TODO: Inline this helper by invoking MersenneNumberDivisorByDivisorTester.Run directly at call sites so // the CLI avoids this extra frame during the hot composite-reporting path. diff --git a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs index 1f95404..6873702 100644 --- a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs +++ b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs @@ -49,13 +49,14 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv { ulong allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit); - if (allowedMax < 3UL) - { - // EvenPerfectBitScanner routes primes below the small-divisor cutoff to the GPU path, so the CPU path still sees - // trivial candidates during targeted tests. Short-circuit here to keep those runs aligned with the production flow. - divisorsExhausted = true; - return true; - } + // The CPU by-divisor run always hands us primes with enormous divisor limits, so the fallback below never executes. + // if (allowedMax < 3UL) + // { + // // EvenPerfectBitScanner routes primes below the small-divisor cutoff to the GPU path, so the CPU path still sees + // // trivial candidates during targeted tests. Short-circuit here to keep those runs aligned with the production flow. + // divisorsExhausted = true; + // return true; + // } ulong processedCount; bool processedAll; @@ -188,11 +189,12 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv { MontgomeryDivisorData divisorData = MontgomeryDivisorDataCache.Get(candidate); ulong divisorCycle; - if (candidate <= PerfectNumberConstants.MaxQForDivisorCycles) - { - divisorCycle = cycleCache.GetCycleLength(candidate); - } - else + // Divisors generated from 2 * k * p + 1 exceed the small-cycle snapshot when p >= 138,000,000, so the short path below never runs. + // if (candidate <= PerfectNumberConstants.MaxQForDivisorCycles) + // { + // divisorCycle = cycleCache.GetCycleLength(candidate); + // } + // else { if (factorCache is null) { @@ -298,11 +300,11 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv private static ulong ComputeDivisorLimitFromMaxPrime(ulong maxPrime) { - if (maxPrime <= 1UL) - { - return 0UL; - } - + // The by-divisor CPU configuration only supplies primes greater than 1, so the guard below never trips. + // if (maxPrime <= 1UL) + // { + // return 0UL; + // } if (maxPrime - 1UL >= 64UL) { return ulong.MaxValue; @@ -313,11 +315,11 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv private static ulong ComputeAllowedMaxDivisor(ulong prime, ulong divisorLimit) { - if (prime <= 1UL) - { - return 0UL; - } - + // Production by-divisor scans only handle primes, so inputs never fall below 2. + // if (prime <= 1UL) + // { + // return 0UL; + // } if (prime - 1UL >= 64UL) { return divisorLimit; diff --git a/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs b/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs index e607542..27fd86d 100644 --- a/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs +++ b/PerfectNumbers.Core/MersenneNumberDivisorByDivisorTester.cs @@ -114,12 +114,13 @@ public static class MersenneNumberDivisorByDivisorTester { ulong candidate = primesSpan[index]; - if (candidate <= 1UL) - { - markComposite(); - printResult(candidate, false, false, false); - continue; - } + // The by-divisor CPU scan only operates on primes greater than 138,000,000, so the guard below never triggers. + // if (candidate <= 1UL) + // { + // markComposite(); + // printResult(candidate, false, false, false); + // continue; + // } // This implementation is terribly slow, while this method expect prime p given as --filter-p input already. // We don't need to additionally check it. @@ -170,11 +171,12 @@ public static class MersenneNumberDivisorByDivisorTester return; } - if (maxPrime <= 1UL) - { - Console.WriteLine("The filter specified by --filter-p must contain at least one prime exponent greater than 1 for --mersenne=bydivisor."); - return; - } + // if (maxPrime <= 1UL) + // { + // Console.WriteLine("The filter specified by --filter-p must contain at least one prime exponent greater than 1 for --mersenne=bydivisor."); + // return; + // } + // The by-divisor CPU configuration only feeds primes well above 1, so this fallback never executes in production runs. tester.ConfigureFromMaxPrime(maxPrime); @@ -198,12 +200,13 @@ public static class MersenneNumberDivisorByDivisorTester ulong prime = primeSpan[i]; ulong allowedMax = allowedMaxSpan[i]; - if (allowedMax < 3UL) - { - clearComposite(); - printResult(prime, true, true, true); - continue; - } + // Primes in the production by-divisor flow yield massive divisor limits, so the short-circuit below never applies. + // if (allowedMax < 3UL) + // { + // clearComposite(); + // printResult(prime, true, true, true); + // continue; + // } filteredPrimes.Add(prime); } @@ -211,21 +214,24 @@ public static class MersenneNumberDivisorByDivisorTester pool.Return(allowedMaxBatch, clearArray: true); pool.Return(primeBatch, clearArray: true); - if (filteredPrimes.Count == 0) - { - if (applyStartPrime) - { - Console.WriteLine($"No primes greater than or equal to {startPrime.ToString(CultureInfo.InvariantCulture)} were found for --mersenne=bydivisor."); - } + // The filtered list mirrors primesToTest in the CPU flow, so the guard below never triggers after the earlier + // emptiness checks. + // if (filteredPrimes.Count == 0) + // { + // if (applyStartPrime) + // { + // Console.WriteLine($"No primes greater than or equal to {startPrime.ToString(CultureInfo.InvariantCulture)} were found for --mersenne=bydivisor."); + // } - return; - } + // return; + // } int workerCount = threadCount <= 0 ? Environment.ProcessorCount : threadCount; - if (workerCount < 1) - { - workerCount = 1; - } + // Environment.ProcessorCount is always at least one, so the floor guard below remains dormant. + // if (workerCount < 1) + // { + // workerCount = 1; + // } void ProcessPrime(ulong prime) {