Document CPU sieve invariants and cache boolean guards
This commit is contained in:
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)]
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in new issue
Block a user