Reuse pooled local cache for partial factor primality checks

This commit is contained in:
Marek Lemańczyk committed 2025-10-19 23:35:08 +02:00
1 parent b7c187bbc5
commit 0fbd635828
1 file changed
+18 -33
+18 -33
View File
@@ -721,34 +721,8 @@ internal static partial class PrimeOrderCalculator
} }
[ThreadStatic]
private static Dictionary<ulong, bool>? _partialFactorPrimalityCache;
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ResetPartialFactorPrimalityCache() private static bool EvaluatePrimalityPartialFactor(ref Dictionary<ulong, bool>? localCache, ulong candidate)
{
Dictionary<ulong, bool>? cache = _partialFactorPrimalityCache;
if (cache is not null && cache.Count > 0)
{
cache.Clear();
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Dictionary<ulong, bool> GetPartialFactorPrimalityCache()
{
Dictionary<ulong, bool>? cache = _partialFactorPrimalityCache;
if (cache is null)
{
cache = ThreadStaticPools.RentUlongBoolDictionary(4);
_partialFactorPrimalityCache = cache;
}
return cache;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool EvaluatePrimalityPartialFactor(ulong candidate)
{ {
if (TryGetCachedPrimality(candidate, out bool cached)) if (TryGetCachedPrimality(candidate, out bool cached))
{ {
@@ -758,7 +732,7 @@ internal static partial class PrimeOrderCalculator
ulong globalCacheLimit = (ulong)PerfectNumberConstants.MaxQForDivisorCycles; ulong globalCacheLimit = (ulong)PerfectNumberConstants.MaxQForDivisorCycles;
if (candidate > globalCacheLimit) if (candidate > globalCacheLimit)
{ {
Dictionary<ulong, bool>? cache = _partialFactorPrimalityCache; Dictionary<ulong, bool>? cache = localCache;
if (cache is not null && cache.TryGetValue(candidate, out bool cachedValue)) if (cache is not null && cache.TryGetValue(candidate, out bool cachedValue))
{ {
return cachedValue; return cachedValue;
@@ -770,7 +744,13 @@ internal static partial class PrimeOrderCalculator
if (candidate > globalCacheLimit) if (candidate > globalCacheLimit)
{ {
Dictionary<ulong, bool> cache = GetPartialFactorPrimalityCache(); Dictionary<ulong, bool>? cache = localCache;
if (cache is null)
{
cache = ThreadStaticPools.RentUlongBoolDictionary(4);
localCache = cache;
}
cache[candidate] = isPrime; cache[candidate] = isPrime;
} }
@@ -813,8 +793,8 @@ internal static partial class PrimeOrderCalculator
List<PendingEntry> pending = ThreadStaticPools.RentPrimeOrderPendingEntryList(2); List<PendingEntry> pending = ThreadStaticPools.RentPrimeOrderPendingEntryList(2);
Stack<ulong>? compositeStack = null; Stack<ulong>? compositeStack = null;
PartialFactorResult result; PartialFactorResult result;
Dictionary<ulong, bool>? primalityCache = null;
ResetPartialFactorPrimalityCache();
if (!gpuFactored) if (!gpuFactored)
{ {
@@ -887,7 +867,7 @@ internal static partial class PrimeOrderCalculator
// continue; // continue;
// } // }
bool isPrime = EvaluatePrimalityPartialFactor(composite); bool isPrime = EvaluatePrimalityPartialFactor(ref primalityCache, composite);
if (isPrime) if (isPrime)
{ {
@@ -937,7 +917,7 @@ internal static partial class PrimeOrderCalculator
continue; continue;
} }
bool isPrime = EvaluatePrimalityPartialFactor(composite); bool isPrime = EvaluatePrimalityPartialFactor(ref primalityCache, composite);
if (isPrime) if (isPrime)
{ {
@@ -963,7 +943,7 @@ internal static partial class PrimeOrderCalculator
} }
else else
{ {
cofactorIsPrime = EvaluatePrimalityPartialFactor(cofactor); cofactorIsPrime = EvaluatePrimalityPartialFactor(ref primalityCache, cofactor);
} }
ArrayPool<FactorEntry> pool = ThreadStaticPools.FactorEntryPool; ArrayPool<FactorEntry> pool = ThreadStaticPools.FactorEntryPool;
@@ -1038,6 +1018,11 @@ internal static partial class PrimeOrderCalculator
// ThreadStaticPools.IntPool.Return(exponentSlotsArray); // ThreadStaticPools.IntPool.Return(exponentSlotsArray);
if (primalityCache is not null)
{
ThreadStaticPools.ReturnUlongBoolDictionary(primalityCache);
}
if (counts is not null) if (counts is not null)
{ {
ThreadStaticPools.ReturnUlongIntDictionary(counts); ThreadStaticPools.ReturnUlongIntDictionary(counts);