Use bit masks for divisor heuristics

This commit is contained in:
Marek Lemańczyk committed 2025-10-24 19:50:27 +02:00
1 parent 46a2178d65
commit bbe0c02069
6 files changed
+83 -43

No files matched your search

+28 -16
View File
@@ -58,7 +58,11 @@ public class MersenneDivisorCycles
return true;
}
if (exponent <= 1UL || divisor <= 1UL || (divisor & 1UL) == 0UL)
const int InvalidParameterMask = 0b111;
int invalidBits = (exponent <= 1UL ? 1 : 0)
| ((divisor <= 1UL ? 1 : 0) << 1)
| ((int)(1UL ^ (divisor & 1UL)) << 2);
if ((invalidBits & InvalidParameterMask) != 0)
{
return false;
}
@@ -91,10 +95,12 @@ public class MersenneDivisorCycles
public static bool CycleEqualsExponentForMersenneCandidate(ulong divisor, in MontgomeryDivisorData divisorData, ulong exponent)
{
if (!IsValidMersenneDivisorCandidate(divisor, exponent))
{
return false;
}
// EvenPerfectBitScanner only calls this helper with divisors generated from 2 * k * p + 1 and primes greater than one,
// so the validation guard would never trigger in production. Keep it commented out to leave the hot path branch-free.
// if (!IsValidMersenneDivisorCandidate(divisor, exponent))
// {
// return false;
// }
if (divisor <= PerfectNumberConstants.MaxQForDivisorCycles)
{
@@ -115,7 +121,11 @@ public class MersenneDivisorCycles
private static bool IsValidMersenneDivisorCandidate(ulong divisor, ulong exponent)
{
if (exponent <= 1UL || divisor <= 1UL || (divisor & 1UL) == 0UL)
const int InvalidParameterMask = 0b111;
int invalidBits = (exponent <= 1UL ? 1 : 0)
| ((divisor <= 1UL ? 1 : 0) << 1)
| ((int)(1UL ^ (divisor & 1UL)) << 2);
if ((invalidBits & InvalidParameterMask) != 0)
{
return false;
}
@@ -255,17 +265,19 @@ public class MersenneDivisorCycles
cycleLength = 0UL;
primeOrderFailed = false;
if ((divisor & (divisor - 1UL)) == 0UL)
{
cycleLength = 1UL;
return true;
}
// EvenPerfectBitScanner never feeds powers of two into this helper, so leave the branch commented out to avoid redundant work.
// if ((divisor & (divisor - 1UL)) == 0UL)
// {
// cycleLength = 1UL;
// return true;
// }
if (divisor <= 3UL || exponent <= 1UL)
{
cycleLength = CalculateCycleLength(divisor, divisorData);
return true;
}
// The scanner only calls this path with prime exponents greater than one and odd divisors above three, keeping the small-parameter guard unreachable.
// if (divisor <= 3UL || exponent <= 1UL)
// {
// cycleLength = CalculateCycleLength(divisor, divisorData);
// return true;
// }
ulong computedOrder = PrimeOrderCalculator.Calculate(
divisor,