Primality tests normalized on GetOrComputePrimality. CofactorIsPrime added to factoring results for reuse in other places.
This commit is contained in:
1 parent
c0f38fa104
commit
e525484b48
3 files changed
+38
-39
No files matched your search
@@ -1,8 +1,9 @@
|
||||
namespace PerfectNumbers.Core
|
||||
{
|
||||
public readonly struct FactorEntry(ulong value, int exponent)
|
||||
public readonly struct FactorEntry(ulong value, int exponent, bool isPrime)
|
||||
{
|
||||
public readonly ulong Value = value;
|
||||
public readonly int Exponent = exponent;
|
||||
public readonly int Exponent = exponent;
|
||||
public readonly bool CofactorIsPrime = isPrime;
|
||||
}
|
||||
}
|
||||
@@ -11,13 +11,14 @@ namespace PerfectNumbers.Core
|
||||
private PartialFactorResult? _next;
|
||||
public ulong Cofactor;
|
||||
public bool FullyFactored;
|
||||
public int Count;
|
||||
public int Count;
|
||||
public bool CofactorIsPrime;
|
||||
|
||||
private PartialFactorResult()
|
||||
{
|
||||
}
|
||||
|
||||
public static PartialFactorResult Rent(in FactorEntry[]? factors, ulong cofactor, bool fullyFactored, int count)
|
||||
public static PartialFactorResult Rent(in FactorEntry[]? factors, ulong cofactor, bool fullyFactored, int count, bool cofactorIsPrime)
|
||||
{
|
||||
PartialFactorResult? instance = s_poolHead;
|
||||
if (instance is null)
|
||||
@@ -33,15 +34,16 @@ namespace PerfectNumbers.Core
|
||||
instance.Factors = factors;
|
||||
instance.Cofactor = cofactor;
|
||||
instance.FullyFactored = fullyFactored;
|
||||
instance.Count = count;
|
||||
instance.Count = count;
|
||||
instance.CofactorIsPrime = cofactorIsPrime;
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static readonly PartialFactorResult Empty = new()
|
||||
{
|
||||
Cofactor = 1UL,
|
||||
FullyFactored = true,
|
||||
};
|
||||
Cofactor = 1UL,
|
||||
FullyFactored = true
|
||||
};
|
||||
|
||||
public PartialFactorResult WithAdditionalPrime(ulong prime)
|
||||
{
|
||||
@@ -49,16 +51,16 @@ namespace PerfectNumbers.Core
|
||||
if (source is null || Count == 0)
|
||||
{
|
||||
FactorEntry[] local = ArrayPool<FactorEntry>.Shared.Rent(1);
|
||||
local[0] = new FactorEntry(prime, 1);
|
||||
return Rent(local, 1UL, true, 1);
|
||||
local[0] = new FactorEntry(prime, 1, true);
|
||||
return Rent(local, 1UL, true, 1, false);
|
||||
}
|
||||
|
||||
FactorEntry[] extended = ArrayPool<FactorEntry>.Shared.Rent(Count + 1);
|
||||
Array.Copy(source, 0, extended, 0, Count);
|
||||
extended[Count] = new FactorEntry(prime, 1);
|
||||
extended[Count] = new FactorEntry(prime, 1, true);
|
||||
Span<FactorEntry> span = extended.AsSpan(0, Count + 1);
|
||||
span.Sort(static (a, b) => a.Value.CompareTo(b.Value));
|
||||
return Rent(extended, 1UL, true, Count + 1);
|
||||
return Rent(extended, 1UL, true, Count + 1, false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@@ -126,11 +126,11 @@ internal static partial class PrimeOrderCalculator
|
||||
Span<FactorEntry> buffer = tempArray;
|
||||
factorSpan.CopyTo(buffer);
|
||||
|
||||
bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factors.Cofactor);
|
||||
// bool isPrime = PrimeTester.IsPrimeInternal(factors.Cofactor, CancellationToken.None);
|
||||
if (!factors.FullyFactored && factors.Cofactor > 1UL && isPrime)
|
||||
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factors.Cofactor);
|
||||
if (!factors.FullyFactored && factors.Cofactor > 1UL && factors.CofactorIsPrime)
|
||||
{
|
||||
buffer[length] = new FactorEntry(factors.Cofactor, 1);
|
||||
buffer[length] = new FactorEntry(factors.Cofactor, 1, true);
|
||||
length++;
|
||||
}
|
||||
|
||||
@@ -190,14 +190,7 @@ internal static partial class PrimeOrderCalculator
|
||||
|
||||
if (!factorization.FullyFactored)
|
||||
{
|
||||
if (factorization.Cofactor <= 1UL)
|
||||
{
|
||||
factorization.Dispose();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factorization.Cofactor);
|
||||
if (!isPrime)
|
||||
if (factorization.Cofactor <= 1UL || !factorization.CofactorIsPrime)
|
||||
{
|
||||
factorization.Dispose();
|
||||
return false;
|
||||
@@ -281,9 +274,8 @@ internal static partial class PrimeOrderCalculator
|
||||
return false;
|
||||
}
|
||||
|
||||
var isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(orderFactors.Cofactor);
|
||||
// if (!PrimeTester.IsPrimeInternal(orderFactors.Cofactor, CancellationToken.None))
|
||||
if (!isPrime)
|
||||
if (!orderFactors.CofactorIsPrime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -607,9 +599,9 @@ internal static partial class PrimeOrderCalculator
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factorization.Cofactor);
|
||||
// bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factorization.Cofactor);
|
||||
// bool isPrime = PrimeTester.IsPrimeInternal(factorization.Cofactor, CancellationToken.None);
|
||||
if (!isPrime)
|
||||
if (!factorization.CofactorIsPrime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -839,9 +831,10 @@ internal static partial class PrimeOrderCalculator
|
||||
|
||||
ulong cofactor = 1UL;
|
||||
int pendingCount = pending.Count;
|
||||
for (int i = 0; i < pendingCount; i++)
|
||||
int index = 0;
|
||||
for (; index < pendingCount; index++)
|
||||
{
|
||||
ulong composite = pending[i];
|
||||
ulong composite = pending[index];
|
||||
bool isPrime = GetOrComputePrimality(composite);
|
||||
|
||||
if (isPrime)
|
||||
@@ -856,33 +849,35 @@ internal static partial class PrimeOrderCalculator
|
||||
}
|
||||
}
|
||||
|
||||
bool cofactorIsPrime = GetOrComputePrimality(cofactor);
|
||||
ArrayPool<FactorEntry> pool = ThreadStaticPools.FactorEntryPool;
|
||||
bool temp;
|
||||
if (useDictionary)
|
||||
{
|
||||
if ((counts is null || counts.Count == 0) && cofactor == value)
|
||||
{
|
||||
result = PartialFactorResult.Rent(null, value, false, 0);
|
||||
result = PartialFactorResult.Rent(null, cofactor, false, 0, cofactorIsPrime);
|
||||
goto ReturnResult;
|
||||
}
|
||||
|
||||
if (counts is null || counts.Count == 0)
|
||||
{
|
||||
result = PartialFactorResult.Rent(null, cofactor, cofactor == 1UL, 0);
|
||||
result = PartialFactorResult.Rent(null, cofactor, cofactor == 1UL, 0, cofactorIsPrime);
|
||||
goto ReturnResult;
|
||||
}
|
||||
|
||||
FactorEntry[] factors = pool.Rent(counts.Count);
|
||||
int index = 0;
|
||||
index = 0;
|
||||
foreach (KeyValuePair<ulong, int> entry in counts)
|
||||
{
|
||||
factors[index] = new FactorEntry(entry.Key, entry.Value);
|
||||
factors[index] = new FactorEntry(entry.Key, entry.Value, true);
|
||||
index++;
|
||||
}
|
||||
|
||||
Array.Sort(factors, static (a, b) => a.Value.CompareTo(b.Value));
|
||||
|
||||
bool fullyFactored = cofactor == 1UL;
|
||||
result = PartialFactorResult.Rent(factors, cofactor, fullyFactored, index);
|
||||
temp = cofactor == 1UL;
|
||||
result = PartialFactorResult.Rent(factors, cofactor, temp, index, cofactorIsPrime);
|
||||
goto ReturnResult;
|
||||
}
|
||||
|
||||
@@ -912,14 +907,14 @@ internal static partial class PrimeOrderCalculator
|
||||
// continue;
|
||||
// }
|
||||
|
||||
array[arrayIndex] = new FactorEntry(primeValue, exponentValue);
|
||||
array[arrayIndex] = new FactorEntry(primeValue, exponentValue, true);
|
||||
arrayIndex++;
|
||||
}
|
||||
|
||||
Span<FactorEntry> arraySpan = array.AsSpan(0, arrayIndex);
|
||||
arraySpan.Sort(static (a, b) => a.Value.CompareTo(b.Value));
|
||||
bool fullyFactoredArray = cofactor == 1UL;
|
||||
result = PartialFactorResult.Rent(array, cofactor, fullyFactoredArray, arrayIndex);
|
||||
temp = cofactor == 1UL;
|
||||
result = PartialFactorResult.Rent(array, cofactor, temp, arrayIndex, cofactorIsPrime);
|
||||
|
||||
ReturnResult:
|
||||
// ThreadStaticPools.UlongPool.Return(primeSlotsArray);
|
||||
@@ -1372,7 +1367,8 @@ internal static partial class PrimeOrderCalculator
|
||||
return;
|
||||
}
|
||||
|
||||
if (Open.Numeric.Primes.Prime.Numbers.IsPrime(value))
|
||||
// if (Open.Numeric.Primes.Prime.Numbers.IsPrime(value))
|
||||
if (GetOrComputePrimality(value))
|
||||
{
|
||||
AddFactor(counts, value, 1);
|
||||
return;
|
||||
|
||||
Reference in new issue
Block a user