Primality tests normalized on GetOrComputePrimality. CofactorIsPrime added to factoring results for reuse in other places.

This commit is contained in:
mlemanczyk committed 2025-10-17 16:24:59 +02:00
1 parent c0f38fa104
commit e525484b48
3 files changed
+38 -39

No files matched your search

+3 -2
View File
@@ -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;
}
}
+12 -10
View File
@@ -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()
+23 -27
View File
@@ -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;