From ee9c151eaa18faf9a8216fbfca88eec5c7ff18f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Sat, 20 Sep 2025 04:24:04 +0200 Subject: [PATCH] Fix residue kernel modulus reduction and add regression test --- .../MersenneResidueModeTests.cs | 7 ++ PerfectNumbers.Core/Gpu/GpuKernelPool.cs | 71 +++++++++++-------- 2 files changed, 50 insertions(+), 28 deletions(-) diff --git a/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs b/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs index 365a6c7..921318c 100644 --- a/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs +++ b/PerfectNumbers.Core.Tests/MersenneNumberTester/MersenneResidueModeTests.cs @@ -19,5 +19,12 @@ public class MersenneResidueModeTests var tester = new MersenneNumberTester(useResidue: true, useIncremental: true, maxK: 1_000UL); tester.IsMersennePrime(31UL).Should().BeTrue(); } + + [Fact] + public void IsMersennePrime_residue_mode_accepts_prime_exponent_when_scanning_multiple_batches() + { + var tester = new MersenneNumberTester(useResidue: true, useIncremental: true, maxK: 2_100_000UL); + tester.IsMersennePrime(31UL).Should().BeTrue(); + } } diff --git a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs index 8ef52b0..b1b1378 100644 --- a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs @@ -312,14 +312,19 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); r3 -= (r3 >= 3UL) ? 3UL : 0UL; + ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); + if (r3 >= 6UL) r3 -= 6UL; + if (r3 >= 3UL) r3 -= 3UL; if (r3 == 0UL) { shouldCheck = false; } else { - ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); if (r5 >= 5UL) r5 -= 5UL; + ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); + if (r5 >= 15UL) r5 -= 15UL; + if (r5 >= 10UL) r5 -= 10UL; + if (r5 >= 5UL) r5 -= 5UL; if (r5 == 0UL) { shouldCheck = false; @@ -434,19 +439,24 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); r3 -= (r3 >= 3UL) ? 3UL : 0UL; - if (r3 == 0UL) - { - shouldCheck = false; - } - else - { - ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); if (r5 >= 5UL) r5 -= 5UL; - if (r5 == 0UL) - { - shouldCheck = false; - } - } + ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); + if (r3 >= 6UL) r3 -= 6UL; + if (r3 >= 3UL) r3 -= 3UL; + if (r3 == 0UL) + { + shouldCheck = false; + } + else + { + ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); + if (r5 >= 15UL) r5 -= 15UL; + if (r5 >= 10UL) r5 -= 10UL; + if (r5 >= 5UL) r5 -= 5UL; + if (r5 == 0UL) + { + shouldCheck = false; + } + } } } if (!shouldCheck) @@ -509,19 +519,24 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); r3 -= (r3 >= 3UL) ? 3UL : 0UL; - if (r3 == 0UL) - { - shouldCheck = false; - } - else - { - ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); if (r5 >= 5UL) r5 -= 5UL; - if (r5 == 0UL) - { - shouldCheck = false; - } - } + ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); + if (r3 >= 6UL) r3 -= 6UL; + if (r3 >= 3UL) r3 -= 3UL; + if (r3 == 0UL) + { + shouldCheck = false; + } + else + { + ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); + if (r5 >= 15UL) r5 -= 15UL; + if (r5 >= 10UL) r5 -= 10UL; + if (r5 >= 5UL) r5 -= 5UL; + if (r5 == 0UL) + { + shouldCheck = false; + } + } } } if (!shouldCheck)