Merge branch 'codex/analyze-gc-instances-in-checkdivisors-method' of https://github.com/mlemanczyk/even-perfect-numbers-scanner into codex/analyze-gc-instances-in-checkdivisors-method

This commit is contained in:
mlemanczyk committed 2025-10-17 03:51:09 +02:00
commit f5c79c8807
2 files changed
+2 -195

No files matched your search

+2 -171
View File
@@ -10,18 +10,6 @@ namespace PerfectNumbers.Core;
internal static partial class PrimeOrderCalculator
{
[ThreadStatic]
private static CycleRemainderStepper[]? s_smallPrimeCycleSteppers;
[ThreadStatic]
private static ulong[]? s_smallPrimeStepperPreviousValues;
[ThreadStatic]
private static ulong[]? s_smallPrimeStepperRemainders;
[ThreadStatic]
private static bool[]? s_smallPrimeStepperHasState;
private static ulong CalculateInternal(ulong prime, ulong? previousOrder, in MontgomeryDivisorData divisorData, in PrimeOrderSearchConfig config)
{
// TODO: Is this condition ever met on EvenPerfectBitScanner's execution path? If not, we can add a clarification comment and comment out the entire block. We want to support p candidates at least greater or equal to 31.
@@ -908,128 +896,6 @@ internal static partial class PrimeOrderCalculator
return result;
}
private static CycleRemainderStepper[] EnsureSmallPrimeCycleSteppers(uint[] primes)
{
int primeCount = primes.Length;
CycleRemainderStepper[]? steppers = s_smallPrimeCycleSteppers;
ArrayPool<CycleRemainderStepper> stepperPool = ThreadStaticPools.CycleRemainderStepperPool;
ArrayPool<ulong> ulongPool = ThreadStaticPools.UlongPool;
ArrayPool<bool> boolPool = ThreadStaticPools.BoolPool;
if (steppers is null || steppers.Length < primeCount)
{
CycleRemainderStepper[]? previousSteppers = steppers;
steppers = stepperPool.Rent(primeCount);
int stepperLength = steppers.Length;
for (int i = 0; i < primeCount; i++)
{
steppers[i] = new CycleRemainderStepper(primes[i]);
}
for (int i = primeCount; i < stepperLength; i++)
{
steppers[i] = default;
}
if (previousSteppers is not null)
{
stepperPool.Return(previousSteppers, clearArray: false);
}
if (s_smallPrimeStepperPreviousValues is not null)
{
ulongPool.Return(s_smallPrimeStepperPreviousValues, clearArray: false);
}
if (s_smallPrimeStepperRemainders is not null)
{
ulongPool.Return(s_smallPrimeStepperRemainders, clearArray: false);
}
if (s_smallPrimeStepperHasState is not null)
{
boolPool.Return(s_smallPrimeStepperHasState, clearArray: false);
}
ulong[] previousValues = ulongPool.Rent(stepperLength);
Array.Clear(previousValues, 0, stepperLength);
ulong[] remainders = ulongPool.Rent(stepperLength);
Array.Clear(remainders, 0, stepperLength);
bool[] hasState = boolPool.Rent(stepperLength);
Array.Clear(hasState, 0, stepperLength);
s_smallPrimeCycleSteppers = steppers;
s_smallPrimeStepperPreviousValues = previousValues;
s_smallPrimeStepperRemainders = remainders;
s_smallPrimeStepperHasState = hasState;
return steppers;
}
int stepperCapacity = steppers.Length;
if (s_smallPrimeStepperPreviousValues is null || s_smallPrimeStepperPreviousValues.Length != stepperCapacity)
{
ulong[] newPrevious = ulongPool.Rent(stepperCapacity);
if (s_smallPrimeStepperPreviousValues is { } existingPrevious)
{
int copyLength = Math.Min(existingPrevious.Length, stepperCapacity);
System.Array.Copy(existingPrevious, newPrevious, copyLength);
if (copyLength < stepperCapacity)
{
Array.Clear(newPrevious, copyLength, stepperCapacity - copyLength);
}
ulongPool.Return(existingPrevious, clearArray: false);
}
else
{
Array.Clear(newPrevious, 0, stepperCapacity);
}
s_smallPrimeStepperPreviousValues = newPrevious;
}
if (s_smallPrimeStepperRemainders is null || s_smallPrimeStepperRemainders.Length != stepperCapacity)
{
ulong[] newRemainders = ulongPool.Rent(stepperCapacity);
if (s_smallPrimeStepperRemainders is { } existingRemainders)
{
int copyLength = Math.Min(existingRemainders.Length, stepperCapacity);
System.Array.Copy(existingRemainders, newRemainders, copyLength);
if (copyLength < stepperCapacity)
{
Array.Clear(newRemainders, copyLength, stepperCapacity - copyLength);
}
ulongPool.Return(existingRemainders, clearArray: false);
}
else
{
Array.Clear(newRemainders, 0, stepperCapacity);
}
s_smallPrimeStepperRemainders = newRemainders;
}
if (s_smallPrimeStepperHasState is null || s_smallPrimeStepperHasState.Length != stepperCapacity)
{
bool[] newHasState = boolPool.Rent(stepperCapacity);
if (s_smallPrimeStepperHasState is { } existingHasState)
{
int copyLength = Math.Min(existingHasState.Length, stepperCapacity);
System.Array.Copy(existingHasState, newHasState, copyLength);
if (copyLength < stepperCapacity)
{
Array.Clear(newHasState, copyLength, stepperCapacity - copyLength);
}
boolPool.Return(existingHasState, clearArray: false);
}
else
{
Array.Clear(newHasState, 0, stepperCapacity);
}
s_smallPrimeStepperHasState = newHasState;
}
return steppers;
}
private static bool TryPopulateSmallPrimeFactorsCpu(
ulong value,
@@ -1060,11 +926,6 @@ internal static partial class PrimeOrderCalculator
int primeCount = primes.Length;
ulong remainingLocal = value;
uint effectiveLimit = limit == 0 ? uint.MaxValue : limit;
CycleRemainderStepper[] cycleSteppers = EnsureSmallPrimeCycleSteppers(primes);
ulong[] stepperPreviousValues = s_smallPrimeStepperPreviousValues!;
ulong[] stepperRemainders = s_smallPrimeStepperRemainders!;
bool[] stepperHasState = s_smallPrimeStepperHasState!;
ulong valueForSteppers = value;
for (int i = 0; i < primeCount && remainingLocal > 1UL; i++)
{
@@ -1088,42 +949,12 @@ internal static partial class PrimeOrderCalculator
// continue;
// }
ref CycleRemainderStepper stepper = ref cycleSteppers[i];
ulong remainder;
if (!stepperHasState[i])
{
stepper.Reset();
remainder = stepper.Initialize(valueForSteppers);
stepperHasState[i] = true;
}
else
{
ulong previousValue = stepperPreviousValues[i];
if (valueForSteppers > previousValue)
{
remainder = stepper.ComputeNext(valueForSteppers);
}
else if (valueForSteppers < previousValue)
{
stepper.Reset();
remainder = stepper.Initialize(valueForSteppers);
}
else
{
remainder = stepperRemainders[i];
}
}
stepperPreviousValues[i] = valueForSteppers;
stepperRemainders[i] = remainder;
if (remainder != 0UL)
ulong primeValue = primeCandidate;
if ((remainingLocal % primeValue) != 0UL)
{
continue;
}
ulong primeValue = primeCandidate;
int exponent = ExtractSmallPrimeExponent(ref remainingLocal, primeValue);
if (exponent == 0)
{