Document CPU sieve invariants and cache boolean guards

This commit is contained in:
Marek Lemańczyk committed 2025-10-22 00:56:17 +02:00
1 parent fa6f75c158
commit f2070a0f64
2 files changed
+19 -21

No files matched your search

@@ -8,6 +8,8 @@ public class PrimeTesterIsPrimeTests
{ {
[Theory] [Theory]
[Trait("Category", "Fast")] [Trait("Category", "Fast")]
// EvenPerfectBitScanner never routes these small values, but factoring helpers and residue checks still call into
// PrimeTester for sanity probes, so the regression suite keeps the tiny cases alongside large primes/composites.
[InlineData(1UL, false)] [InlineData(1UL, false)]
[InlineData(2UL, true)] [InlineData(2UL, true)]
[InlineData(3UL, true)] [InlineData(3UL, true)]
+17 -21
View File
@@ -69,28 +69,24 @@ public sealed class PrimeTester(bool useInternal = false)
internal static bool IsPrimeInternal(ulong n, CancellationToken ct) internal static bool IsPrimeInternal(ulong n, CancellationToken ct)
{ {
bool result = true; // EvenPerfectBitScanner streams monotonically increasing odd exponents that start at 136,279,841 and already exclude
if (n <= 3UL) // multiples of five. Factorization helpers (PrimeOrderCalculator, Pollard routines, and divisor-cycle warmups) reuse
// this path for arbitrary residues and cofactors, so keep the boolean guards even though the scanner never trips them.
bool isTwo = n == 2UL;
bool isOdd = (n & 1UL) != 0UL;
// TODO: Replace this modulo check with ULongExtensions.Mod5 so the CPU hot path reuses the benchmarked helper instead of `%`.
ulong mod5 = n % 5UL;
bool divisibleByFive = n > 5UL && mod5 == 0UL;
bool result = n >= 2UL && (isTwo || isOdd) && !divisibleByFive;
bool requiresTrialDivision = result && n >= 7UL && !isTwo;
if (requiresTrialDivision)
{ {
result = n >= 2UL; bool sharesMaxExponentFactor = n.Mod10() == 1UL && SharesFactorWithMaxExponent(n);
} result &= !sharesMaxExponentFactor;
else if ((n & 1UL) == 0)
{ if (result)
result = false;
}
else if (n > 5UL && (n % 5UL) == 0UL)
{
// TODO: Replace this modulo check with ULongExtensions.Mod5 so the CPU hot path
// reuses the benchmarked helper instead of `%` when sieving large prime ranges.
result = false;
}
else
{
if (n.Mod10() == 1UL && SharesFactorWithMaxExponent(n))
{
result = false;
}
else
{ {
var smallPrimeDivisorsLength = PrimesGenerator.SmallPrimes.Length; var smallPrimeDivisorsLength = PrimesGenerator.SmallPrimes.Length;
uint[] smallPrimeDivisors = PrimesGenerator.SmallPrimes; uint[] smallPrimeDivisors = PrimesGenerator.SmallPrimes;