using System.Buffers; using System.Runtime.CompilerServices; using PerfectNumbers.Core.Cpu; using PerfectNumbers.Core.Gpu; using PeterO.Numbers; namespace PerfectNumbers.Core { public readonly struct ThreadStaticPools { [ThreadStatic] private static ArrayPool? _eintegerPool; public static ArrayPool EIntegerPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _eintegerPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _factorEntryPool; public static ArrayPool FactorEntryPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _factorEntryPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _factorEntry128Pool; public static ArrayPool FactorEntry128Pool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _factorEntry128Pool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _gpuUInt128Pool; public static ArrayPool GpuUInt128Pool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _gpuUInt128Pool ??= ArrayPool.Create(); } } [ThreadStatic] private static MersenneCpuDivisorScanSession? _mersenneCpuDivisorSession; [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static MersenneCpuDivisorScanSession? RentMersenneCpuDivisorSession() { MersenneCpuDivisorScanSession? session = _mersenneCpuDivisorSession; if (session is null) { return null; } _mersenneCpuDivisorSession = null; return session; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void ReturnMersenneCpuDivisorSession(MersenneCpuDivisorScanSession session) { _mersenneCpuDivisorSession = session; } [ThreadStatic] private static ArrayPool? _uint128Pool; public static ArrayPool UInt128Pool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _uint128Pool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _ulongPool; public static ArrayPool UlongPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _ulongPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _boolPool; public static ArrayPool BoolPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _boolPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _bytePool; public static ArrayPool BytePool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _bytePool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _montgomeryDivisorDataPool; public static ArrayPool MontgomeryDivisorDataPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _montgomeryDivisorDataPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _gpuDivisorPartialDataPool; internal static ArrayPool GpuDivisorPartialDataPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _gpuDivisorPartialDataPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _intPool; public static ArrayPool IntPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _intPool ??= ArrayPool.Create(); } } [ThreadStatic] private static ArrayPool? _charPool; public static ArrayPool CharPool { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return _charPool ??= ArrayPool.Create(); } } [ThreadStatic] private static List>? _ulongListPool; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List RentUlongList(int capacityHint) { List>? pool = _ulongListPool; if (pool is not null) { int poolCount = pool.Count; if (poolCount > 0) { int lastIndex = poolCount - 1; List list = pool[lastIndex]; pool.RemoveAt(lastIndex); if (list.Capacity < capacityHint) { list.Capacity = capacityHint; } return list; } } return new List(capacityHint); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnUlongList(List list) { List>? pool = _ulongListPool; if (pool is null) { pool = new List>(4); _ulongListPool = pool; } pool.Add(list); } [ThreadStatic] private static ArrayPool<(ulong, ulong)>? _ulongUlongTupleArrayPool; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static (ulong, ulong)[] RentUlongUlongArray(int capacityHint) { _ulongUlongTupleArrayPool ??= ArrayPool<(ulong, ulong)>.Create(); ArrayPool<(ulong, ulong)>? pool = _ulongUlongTupleArrayPool; return pool.Rent(capacityHint); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Return((ulong, ulong)[] array) => _ulongUlongTupleArrayPool!.Return(array, clearArray: false); [ThreadStatic] private static List>? _primeOrderPendingEntryListPool; [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static List RentPrimeOrderPendingEntryList(int capacityHint) { List>? pool = _primeOrderPendingEntryListPool; if (pool is not null) { int poolCount = pool.Count; if (poolCount > 0) { int lastIndex = poolCount - 1; List list = pool[lastIndex]; pool.RemoveAt(lastIndex); if (list.Capacity < capacityHint) { list.Capacity = capacityHint; } return list; } } return new List(capacityHint); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void ReturnPrimeOrderPendingEntryList(List list) { List>? pool = _primeOrderPendingEntryListPool; if (pool is null) { pool = new List>(4); _primeOrderPendingEntryListPool = pool; } pool.Add(list); } [ThreadStatic] private static List>? _ulongStackPool; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Stack RentUlongStack(int capacityHint) { List>? pool = _ulongStackPool; if (pool is not null) { int poolCount = pool.Count; if (poolCount > 0) { int lastIndex = poolCount - 1; Stack stack = pool[lastIndex]; pool.RemoveAt(lastIndex); if (stack.Count < capacityHint) { stack.EnsureCapacity(capacityHint); } return stack; } } return new Stack(capacityHint); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnUlongStack(Stack stack) { List>? pool = _ulongStackPool; if (pool is null) { pool = new List>(4); _ulongStackPool = pool; } pool.Add(stack); } [ThreadStatic] private static Dictionary? _factorCountDictionary; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Dictionary RentFactorCountDictionary() { Dictionary? dictionary = _factorCountDictionary; if (dictionary is null) { return new Dictionary(8); } _factorCountDictionary = null; return dictionary; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnFactorCountDictionary(Dictionary dictionary) { _factorCountDictionary = dictionary; } [ThreadStatic] private static Dictionary? _factorScratchDictionary; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Dictionary RentFactorScratchDictionary() { Dictionary? dictionary = _factorScratchDictionary; if (dictionary is null) { return new Dictionary(8); } _factorScratchDictionary = null; return dictionary; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnFactorScratchDictionary(Dictionary dictionary) { _factorScratchDictionary = dictionary; } [ThreadStatic] private static ExponentRemainderStepperCpu _exponentRemainderStepperCpu; [ThreadStatic] private static bool _hasExponentRemainderStepperCpu; [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ExponentRemainderStepperCpu RentExponentStepperCpu(in MontgomeryDivisorData divisorData) { if (_hasExponentRemainderStepperCpu && _exponentRemainderStepperCpu.MatchesDivisor(divisorData)) { ExponentRemainderStepperCpu stepper = _exponentRemainderStepperCpu; _hasExponentRemainderStepperCpu = false; stepper.Reset(); return stepper; } return new ExponentRemainderStepperCpu(divisorData); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void ReturnExponentStepperCpu(ExponentRemainderStepperCpu stepper) { stepper.Reset(); _exponentRemainderStepperCpu = stepper; _hasExponentRemainderStepperCpu = true; } } }