diff --git a/EvenPerfectBitScanner/Program.cs b/EvenPerfectBitScanner/Program.cs index 1e04e95..55a9508 100644 --- a/EvenPerfectBitScanner/Program.cs +++ b/EvenPerfectBitScanner/Program.cs @@ -519,7 +519,7 @@ internal static class Program RleBlacklist.Load(_rleBlacklistPath!); } - ulong remainder = currentP % 6UL; + ulong remainder = currentP.Mod6(); if (currentP == InitialP && string.IsNullOrEmpty(filterFile)) { // bool passedAllTests = IsEvenPerfectCandidate(InitialP, out bool searchedMersenne, out bool detailedCheck); @@ -1595,7 +1595,7 @@ internal static class Program // Optional: RLE blacklist and binary-threshold filters on p (safe only when configured) if (p <= _rleHardMaxP) { - if (!_rleOnlyLast7 || p % 10UL == 7UL) + if (!_rleOnlyLast7 || p.Mod10() == 7UL) { if (RleBlacklist.IsLoaded() && RleBlacklist.Matches(p)) { diff --git a/PerfectNumbers.Core/Cpu/MersenneNumberResidueCpuTester.cs b/PerfectNumbers.Core/Cpu/MersenneNumberResidueCpuTester.cs index 2e13805..0946177 100644 --- a/PerfectNumbers.Core/Cpu/MersenneNumberResidueCpuTester.cs +++ b/PerfectNumbers.Core/Cpu/MersenneNumberResidueCpuTester.cs @@ -21,7 +21,7 @@ public class MersenneNumberResidueCpuTester q.Mod10_8_5_3(out ulong r10, out ulong r8, out ulong r5, out ulong r3); // Step residues for q += 2*p twoP.Mod10_8_5_3(out ulong step10, out ulong step8, out ulong step5, out ulong step3); - step10 %= 10UL; + step10 = step10.Mod10(); // Allowed last-digit sets for q depending on last digit of M_p // lastIsSeven == true => allow {7,9} diff --git a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs index 3b91635..81a3cb4 100644 --- a/PerfectNumbers.Core/Gpu/GpuKernelPool.cs +++ b/PerfectNumbers.Core/Gpu/GpuKernelPool.cs @@ -200,8 +200,10 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne ArrayView1D smallCycles) { ulong idx = (ulong)index.X; - // residue automaton - ulong step10 = (exponent.Mod10() << 1).Mod10(); + ulong idxMod3 = idx.Mod3(); + ulong idxMod5 = idx.Mod5(); + // residue automaton + ulong step10 = (exponent.Mod10() << 1).Mod10(); ulong r10 = q0m10 + (step10 * idx).Mod10(); r10 -= (r10 >= 10UL) ? 10UL : 0UL; bool shouldCheck = r10 != 5UL; // skip q ≡ 5 (mod 10); other residues handled by r8/r3/r5 @@ -215,16 +217,16 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong step3 = ((exponent % 3UL) << 1) % 3UL; - ulong r3 = q0m3 + (step3 * (idx % 3UL)); r3 -= (r3 >= 3UL) ? 3UL : 0UL; + ulong step3 = (exponent.Mod3() << 1).Mod3(); + ulong r3 = q0m3 + (step3 * idxMod3); r3 -= (r3 >= 3UL) ? 3UL : 0UL; if (r3 == 0UL) { shouldCheck = false; } else { - ulong step5Loc = ((exponent % 5UL) << 1) % 5UL; - ulong r5 = q0m5 + (step5Loc * (idx % 5UL)); if (r5 >= 5UL) r5 -= 5UL; + ulong step5Loc = (exponent.Mod5() << 1).Mod5(); + ulong r5 = q0m5 + (step5Loc * idxMod5); if (r5 >= 5UL) r5 -= 5UL; if (r5 == 0UL) { shouldCheck = false; @@ -358,6 +360,8 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne ArrayView1D smallPrimesPow2LastSeven) { ulong idx = (ulong)index.X; + ulong idxMod3 = idx.Mod3(); + ulong idxMod5 = idx.Mod5(); ulong r10 = ra.Q0M10 + (ra.Step10 * idx).Mod10(); r10 -= (r10 >= 10UL) ? 10UL : 0UL; bool shouldCheck = r10 != 5UL; if (shouldCheck) @@ -369,7 +373,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); + ulong r3 = ra.Q0M3 + (ra.Step3 * idxMod3); if (r3 >= 6UL) r3 -= 6UL; if (r3 >= 3UL) r3 -= 3UL; if (r3 == 0UL) @@ -378,7 +382,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); + ulong r5 = ra.Q0M5 + (ra.Step5 * idxMod5); if (r5 >= 15UL) r5 -= 15UL; if (r5 >= 10UL) r5 -= 10UL; if (r5 >= 5UL) r5 -= 5UL; @@ -489,7 +493,9 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne ResidueAutomatonArgs ra, ArrayView found, ArrayView1D smallCycles) { ulong idx = (ulong)index.X; - ulong r10 = ra.Q0M10 + (ra.Step10 * idx).Mod10(); r10 -= (r10 >= 10UL) ? 10UL : 0UL; + ulong idxMod3 = idx.Mod3(); + ulong idxMod5 = idx.Mod5(); + ulong r10 = ra.Q0M10 + (ra.Step10 * idx).Mod10(); r10 -= (r10 >= 10UL) ? 10UL : 0UL; bool shouldCheck = r10 != 5UL; if (shouldCheck) { @@ -500,7 +506,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); + ulong r3 = ra.Q0M3 + (ra.Step3 * idxMod3); if (r3 >= 6UL) r3 -= 6UL; if (r3 >= 3UL) r3 -= 3UL; if (r3 == 0UL) @@ -509,7 +515,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); + ulong r5 = ra.Q0M5 + (ra.Step5 * idxMod5); if (r5 >= 15UL) r5 -= 15UL; if (r5 >= 10UL) r5 -= 10UL; if (r5 >= 5UL) r5 -= 5UL; @@ -573,7 +579,9 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne ResidueAutomatonArgs ra, ArrayView found, ArrayView1D smallCycles) { ulong idx = (ulong)index.X; - ulong r10 = ra.Q0M10 + (ra.Step10 * idx).Mod10(); r10 -= (r10 >= 10UL) ? 10UL : 0UL; + ulong idxMod3 = idx.Mod3(); + ulong idxMod5 = idx.Mod5(); + ulong r10 = ra.Q0M10 + (ra.Step10 * idx).Mod10(); r10 -= (r10 >= 10UL) ? 10UL : 0UL; bool shouldCheck = r10 != 5UL; if (shouldCheck) { @@ -584,7 +592,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r3 = ra.Q0M3 + (ra.Step3 * (idx % 3UL)); + ulong r3 = ra.Q0M3 + (ra.Step3 * idxMod3); if (r3 >= 6UL) r3 -= 6UL; if (r3 >= 3UL) r3 -= 3UL; if (r3 == 0UL) @@ -593,7 +601,7 @@ public ref struct GpuKernelLease(IDisposable limiter, GpuContextLease gpu, Kerne } else { - ulong r5 = ra.Q0M5 + (ra.Step5 * (idx % 5UL)); + ulong r5 = ra.Q0M5 + (ra.Step5 * idxMod5); if (r5 >= 15UL) r5 -= 15UL; if (r5 >= 10UL) r5 -= 10UL; if (r5 >= 5UL) r5 -= 5UL; diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs index b2f639b..076f6f8 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberIncrementalGpuTester.cs @@ -25,8 +25,8 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u var incKernel = gpuLease.IncrementalKernel; ulong step10 = (exponent.Mod10() << 1).Mod10(); ulong step8 = ((exponent & 7UL) << 1) & 7UL; - ulong step3 = ((exponent % 3UL) << 1) % 3UL; - ulong step5 = ((exponent % 5UL) << 1) % 5UL; + ulong step3 = (exponent.Mod3() << 1).Mod3(); + ulong step5 = (exponent.Mod5() << 1).Mod5(); GpuUInt128 twoPGpu = (GpuUInt128)twoP; var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator); ResiduePrimeViews primeViews = default; diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs index f978eaa..0bdca4c 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberLucasLehmerGpuTester.cs @@ -51,7 +51,7 @@ public class MersenneNumberLucasLehmerGpuTester // Early rejections aligned with incremental/order sieves, but safe for small p: // - If 3 | p and p != 3, then 7 | M_p -> composite. // - If p ≡ 1 (mod 4) and p shares a factor with (p-1), reject fast. - if (exponent % 3UL == 0UL && exponent != 3UL) + if (exponent.Mod3() == 0UL && exponent != 3UL) { return false; } diff --git a/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs b/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs index c4dedd9..0d1e738 100644 --- a/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs +++ b/PerfectNumbers.Core/Gpu/MersenneNumberOrderGpuTester.cs @@ -27,10 +27,10 @@ public class MersenneNumberOrderGpuTester(GpuKernelType kernelType, bool useGpuO var foundBuffer = accelerator.Allocate1D(1); UInt128 exponent128 = exponent; exponent128.Mod10_8_5_3(out ulong exponentMod10, out ulong exponentMod8, out ulong exponentMod5, out ulong exponentMod3); - ulong step10 = (exponentMod10 << 1) % 10UL; - ulong step8 = (exponentMod8 << 1) & 7UL; - ulong step3 = (exponentMod3 << 1) % 3UL; - ulong step5 = (exponentMod5 << 1) % 5UL; + ulong step10 = (exponentMod10 << 1).Mod10(); + ulong step8 = (exponentMod8 << 1) & 7UL; + ulong step3 = (exponentMod3 << 1).Mod3(); + ulong step5 = (exponentMod5 << 1).Mod5(); try { UInt128 remaining; diff --git a/PerfectNumbers.Core/MersenneDivisorCycles.cs b/PerfectNumbers.Core/MersenneDivisorCycles.cs index d8dfc3f..edf7930 100644 --- a/PerfectNumbers.Core/MersenneDivisorCycles.cs +++ b/PerfectNumbers.Core/MersenneDivisorCycles.cs @@ -189,7 +189,7 @@ public class MersenneDivisorCycles for (int i = 0; i < localCycleIndex; i++) { (d, cycle) = localCycles[i]; - if (d % 3UL == 0UL || d % 5UL == 0UL || d % 7UL == 0UL || d % 11UL == 0UL) + if (d.Mod3() == 0UL || d.Mod5() == 0UL || d.Mod7() == 0UL || d.Mod11() == 0UL) continue; writer.Write(d); @@ -249,7 +249,7 @@ public class MersenneDivisorCycles { while (skipCount > 0L && start <= maxDivisor) { - if ((start & 1UL) == 0UL || start % 3UL == 0UL || start % 5UL == 0UL || start % 7UL == 0UL || start % 11UL == 0UL) + if ((start & 1UL) == 0UL || start.Mod3() == 0UL || start.Mod5() == 0UL || start.Mod7() == 0UL || start.Mod11() == 0UL) { start++; continue; @@ -296,7 +296,7 @@ public class MersenneDivisorCycles { d = divisors[i]; - if (d % 3UL == 0UL || d % 5UL == 0UL || d % 7UL == 0UL || d % 11UL == 0UL) + if (d.Mod3() == 0UL || d.Mod5() == 0UL || d.Mod7() == 0UL || d.Mod11() == 0UL) continue; writer.Write(d); diff --git a/PerfectNumbers.Core/MersenneNumberTester.cs b/PerfectNumbers.Core/MersenneNumberTester.cs index a3b7c1c..8f9fe6b 100644 --- a/PerfectNumbers.Core/MersenneNumberTester.cs +++ b/PerfectNumbers.Core/MersenneNumberTester.cs @@ -67,7 +67,7 @@ public sealed class MersenneNumberTester( for (; k <= limit; k++) { q = twoP * k + UInt128.One; - remainder = (ulong)(q % 10UL); + remainder = q.Mod10(); bool shouldCheck = lastIsSeven ? remainder == 7UL || remainder == 9UL || remainder == 3UL : remainder == 1UL || remainder == 3UL || remainder == 9UL; @@ -75,12 +75,12 @@ public sealed class MersenneNumberTester( // Early modular filters for odd order and small-prime rejections if (shouldCheck) { - ulong mod8 = (ulong)(q % 8UL); + ulong mod8 = q.Mod8(); if (mod8 != 1UL && mod8 != 7UL) { continue; } - else if ((ulong)(q % 3UL) == 0UL || (ulong)(q % 5UL) == 0UL) + else if (q.Mod3() == 0UL || q.Mod5() == 0UL) { continue; } @@ -106,7 +106,7 @@ public sealed class MersenneNumberTester( for (; k2 <= limit; k2++) { q2 = twoP * k2 + 1UL; - remainder2 = (ulong)(q2 % 10UL); + remainder2 = q2.Mod10(); bool shouldCheck2 = lastIsSeven ? remainder2 == 7UL || remainder2 == 9UL || remainder2 == 3UL : remainder2 == 1UL || remainder2 == 3UL || remainder2 == 9UL; @@ -114,12 +114,12 @@ public sealed class MersenneNumberTester( // Early modular filters for odd order and small-prime rejections if (shouldCheck2) { - ulong mod8 = (ulong)(q2 % 8UL); + ulong mod8 = q2.Mod8(); if (mod8 != 1UL && mod8 != 7UL) { shouldCheck2 = false; } - else if ((ulong)(q2 % 3UL) == 0UL || (ulong)(q2 % 5UL) == 0UL) + else if (q2.Mod3() == 0UL || q2.Mod5() == 0UL) { shouldCheck2 = false; } @@ -203,7 +203,7 @@ public sealed class MersenneNumberTester( { // Safe early rejections using known orders for tiny primes: // 7 | M_p iff 3 | p. Avoid rejecting p == 3 where M_3 == 7 is prime. - if (exponent % 3UL == 0UL && exponent != 3UL) + if (exponent.Mod3() == 0UL && exponent != 3UL) { return false; } diff --git a/PerfectNumbers.Core/PrimeTester.cs b/PerfectNumbers.Core/PrimeTester.cs index 0351167..fa962d8 100644 --- a/PerfectNumbers.Core/PrimeTester.cs +++ b/PerfectNumbers.Core/PrimeTester.cs @@ -53,13 +53,13 @@ public sealed class PrimeTester(bool useInternal = false) { result = false; } - else if (n > 5UL && n % 5UL == 0UL) + else if (n > 5UL && n.Mod5() == 0UL) { result = false; } else { - if (n % 10UL == 1UL && SharesFactorWithMaxExponent(n)) + if (n.Mod10() == 1UL && SharesFactorWithMaxExponent(n)) { result = false; } @@ -260,13 +260,13 @@ public sealed class PrimeTester(bool useInternal = false) return; } - if ((n & 1UL) == 0UL || (n > 5UL && n % 5UL == 0UL)) + if ((n & 1UL) == 0UL || (n > 5UL && n.Mod5() == 0UL)) { results[index] = 0; return; } - if (n % 10UL == 1UL) + if (n.Mod10() == 1UL) { // Early reject special GCD heuristic with floor(log2 n) ulong m = 63UL - (ulong)ILGPU.Algorithms.XMath.LeadingZeroCount(n);