diff --git a/EvenPerfectBitScanner/Program.cs b/EvenPerfectBitScanner/Program.cs index e813d6b..03e11d9 100644 --- a/EvenPerfectBitScanner/Program.cs +++ b/EvenPerfectBitScanner/Program.cs @@ -579,9 +579,6 @@ internal static class Program Console.WriteLine("Initialization..."); // Compose a results file name that encodes configuration (before opening file) - string byDivisorDeltasLabel = mersenneOnGpu - ? "gpu" - : (byDivisorDeltasDevice == ByDivisorDeltasDevice.Gpu ? "cpu-gpu" : "cpu"); var builtName = BuildResultsFileName( useBitTransform, threadCount, @@ -591,19 +588,18 @@ internal static class Program useDivisor, useByDivisor, mersenneOnGpu, - useOrder, - useModuloWorkaround, - _useGcdFilter, - NttGpuMath.GpuTransformBackend, - gpuPrimeThreads, - sliceSize, - scanBatchSize, - _orderWarmupLimitOverride ?? 5_000_000UL, - NttGpuMath.ReductionMode, - mersenneOnGpu ? "gpu" : "cpu", - (GpuContextPool.ForceCpu ? "cpu" : "gpu"), - orderOnGpu ? "gpu" : "cpu", - byDivisorDeltasLabel); + useOrder, + useModuloWorkaround, + _useGcdFilter, + NttGpuMath.GpuTransformBackend, + gpuPrimeThreads, + sliceSize, + scanBatchSize, + _orderWarmupLimitOverride ?? 5_000_000UL, + NttGpuMath.ReductionMode, + mersenneOnGpu ? "gpu" : "cpu", + (GpuContextPool.ForceCpu ? "cpu" : "gpu"), + orderOnGpu ? "gpu" : "cpu"); if (!string.IsNullOrEmpty(_resultsPrefix)) { @@ -1020,7 +1016,7 @@ internal static class Program Console.WriteLine(" --help, -help, --?, -?, /? show this help message"); } - private static string BuildResultsFileName(bool bitInc, int threads, int block, GpuKernelType kernelType, bool useLucasFlag, bool useDivisorFlag, bool useByDivisorFlag, bool mersenneOnGpu, bool useOrder, bool useModWorkaround, bool useGcd, NttBackend nttBackend, int gpuPrimeThreads, int llSlice, int gpuScanBatch, ulong warmupLimit, ModReductionMode reduction, string mersenneDevice, string primesDevice, string orderDevice, string byDivisorDeltasDevice) + private static string BuildResultsFileName(bool bitInc, int threads, int block, GpuKernelType kernelType, bool useLucasFlag, bool useDivisorFlag, bool useByDivisorFlag, bool mersenneOnGpu, bool useOrder, bool useModWorkaround, bool useGcd, NttBackend nttBackend, int gpuPrimeThreads, int llSlice, int gpuScanBatch, ulong warmupLimit, ModReductionMode reduction, string mersenneDevice, string primesDevice, string orderDevice) { string inc = bitInc ? "bit" : "add"; string mers = useDivisorFlag @@ -1028,7 +1024,7 @@ internal static class Program : (useLucasFlag ? "lucas" : (useByDivisorFlag - ? $"bydivisor-{byDivisorDeltasDevice}" + ? "bydivisor" : (kernelType == GpuKernelType.Pow2Mod ? "pow2mod" : "incremental"))); string ntt = nttBackend == NttBackend.Staged ? "staged" : "reference"; string red = reduction switch { ModReductionMode.Mont64 => "mont64", ModReductionMode.Barrett128 => "barrett128", ModReductionMode.GpuUInt128 => "uint128", _ => "auto" }; diff --git a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs index 65f0a9c..41889aa 100644 --- a/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs +++ b/PerfectNumbers.Core/Cpu/MersenneNumberDivisorByDivisorCpuTester.cs @@ -363,27 +363,24 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv return false; } - UInt128 step128 = (UInt128)prime << 1; - if (step128 == UInt128.Zero) + GpuUInt128 step128 = new GpuUInt128(prime); + step128.ShiftLeft(1); + if (step128.IsZero) { processedAll = true; return false; } - if (step128 > ulong.MaxValue) - { - return CheckDivisorsCpu(prime, allowedMax, out lastProcessed, out processedAll, out processedCount, timeLimit); - } - - UInt128 limit = allowedMax; - UInt128 divisor128 = step128 + UInt128.One; - if (divisor128 > limit) + GpuUInt128 limit128 = new GpuUInt128(allowedMax); + GpuUInt128 divisor128 = step128; + divisor128.Add(1UL); + if (divisor128.CompareTo(limit128) > 0) { processedAll = true; return false; } - ulong step = (ulong)step128; + ulong step = step128.Low; ulong limit64 = allowedMax; int batchCapacity = Math.Max(1, _batchSize); @@ -412,20 +409,27 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv byte step7 = (byte)(step % 7UL); byte step11 = (byte)(step % 11UL); - byte remainder10 = (byte)((ulong)divisor128 % 10UL); - byte remainder8 = (byte)((ulong)divisor128 % 8UL); - byte remainder5 = (byte)((ulong)divisor128 % 5UL); - byte remainder3 = (byte)((ulong)divisor128 % 3UL); - byte remainder7 = (byte)((ulong)divisor128 % 7UL); - byte remainder11 = (byte)((ulong)divisor128 % 11UL); + ulong startDivisor64 = divisor128.Low; + byte remainder10 = (byte)(startDivisor64 % 10UL); + byte remainder8 = (byte)(startDivisor64 % 8UL); + byte remainder5 = (byte)(startDivisor64 % 5UL); + byte remainder3 = (byte)(startDivisor64 % 3UL); + byte remainder7 = (byte)(startDivisor64 % 7UL); + byte remainder11 = (byte)(startDivisor64 % 11UL); bool lastIsSeven = (prime & 3UL) == 3UL; try { - while (divisor128 <= limit) + while (divisor128.CompareTo(limit128) <= 0) { - int chunkCount = ComputeChunkCount(divisor128, limit, step128, batchCapacity); + if (divisor128.High != 0UL) + { + break; + } + + ulong currentDivisor = divisor128.Low; + int chunkCount = ComputeChunkCount(currentDivisor, limit64, step, batchCapacity); if (chunkCount <= 0) { break; @@ -435,7 +439,7 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv Span maskSpan = maskBuffer.AsSpan(0, chunkCount); candidateEvaluator.EvaluateCandidates( - (ulong)divisor128, + currentDivisor, step, limit64, remainder10, @@ -508,7 +512,10 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv } } - divisor128 += step128 * (UInt128)chunkCount; + GpuUInt128 increment = step128; + increment.Mul((ulong)chunkCount); + divisor128.Add(increment); + remainder10 = AdvanceRemainder(remainder10, step10, 10, chunkCount); remainder8 = AdvanceRemainder(remainder8, step8, 8, chunkCount); remainder5 = AdvanceRemainder(remainder5, step5, 5, chunkCount); @@ -524,26 +531,26 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv candidateEvaluator.Dispose(); } - processedAll = divisor128 > limit; + processedAll = divisor128.CompareTo(limit128) > 0; return false; } - private static int ComputeChunkCount(UInt128 currentDivisor, UInt128 limit, UInt128 step, int maxCount) + private static int ComputeChunkCount(ulong currentDivisor, ulong limit, ulong step, int maxCount) { - if (maxCount <= 0 || step == UInt128.Zero || currentDivisor > limit) + if (maxCount <= 0 || step == 0UL || currentDivisor > limit) { return 0; } - UInt128 distance = limit - currentDivisor; - UInt128 stepsAvailable = distance / step; - UInt128 total = stepsAvailable + UInt128.One; - if (total > (UInt128)maxCount) + ulong distance = limit - currentDivisor; + ulong stepsAvailable = step == 0UL ? 0UL : distance / step; + ulong total = stepsAvailable + 1UL; + if (total > (ulong)maxCount) { - total = (UInt128)maxCount; + total = (ulong)maxCount; } - if (total > (UInt128)int.MaxValue) + if (total > (ulong)int.MaxValue) { return int.MaxValue; }