diff --git a/PerfectNumbers.Core/MersenneDivisorCycles.cs b/PerfectNumbers.Core/MersenneDivisorCycles.cs index afa8d70..851473c 100644 --- a/PerfectNumbers.Core/MersenneDivisorCycles.cs +++ b/PerfectNumbers.Core/MersenneDivisorCycles.cs @@ -411,7 +411,8 @@ public class MersenneDivisorCycles // Atomic.Add(ref _tryFactorIntoCountsInternalHits, 1UL); // Console.WriteLine($"MersenneDivisorCycles.TryFactorIntoCountsInternal hits {Volatile.Read(ref _tryFactorIntoCountsInternalHits)}"); - if (PrimeTester.IsPrimeCpu(remaining, CancellationToken.None)) + HeuristicPrimeTester primeTester = _primeTester ??= new(); + if (primeTester.IsPrimeGpu(remaining)) // if (PrimeTester.IsPrimeCpu(remaining, CancellationToken.None)) { AddFactor(counts, remaining); @@ -916,19 +917,22 @@ public class MersenneDivisorCycles return CalculateCycleLengthFallback(divisor); } - internal static bool TryCalculateCycleLengthHeuristic(ulong divisor, in MontgomeryDivisorData divisorData, out ulong cycleLength, bool skipPrimeOrderHeuristic = false) - { - if ((divisor & (divisor - 1UL)) == 0UL) - { - cycleLength = 1UL; - return true; - } + [ThreadStatic] + private static HeuristicPrimeTester? _primeTester; - if (divisor <= 3UL) - { - cycleLength = CalculateCycleLengthFallback(divisor); - return true; - } + internal static bool TryCalculateCycleLengthHeuristic(ulong divisor, in MontgomeryDivisorData divisorData, out ulong cycleLength, bool skipPrimeOrderHeuristic = false) + { + if ((divisor & (divisor - 1UL)) == 0UL) + { + cycleLength = 1UL; + return true; + } + + if (divisor <= 3UL) + { + cycleLength = CalculateCycleLengthFallback(divisor); + return true; + } // if (!skipPrimeOrderHeuristic) // { @@ -936,26 +940,27 @@ public class MersenneDivisorCycles // Console.WriteLine($"MersenneDivisorCycles.CalculateCycleLengthFallback hits {Volatile.Read(ref _tryCalculateCycleLengthHeuristicHits)}"); // } - // if (!skipPrimeOrderHeuristic && HeuristicPrimeTester.Exclusive.IsPrimeCpu(divisor, CancellationToken.None)) - if (!skipPrimeOrderHeuristic && PrimeTester.IsPrimeCpu(divisor, CancellationToken.None)) - // if (!skipPrimeOrderHeuristic && PrimeTester.IsPrimeCpu(divisor, CancellationToken.None)) - { - ulong computedOrder = PrimeOrderCalculator.Calculate( - divisor, - previousOrder: null, - divisorData, - PrimeOrderCalculator.PrimeOrderSearchConfig.HeuristicDefault, - PrimeOrderCalculator.PrimeOrderHeuristicDevice.Cpu); - if (computedOrder != 0UL) - { - cycleLength = computedOrder; - return true; - } - } + HeuristicPrimeTester primeTester = _primeTester ??= new(); + // if (!skipPrimeOrderHeuristic && HeuristicPrimeTester.Exclusive.IsPrimeCpu(divisor, CancellationToken.None)) + if (!skipPrimeOrderHeuristic && primeTester.IsPrimeGpu(divisor)) + // if (!skipPrimeOrderHeuristic && PrimeTester.IsPrimeCpu(divisor, CancellationToken.None)) + { + ulong computedOrder = PrimeOrderCalculator.Calculate( + divisor, + previousOrder: null, + divisorData, + PrimeOrderCalculator.PrimeOrderSearchConfig.HeuristicDefault, + PrimeOrderCalculator.PrimeOrderHeuristicDevice.Cpu); + if (computedOrder != 0UL) + { + cycleLength = computedOrder; + return true; + } + } - cycleLength = 0UL; - return false; - } + cycleLength = 0UL; + return false; + } private static ulong CalculateCycleLengthFallback(ulong divisor) { diff --git a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs index 31ba9da..1be9074 100644 --- a/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs +++ b/PerfectNumbers.Core/PrimeOrderCalculator.Cpu.cs @@ -1078,6 +1078,8 @@ internal static partial class PrimeOrderCalculator Stack? compositeStack = null; PartialFactorResult result; PrimeTester primeTester = PrimeTester.Exclusive; + CancellationToken ct = CancellationToken.None; + HeuristicPrimeTester? tester = _tester ??= new(); if (!gpuFactored) { @@ -1150,7 +1152,7 @@ internal static partial class PrimeOrderCalculator // Console.WriteLine($"Partial factor hits {Volatile.Read(ref _partialFactorHits)}"); // bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None); - bool isPrime = PrimeTester.IsPrimeGpu(composite); + bool isPrime = tester.IsPrimeGpu(composite); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); if (isPrime) @@ -1218,7 +1220,7 @@ internal static partial class PrimeOrderCalculator // Console.WriteLine($"Partial factor pending hits {Volatile.Read(ref _partialFactorPendingHits)}"); // bool isPrime = PrimeTester.IsPrimeCpu(composite, CancellationToken.None); - bool isPrime = PrimeTester.IsPrimeGpu(composite); + bool isPrime = tester.IsPrimeGpu(composite); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(composite); entry = entry.WithPrimality(isPrime); @@ -1255,7 +1257,7 @@ internal static partial class PrimeOrderCalculator // Atomic.Add(ref _partialFactorCofactorHits, 1UL); // Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}"); - cofactorIsPrime = PrimeTester.IsPrimeCpu(cofactor, CancellationToken.None); + cofactorIsPrime = tester.IsPrimeGpu(cofactor); // cofactorIsPrime = PrimeTester.IsPrimeGpu(cofactor); // cofactorIsPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(cofactor); } @@ -1777,9 +1779,11 @@ internal static partial class PrimeOrderCalculator { FactorCompletely(value, counts, knownComposite: false); } - + // private static ulong _factorCompletelyHits; // private static ulong _factorCompletelyPollardRhoHits; + [ThreadStatic] + private static HeuristicPrimeTester? _tester; private static void FactorCompletely(ulong value, Dictionary counts, bool knownComposite) { @@ -1790,10 +1794,10 @@ internal static partial class PrimeOrderCalculator // Atomic.Add(ref _factorCompletelyHits, 1UL); // Console.WriteLine($"Factor completely hits {Volatile.Read(ref _factorCompletelyHits)}"); - // PrimeTester primeTester = PrimeTester.Exclusive; + HeuristicPrimeTester tester = _tester ??= new(); // bool isPrime = primeTester.HeuristicIsPrimeGpu(value); - bool isPrime = PrimeTester.IsPrimeCpu(value, CancellationToken.None); + bool isPrime = tester.IsPrimeGpu(value); // bool isPrime = PrimeTester.IsPrimeGpu(value); // bool isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(value); if (!knownComposite && isPrime) @@ -1809,7 +1813,7 @@ internal static partial class PrimeOrderCalculator // Console.WriteLine($"Factor completely after PollardRho hits {Volatile.Read(ref _factorCompletelyPollardRhoHits)}"); // isPrime = primeTester.HeuristicIsPrimeGpu(factor); - isPrime = PrimeTester.IsPrimeCpu(factor, CancellationToken.None); + isPrime = tester.IsPrimeGpu(factor); // isPrime = PrimeTester.IsPrimeGpu(factor); // isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(factor); if (isPrime) @@ -1846,7 +1850,7 @@ internal static partial class PrimeOrderCalculator // Atomic.Add(ref _partialFactorCofactorHits, 1UL); // Console.WriteLine($"Partial factor cofactor hits {Volatile.Read(ref _partialFactorCofactorHits)}"); - isPrime = PrimeTester.IsPrimeCpu(quotient, CancellationToken.None); + isPrime = tester.IsPrimeGpu(quotient); // isPrime = PrimeTester.IsPrimeGpu(quotient); // isPrime = Open.Numeric.Primes.Prime.Numbers.IsPrime(quotient); }