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