Reuse stack buffers when lowering divisor exponents
This commit is contained in:
1 parent
1b3a89ca53
commit
c15405e3b1
4 files changed
+497
-172
No files matched your search
@@ -1,4 +1,5 @@
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using PerfectNumbers.Core.Cpu;
|
||||
|
||||
@@ -30,7 +31,6 @@ namespace PerfectNumbers.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[ThreadStatic]
|
||||
private static MersenneCpuDivisorScanSession? _mersenneCpuDivisorSession;
|
||||
|
||||
@@ -66,6 +66,18 @@ namespace PerfectNumbers.Core
|
||||
}
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static ArrayPool<bool>? _boolPool;
|
||||
|
||||
public static ArrayPool<bool> BoolPool
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return _boolPool ??= ArrayPool<bool>.Create();
|
||||
}
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static ArrayPool<byte>? _bytePool;
|
||||
|
||||
@@ -102,7 +114,6 @@ namespace PerfectNumbers.Core
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[ThreadStatic]
|
||||
private static List<List<ulong>>? _ulongListPool;
|
||||
|
||||
@@ -110,22 +121,26 @@ namespace PerfectNumbers.Core
|
||||
public static List<ulong> RentUlongList(int capacityHint)
|
||||
{
|
||||
List<List<ulong>>? pool = _ulongListPool;
|
||||
if (pool is not null && pool.Count > 0)
|
||||
if (pool is not null)
|
||||
{
|
||||
int lastIndex = pool.Count - 1;
|
||||
List<ulong> list = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (list.Count > 0)
|
||||
int poolCount = pool.Count;
|
||||
if (poolCount > 0)
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
int lastIndex = poolCount - 1;
|
||||
List<ulong> list = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (list.Count > 0)
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
if (list.Capacity < capacityHint)
|
||||
{
|
||||
list.Capacity = capacityHint;
|
||||
}
|
||||
if (list.Capacity < capacityHint)
|
||||
{
|
||||
list.Capacity = capacityHint;
|
||||
}
|
||||
|
||||
return list;
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
return new List<ulong>(capacityHint);
|
||||
@@ -151,22 +166,26 @@ namespace PerfectNumbers.Core
|
||||
internal static List<PrimeOrderCalculator.PendingEntry> RentPrimeOrderPendingEntryList(int capacityHint)
|
||||
{
|
||||
List<List<PrimeOrderCalculator.PendingEntry>>? pool = _primeOrderPendingEntryListPool;
|
||||
if (pool is not null && pool.Count > 0)
|
||||
if (pool is not null)
|
||||
{
|
||||
int lastIndex = pool.Count - 1;
|
||||
List<PrimeOrderCalculator.PendingEntry> list = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (list.Count > 0)
|
||||
int poolCount = pool.Count;
|
||||
if (poolCount > 0)
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
int lastIndex = poolCount - 1;
|
||||
List<PrimeOrderCalculator.PendingEntry> list = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (list.Count > 0)
|
||||
{
|
||||
list.Clear();
|
||||
}
|
||||
|
||||
if (list.Capacity < capacityHint)
|
||||
{
|
||||
list.Capacity = capacityHint;
|
||||
}
|
||||
if (list.Capacity < capacityHint)
|
||||
{
|
||||
list.Capacity = capacityHint;
|
||||
}
|
||||
|
||||
return list;
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
return new List<PrimeOrderCalculator.PendingEntry>(capacityHint);
|
||||
@@ -192,22 +211,28 @@ namespace PerfectNumbers.Core
|
||||
public static Stack<ulong> RentUlongStack(int capacityHint)
|
||||
{
|
||||
List<Stack<ulong>>? pool = _ulongStackPool;
|
||||
if (pool is not null && pool.Count > 0)
|
||||
if (pool is not null)
|
||||
{
|
||||
int lastIndex = pool.Count - 1;
|
||||
Stack<ulong> stack = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (stack.Count > 0)
|
||||
int poolCount = pool.Count;
|
||||
if (poolCount > 0)
|
||||
{
|
||||
stack.Clear();
|
||||
}
|
||||
int lastIndex = poolCount - 1;
|
||||
Stack<ulong> stack = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
int stackCount = stack.Count;
|
||||
if (stackCount > 0)
|
||||
{
|
||||
stack.Clear();
|
||||
stackCount = 0;
|
||||
}
|
||||
|
||||
if (stack.Count < capacityHint)
|
||||
{
|
||||
stack.EnsureCapacity(capacityHint);
|
||||
}
|
||||
if (stackCount < capacityHint)
|
||||
{
|
||||
stack.EnsureCapacity(capacityHint);
|
||||
}
|
||||
|
||||
return stack;
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
return new Stack<ulong>(capacityHint);
|
||||
@@ -226,6 +251,7 @@ namespace PerfectNumbers.Core
|
||||
pool.Add(stack);
|
||||
}
|
||||
|
||||
// The factor-count scratch caches were removed because divisor factorizations never repeat across scan iterations.
|
||||
[ThreadStatic]
|
||||
private static List<Dictionary<ulong, int>>? _ulongIntDictionaryPool;
|
||||
|
||||
@@ -233,22 +259,23 @@ namespace PerfectNumbers.Core
|
||||
public static Dictionary<ulong, int> RentUlongIntDictionary(int capacityHint)
|
||||
{
|
||||
List<Dictionary<ulong, int>>? pool = _ulongIntDictionaryPool;
|
||||
if (pool is not null && pool.Count > 0)
|
||||
if (pool is not null)
|
||||
{
|
||||
int lastIndex = pool.Count - 1;
|
||||
Dictionary<ulong, int> dictionary = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (dictionary.Count > 0)
|
||||
int poolCount = pool.Count;
|
||||
if (poolCount > 0)
|
||||
{
|
||||
dictionary.Clear();
|
||||
}
|
||||
int lastIndex = poolCount - 1;
|
||||
Dictionary<ulong, int> dictionary = pool[lastIndex];
|
||||
pool.RemoveAt(lastIndex);
|
||||
if (dictionary.Count > 0)
|
||||
{
|
||||
dictionary.Clear();
|
||||
}
|
||||
|
||||
if (dictionary.Count < capacityHint)
|
||||
{
|
||||
dictionary.EnsureCapacity(capacityHint);
|
||||
}
|
||||
|
||||
return dictionary;
|
||||
return dictionary;
|
||||
}
|
||||
}
|
||||
|
||||
return new Dictionary<ulong, int>(capacityHint);
|
||||
@@ -268,51 +295,31 @@ namespace PerfectNumbers.Core
|
||||
}
|
||||
|
||||
[ThreadStatic]
|
||||
private static Dictionary<ulong, int>? _factorCountDictionary;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Dictionary<ulong, int> RentFactorCountDictionary()
|
||||
{
|
||||
Dictionary<ulong, int>? dictionary = _factorCountDictionary;
|
||||
if (dictionary is null)
|
||||
{
|
||||
return new Dictionary<ulong, int>(8);
|
||||
}
|
||||
|
||||
_factorCountDictionary = null;
|
||||
dictionary.Clear();
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ReturnFactorCountDictionary(Dictionary<ulong, int> dictionary)
|
||||
{
|
||||
dictionary.Clear();
|
||||
_factorCountDictionary = dictionary;
|
||||
}
|
||||
private static ExponentRemainderStepper _exponentRemainderStepper;
|
||||
|
||||
[ThreadStatic]
|
||||
private static Dictionary<ulong, int>? _factorScratchDictionary;
|
||||
private static bool _hasExponentRemainderStepper;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Dictionary<ulong, int> RentFactorScratchDictionary()
|
||||
internal static ExponentRemainderStepper RentExponentStepper(in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
Dictionary<ulong, int>? dictionary = _factorScratchDictionary;
|
||||
if (dictionary is null)
|
||||
if (_hasExponentRemainderStepper && _exponentRemainderStepper.MatchesDivisor(divisorData))
|
||||
{
|
||||
return new Dictionary<ulong, int>(8);
|
||||
ExponentRemainderStepper stepper = _exponentRemainderStepper;
|
||||
_hasExponentRemainderStepper = false;
|
||||
stepper.Reset();
|
||||
return stepper;
|
||||
}
|
||||
|
||||
_factorScratchDictionary = null;
|
||||
dictionary.Clear();
|
||||
return dictionary;
|
||||
return new ExponentRemainderStepper(divisorData);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void ReturnFactorScratchDictionary(Dictionary<ulong, int> dictionary)
|
||||
internal static void ReturnExponentStepper(ExponentRemainderStepper stepper)
|
||||
{
|
||||
dictionary.Clear();
|
||||
_factorScratchDictionary = dictionary;
|
||||
stepper.Reset();
|
||||
_exponentRemainderStepper = stepper;
|
||||
_hasExponentRemainderStepper = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user