Reusable buffers introduced.
This commit is contained in:
1 parent
fd58079c5a
commit
39a66fdef1
8 files changed
+829
-1056
No files matched your search
@@ -1,154 +1,109 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using PerfectNumbers.Core.Gpu;
|
||||
|
||||
namespace PerfectNumbers.Core
|
||||
{
|
||||
public sealed class PartialFactorResult
|
||||
{
|
||||
private const int ExponentHardLimit = 256;
|
||||
|
||||
[ThreadStatic]
|
||||
private static PartialFactorResult? s_poolHead;
|
||||
|
||||
public ulong[]? Factors;
|
||||
public int[]? Exponents;
|
||||
private PartialFactorResult? _next;
|
||||
public ulong Cofactor;
|
||||
public bool FullyFactored;
|
||||
public int Count;
|
||||
public bool CofactorIsPrime;
|
||||
|
||||
private PartialFactorResult()
|
||||
{
|
||||
}
|
||||
|
||||
public static PartialFactorResult Rent(in ulong[]? factors, in int[]? exponents, ulong cofactor, bool fullyFactored, int count, bool cofactorIsPrime)
|
||||
{
|
||||
PartialFactorResult? instance = s_poolHead;
|
||||
if (instance is null)
|
||||
{
|
||||
instance = new PartialFactorResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
s_poolHead = instance._next;
|
||||
}
|
||||
|
||||
instance._next = null;
|
||||
instance.Factors = factors;
|
||||
instance.Exponents = exponents;
|
||||
instance.Cofactor = cofactor;
|
||||
instance.FullyFactored = fullyFactored;
|
||||
instance.Count = count;
|
||||
instance.CofactorIsPrime = cofactorIsPrime;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static PartialFactorResult Rent(ulong cofactor, bool fullyFactored, int count, bool cofactorIsPrime)
|
||||
{
|
||||
PartialFactorResult? instance = s_poolHead;
|
||||
if (instance is null)
|
||||
{
|
||||
instance = new PartialFactorResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
s_poolHead = instance._next;
|
||||
}
|
||||
|
||||
instance._next = null;
|
||||
instance.Factors = null;
|
||||
instance.Exponents = null;
|
||||
instance.Cofactor = cofactor;
|
||||
instance.FullyFactored = fullyFactored;
|
||||
instance.Count = count;
|
||||
instance.CofactorIsPrime = cofactorIsPrime;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static readonly PartialFactorResult Empty = new()
|
||||
public static readonly PartialFactorResult Empty = new(MontgomeryDivisorData.Empty)
|
||||
{
|
||||
Cofactor = 1UL,
|
||||
FullyFactored = true
|
||||
};
|
||||
|
||||
internal readonly List<PartialFactorPendingEntry> Pending = new(PrimeOrderConstants.GpuSmallPrimeFactorSlots);
|
||||
internal readonly FixedCapacityStack<ulong> CompositeStack = new(PrimeOrderConstants.GpuSmallPrimeFactorSlots);
|
||||
internal readonly ulong[] SpecialMaxBuffer = new ulong[PrimeOrderConstants.GpuSmallPrimeFactorSlots];
|
||||
|
||||
public readonly ulong[] Factors = new ulong[ExponentHardLimit];
|
||||
public readonly int[] Exponents = new int[ExponentHardLimit];
|
||||
public readonly ulong[] FactorCandidates = new ulong[ExponentHardLimit];
|
||||
public readonly List<ulong> FactorCandidatesList = new(ExponentHardLimit);
|
||||
public readonly ulong[] ValidateOrderFactorCandidates = new ulong[ExponentHardLimit];
|
||||
public readonly bool[] FactorCandidateEvaluations = new bool[ExponentHardLimit];
|
||||
internal readonly Dictionary<ulong, int> FactorCounts = new(capacity: 8);
|
||||
public ExponentRemainderStepperCpu ExponentRemainderStepper;
|
||||
|
||||
private PartialFactorResult? _next;
|
||||
public ulong Cofactor;
|
||||
public bool CofactorIsPrime;
|
||||
public int Count;
|
||||
public bool FullyFactored;
|
||||
public bool HasFactors;
|
||||
|
||||
private PartialFactorResult(in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
ExponentRemainderStepper = new(divisorData);
|
||||
}
|
||||
|
||||
public static PartialFactorResult Rent(in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
if (s_poolHead is { } instance)
|
||||
{
|
||||
s_poolHead = instance._next;
|
||||
instance._next = null;
|
||||
instance.Cofactor = 0UL;
|
||||
instance.FullyFactored = false;
|
||||
instance.Count = 0;
|
||||
instance.CofactorIsPrime = false;
|
||||
instance.HasFactors = false;
|
||||
if (!instance.ExponentRemainderStepper.MatchesDivisor(divisorData, 0UL))
|
||||
{
|
||||
instance.ExponentRemainderStepper = new ExponentRemainderStepperCpu(divisorData, 0UL);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
return new PartialFactorResult(divisorData);
|
||||
}
|
||||
|
||||
public void WithAdditionalPrime(ulong prime)
|
||||
{
|
||||
ulong[]? sourceFactors = Factors;
|
||||
ulong[] sourceFactors = Factors;
|
||||
int sourceCount = Count;
|
||||
if (sourceFactors is null || sourceCount == 0)
|
||||
if (sourceCount == 0)
|
||||
{
|
||||
InitializeWithPrime(prime);
|
||||
return;
|
||||
}
|
||||
|
||||
int newSize = (int)BitOperations.RoundUpToPowerOf2((uint)sourceCount + 1U);
|
||||
ulong[] extendedFactors = sourceFactors.Length >= newSize
|
||||
? sourceFactors
|
||||
: ResizeFactors(sourceFactors, sourceCount, newSize);
|
||||
int[] sourceExponents = Exponents;
|
||||
|
||||
int[] sourceExponents = Exponents!;
|
||||
int[] extendedExponents = sourceExponents.Length >= newSize
|
||||
? sourceExponents
|
||||
: ResizeExponents(sourceCount, newSize, sourceExponents);
|
||||
int newSize = sourceCount + 1;
|
||||
sourceFactors[sourceCount] = prime;
|
||||
sourceExponents[sourceCount] = 1;
|
||||
Array.Sort(sourceFactors, sourceExponents, 0, newSize);
|
||||
|
||||
newSize = sourceCount + 1;
|
||||
extendedFactors[sourceCount] = prime;
|
||||
extendedExponents[sourceCount] = 1;
|
||||
Array.Sort(extendedFactors, extendedExponents, 0, newSize);
|
||||
|
||||
Factors = extendedFactors;
|
||||
Exponents = extendedExponents;
|
||||
Cofactor = 1UL;
|
||||
FullyFactored = true;
|
||||
Count = newSize;
|
||||
CofactorIsPrime = false;
|
||||
}
|
||||
|
||||
private static int[] ResizeExponents(int sourceCount, int newSize, in int[] sourceExponents)
|
||||
{
|
||||
int[] extendedExponents = FixedCapacityPools.ExclusiveIntArray.Rent(newSize);
|
||||
Array.Copy(sourceExponents, 0, extendedExponents, 0, sourceCount);
|
||||
FixedCapacityPools.ExclusiveIntArray.Return(sourceExponents);
|
||||
return extendedExponents;
|
||||
}
|
||||
|
||||
private static ulong[] ResizeFactors(in ulong[] sourceFactors, int sourceCount, int newSize)
|
||||
{
|
||||
ulong[] extendedFactors = FixedCapacityPools.ExclusiveUlongArray.Rent(newSize);
|
||||
Array.Copy(sourceFactors, 0, extendedFactors, 0, sourceCount);
|
||||
FixedCapacityPools.ExclusiveUlongArray.Return(sourceFactors);
|
||||
return extendedFactors;
|
||||
HasFactors = true;
|
||||
}
|
||||
|
||||
private void InitializeWithPrime(ulong prime)
|
||||
{
|
||||
ulong[] factors = FixedCapacityPools.ExclusiveUlongArray.Rent(1);
|
||||
int[] exponents = FixedCapacityPools.ExclusiveIntArray.Rent(1);
|
||||
factors[0] = prime;
|
||||
exponents[0] = 1;
|
||||
Factors = factors;
|
||||
Exponents = exponents;
|
||||
Factors[0] = prime;
|
||||
Exponents[0] = 1;
|
||||
Cofactor = 1UL;
|
||||
FullyFactored = true;
|
||||
Count = 1;
|
||||
CofactorIsPrime = false;
|
||||
HasFactors = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (this != Empty)
|
||||
{
|
||||
|
||||
ulong[]? factors = Factors;
|
||||
|
||||
if (factors is not null)
|
||||
{
|
||||
int[] exponents = Exponents!;
|
||||
Factors = null;
|
||||
Exponents = null;
|
||||
|
||||
FixedCapacityPools.ExclusiveUlongArray.Return(factors);
|
||||
FixedCapacityPools.ExclusiveIntArray.Return(exponents);
|
||||
}
|
||||
|
||||
_next = s_poolHead;
|
||||
s_poolHead = this;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user