PrimeOrderCalculator.PartialFactorCpu variables optimized. Removed constant parameter from AddFactorToCollector.

This commit is contained in:
mlemanczyk committed 2025-12-13 15:36:32 +01:00
1 parent 0fb5a5fa10
commit 1b3882addc
4 files changed
+31 -62

No files matched your search

@@ -2,6 +2,7 @@ using System.Runtime.CompilerServices;
namespace PerfectNumbers.Core; namespace PerfectNumbers.Core;
[method: MethodImpl(MethodImplOptions.AggressiveInlining)]
public struct PartialFactorPendingEntry(ulong value, bool knownComposite) public struct PartialFactorPendingEntry(ulong value, bool knownComposite)
{ {
public readonly ulong Value = value; public readonly ulong Value = value;
+26 -58
View File
@@ -1319,20 +1319,21 @@ internal static partial class PrimeOrderCalculator
primeSlots, primeSlots,
exponentSlots, exponentSlots,
out int factorCount, out int factorCount,
out ulong remaining); out value);
if (remaining > 1UL) bool cofactorContainsComposite;
if (value > 1UL)
{ {
if (config.PollardRhoMilliseconds > 0) if (config.PollardRhoMilliseconds > 0)
{ {
long deadlineTimestamp = CreateDeadlineTimestamp(config.PollardRhoMilliseconds);
FixedCapacityStack<ulong> compositeStack = result.CompositeStack; FixedCapacityStack<ulong> compositeStack = result.CompositeStack;
compositeStack.Clear(); compositeStack.Clear();
compositeStack.Push(remaining); compositeStack.Push(value);
long deadlineTimestamp = CreateDeadlineTimestamp(config.PollardRhoMilliseconds);
CollectFactorsCpu(primeSlots, exponentSlots, ref factorCount, pending, compositeStack, deadlineTimestamp, out bool limitReached); CollectFactorsCpu(primeSlots, exponentSlots, ref factorCount, pending, compositeStack, deadlineTimestamp, out cofactorContainsComposite);
if (limitReached) if (cofactorContainsComposite)
{ {
while (compositeStack.Count > 0) while (compositeStack.Count > 0)
{ {
@@ -1342,72 +1343,61 @@ internal static partial class PrimeOrderCalculator
} }
else else
{ {
pending.Add(new (remaining, knownComposite: false)); pending.Add(new (value, knownComposite: false));
} }
} }
ulong cofactor = 1UL; ulong cofactor = 1UL;
bool cofactorContainsComposite = false; bool isPrime;
int pendingCount = pending.Count; int pendingCount = pending.Count;
int index = 0; cofactorContainsComposite = false;
for (; index < pendingCount; index++) for (int index = 0; index < pendingCount; index++)
{ {
PartialFactorPendingEntry entry = pending[index]; PartialFactorPendingEntry entry = pending[index];
ulong composite = entry.Value; // Reuse "value" parameter for testing if a number is composite to limit registry pressure.
value = entry.Value;
if (entry.KnownComposite) if (entry.KnownComposite)
{ {
cofactor = checked(cofactor * composite); cofactor = checked(cofactor * value);
cofactorContainsComposite = true; cofactorContainsComposite = true;
continue; continue;
} }
if (!entry.HasKnownPrimality) if (!entry.HasKnownPrimality)
{ {
bool isPrime = PrimeTesterByLastDigit.IsPrimeCpu(composite); isPrime = PrimeTesterByLastDigit.IsPrimeCpu(value);
entry.WithPrimality(isPrime); entry.WithPrimality(isPrime);
} }
if (entry.IsPrime) if (entry.IsPrime)
{ {
AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, value);
} }
// composite is never smaller on the execution path // composite is never smaller on the execution path
// else if (composite > 1UL) // else if (composite > 1UL)
else else
{ {
cofactor = checked(cofactor * composite); cofactor = checked(cofactor * value);
cofactorContainsComposite = true; cofactorContainsComposite = true;
} }
} }
bool cofactorIsPrime; if (cofactorContainsComposite || cofactor <= 1UL)
if (cofactor <= 1UL)
{ {
cofactorIsPrime = false; isPrime = false;
}
else if (cofactorContainsComposite)
{
cofactorIsPrime = false;
} }
else else
{ {
cofactorIsPrime = PrimeTesterByLastDigit.IsPrimeCpu(cofactor); isPrime = PrimeTesterByLastDigit.IsPrimeCpu(cofactor);
} }
// This will never happen in production code. We'll always get at least 1 factor // This will never happen in production code. We'll always get at least 1 factor
// if (factorCount == 0) // if (factorCount == 0)
// { // {
// if (cofactor == value) // (...)
// {
// result = PartialFactorResult.Rent(null, value, false, 0);
// goto ReturnResult;
// }
// result = PartialFactorResult.Rent(null, cofactor, cofactor == 1UL, 0);
// goto ReturnResult;
// } // }
Array.Sort(factors, exponents, 0, factorCount); Array.Sort(factors, exponents, 0, factorCount);
@@ -1417,7 +1407,7 @@ internal static partial class PrimeOrderCalculator
result.Cofactor = cofactor; result.Cofactor = cofactor;
result.FullyFactored = cofactor == 1UL; result.FullyFactored = cofactor == 1UL;
result.Count = factorCount; result.Count = factorCount;
result.CofactorIsPrime = cofactorIsPrime; result.CofactorIsPrime = isPrime;
return result; return result;
} }
@@ -1432,7 +1422,7 @@ internal static partial class PrimeOrderCalculator
if (isPrime) if (isPrime)
{ {
AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite);
continue; continue;
} }
@@ -1511,10 +1501,6 @@ internal static partial class PrimeOrderCalculator
continue; continue;
} }
EnsureCollectorCapacity(
primeTargets,
factorCount + 1);
primeTargets[factorCount] = primeValue; primeTargets[factorCount] = primeValue;
exponentTargets[factorCount] = exponent; exponentTargets[factorCount] = exponent;
factorCount++; factorCount++;
@@ -1722,40 +1708,22 @@ internal static partial class PrimeOrderCalculator
Span<ulong> primes, Span<ulong> primes,
Span<int> exponents, Span<int> exponents,
ref int count, ref int count,
ulong prime, ulong prime)
int exponent)
{ {
if (exponent <= 0)
{
return;
}
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
if (primes[i] == prime) if (primes[i] == prime)
{ {
exponents[i] += exponent; exponents[i]++;
return; return;
} }
} }
EnsureCollectorCapacity(
primes,
count + 1);
primes[count] = prime; primes[count] = prime;
exponents[count] = exponent; exponents[count] = 1;
count++; count++;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static void EnsureCollectorCapacity(
Span<ulong> primes,
int requiredCapacity)
{
ArgumentOutOfRangeException.ThrowIfGreaterThan(requiredCapacity, primes.Length);
}
[MethodImpl(MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveOptimization)]
private static ulong CalculateByFactorizationCpu(ulong prime, in MontgomeryDivisorData divisorData) private static ulong CalculateByFactorizationCpu(ulong prime, in MontgomeryDivisorData divisorData)
{ {
@@ -170,7 +170,7 @@ internal static partial class PrimeOrderCalculator
if (isPrime) if (isPrime)
{ {
AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite);
continue; continue;
} }
@@ -426,7 +426,7 @@ internal static partial class PrimeOrderCalculator
if (entry.IsPrime) if (entry.IsPrime)
{ {
AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite);
} }
// composite is never smaller on the execution path // composite is never smaller on the execution path
// else if (composite > 1UL) // else if (composite > 1UL)
@@ -92,7 +92,7 @@ internal static partial class PrimeOrderCalculator
if (isPrime) if (isPrime)
{ {
AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite);
continue; continue;
} }
@@ -218,7 +218,7 @@ internal static partial class PrimeOrderCalculator
if (entry.IsPrime) if (entry.IsPrime)
{ {
AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite, 1); AddFactorToCollector(primeSlots, exponentSlots, ref factorCount, composite);
} }
// composite is never smaller on the execution path // composite is never smaller on the execution path
// else if (composite > 1UL) // else if (composite > 1UL)