MersenneNumberTesterTemplate extended to depend on new enums: CacheStatus & OrderDevice instead of constructor parameters to limit code branches during execution.

This commit is contained in:
mlemanczyk committed 2025-12-19 22:01:21 +01:00
1 parent c5c42b0c19
commit 9147124ddf
5 files changed
+270 -367

No files matched your search

+19 -12
View File
@@ -227,7 +227,7 @@ public class ProgramTests
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( maxK: 1_000UL), trackAllValues: true)); mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL), trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
@@ -260,7 +260,7 @@ public class ProgramTests
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
maxK: 1_024UL), trackAllValues: true)); maxK: 1_024UL), trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
@@ -296,7 +296,7 @@ public class ProgramTests
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
maxK: 5_000_000UL), trackAllValues: true)); maxK: 5_000_000UL), trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
@@ -331,7 +331,7 @@ public class ProgramTests
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
maxK: 5_000_000UL), trackAllValues: true)); maxK: 5_000_000UL), trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
@@ -367,10 +367,8 @@ public class ProgramTests
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
useGpuScan: false,
useGpuOrder: false,
maxK: 1_024UL), trackAllValues: true)); maxK: 1_024UL), trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true));
@@ -402,12 +400,21 @@ public class ProgramTests
var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var mersenneField = typeof(Program).GetField("MersenneTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForResidueCalculationMethodForCpu( mersenneField.SetValue(null, new ThreadLocal<object>(() =>
{
if (configuration.UseGpuOrder)
{
return new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(
kernelType: configuration.KernelType, kernelType: configuration.KernelType,
useGpuScan: true, maxK: configuration.ResidueMaxK);
useGpuOrder: configuration.UseGpuOrder, }
maxK: configuration.ResidueMaxK), trackAllValues: true));
return new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
kernelType: configuration.KernelType,
maxK: configuration.ResidueMaxK);
}, trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true));
@@ -488,7 +495,7 @@ public class ProgramTests
var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!; var primeField = typeof(Program).GetField("PrimeTesters", BindingFlags.NonPublic | BindingFlags.Static)!;
var compositeField = typeof(Program).GetField("_lastCompositeP", BindingFlags.NonPublic | BindingFlags.Static)!; var compositeField = typeof(Program).GetField("_lastCompositeP", BindingFlags.NonPublic | BindingFlags.Static)!;
mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForIncrementalCalculationMethodForCpu( maxK: 1_000UL), trackAllValues: true)); mersenneField.SetValue(null, new ThreadLocal<object>(() => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu( maxK: 1_000UL), trackAllValues: true));
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true)); primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true)); CandidatesCalculator.OverrideResidueTrackers(new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
+137 -282
View File
@@ -28,7 +28,8 @@ private static ThreadLocal<object>? MersenneTesters;
private static int _testTargetPrimeCount; private static int _testTargetPrimeCount;
private static int _testProcessedPrimeCount; private static int _testProcessedPrimeCount;
private static ComputationDevice _mersenneDevice; private static ComputationDevice _mersenneDevice;
private static ComputationDevice _orderDevice; private static OrderDevice _orderCalculationDevice;
private static CacheStatus _cacheStatus;
private static CalculationMethod _calculationMethod; private static CalculationMethod _calculationMethod;
[ThreadStatic] [ThreadStatic]
@@ -99,17 +100,18 @@ private static ThreadLocal<object>? MersenneTesters;
: (useResidue ? PrimeTransformMode.Add : PrimeTransformMode.AddPrimes); : (useResidue ? PrimeTransformMode.Add : PrimeTransformMode.AddPrimes);
CandidatesCalculator.Configure(transformMode); CandidatesCalculator.Configure(transformMode);
ComputationDevice mersenneDevice = _cliArguments.MersenneDevice; ComputationDevice mersenneDevice = _cliArguments.MersenneDevice;
ComputationDevice orderDevice = EnvironmentConfiguration.OrderDevice;
_mersenneDevice = mersenneDevice; _mersenneDevice = mersenneDevice;
_orderDevice = orderDevice;
_calculationMethod = useResidue _calculationMethod = useResidue
? CalculationMethod.Residue ? CalculationMethod.Residue
: (useLucas : (useLucas
? CalculationMethod.LucasLehmer ? CalculationMethod.LucasLehmer
: (useOrder ? CalculationMethod.Divisor : CalculationMethod.Incremental)); : (useOrder ? CalculationMethod.Divisor : CalculationMethod.Incremental));
bool mersenneOnGpu = mersenneDevice == ComputationDevice.Gpu; bool mersenneOnGpu = mersenneDevice == ComputationDevice.Gpu;
bool orderOnGpu = EnvironmentConfiguration.UseGpuOrder; OrderDevice orderCalculationDevice = EnvironmentConfiguration.UseGpuOrder
bool orderOnHybrid = EnvironmentConfiguration.UseHybridOrder; ? OrderDevice.Gpu
: (EnvironmentConfiguration.UseHybridOrder ? OrderDevice.Hybrid : OrderDevice.Cpu);
_orderCalculationDevice = orderCalculationDevice;
_cacheStatus = CacheStatus.Disabled;
int sliceSize = Math.Max(1, _cliArguments.SliceSize); int sliceSize = Math.Max(1, _cliArguments.SliceSize);
ulong residueKMax = _cliArguments.ResidueKMax; ulong residueKMax = _cliArguments.ResidueKMax;
string filterFile = _cliArguments.FilterFile; string filterFile = _cliArguments.FilterFile;
@@ -228,18 +230,15 @@ private static ThreadLocal<object>? MersenneTesters;
{ {
object tester = CreateMersenneTester( object tester = CreateMersenneTester(
_calculationMethod, _calculationMethod,
orderDevice, _cacheStatus,
_orderCalculationDevice,
mersenneDevice,
kernelType, kernelType,
useLucas,
useOrder,
mersenneOnGpu,
orderOnGpu,
orderOnHybrid,
residueKMax); residueKMax);
if (!useLucas) if (!useLucas)
{ {
Console.WriteLine("Warming up orders"); Console.WriteLine("Warming up orders");
WarmUpOrders(tester, orderDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL); WarmUpOrders(tester, _orderCalculationDevice, _mersenneDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL);
} }
return tester; return tester;
@@ -303,10 +302,10 @@ private static ThreadLocal<object>? MersenneTesters;
_ => "cpu", _ => "cpu",
}; };
string orderDeviceLabel = orderDevice switch string orderDeviceLabel = _orderCalculationDevice switch
{ {
ComputationDevice.Hybrid => "hybrid", OrderDevice.Hybrid => "hybrid",
ComputationDevice.Gpu => "gpu", OrderDevice.Gpu => "gpu",
_ => "cpu", _ => "cpu",
}; };
@@ -543,7 +542,7 @@ private static ThreadLocal<object>? MersenneTesters;
if (!useLucas) if (!useLucas)
{ {
Console.WriteLine("Warming up orders..."); Console.WriteLine("Warming up orders...");
WarmUpOrders(MersenneTesters.Value!, orderDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL); WarmUpOrders(MersenneTesters.Value!, _orderCalculationDevice, _mersenneDevice, currentP, orderWarmupLimitOverride ?? 5_000_000UL);
} }
} }
@@ -653,299 +652,155 @@ private static ThreadLocal<object>? MersenneTesters;
private static bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent) private static bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent)
{ {
object tester = MersenneTesters!.Value!; object tester = MersenneTesters!.Value!;
return (_calculationMethod, _orderDevice) switch return (_calculationMethod, _orderCalculationDevice, _mersenneDevice) switch
{ {
(CalculationMethod.Residue, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, _) => ((MersenneNumberTesterForResidueCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Residue, OrderDevice.Gpu, _) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Residue, _, _) => ((MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.LucasLehmer, OrderDevice.Gpu, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.LucasLehmer, _, _) => ((MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, _) => ((MersenneNumberTesterForDivisorCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Divisor, OrderDevice.Gpu, _) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Divisor, _, _) => ((MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.ByDivisor, OrderDevice.Gpu, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.ByDivisor, _, _) => ((MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), (CalculationMethod.Pow2Mod, OrderDevice.Gpu, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(CalculationMethod.Pow2Mod, _, _) => ((MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(_, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForGpu)tester).IsMersennePrime(gpu, exponent), (_, OrderDevice.Gpu, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(_, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForHybrid)tester).IsMersennePrime(gpu, exponent), (_, OrderDevice.Gpu, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
_ => ((MersenneNumberTesterForIncrementalCalculationMethodForCpu)tester).IsMersennePrime(gpu, exponent), (_, OrderDevice.Gpu, _) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(_, OrderDevice.Hybrid, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(_, OrderDevice.Hybrid, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
(_, OrderDevice.Hybrid, _) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
(_, _, ComputationDevice.Gpu) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu)tester).IsMersennePrime(gpu, exponent),
(_, _, ComputationDevice.Hybrid) => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid)tester).IsMersennePrime(gpu, exponent),
_ => ((MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu)tester).IsMersennePrime(gpu, exponent),
}; };
} }
private static object CreateMersenneTester( private static object CreateMersenneTester(
CalculationMethod method, CalculationMethod method,
ComputationDevice device, CacheStatus cacheStatus,
OrderDevice orderDevice,
ComputationDevice mersenneDevice,
GpuKernelType kernelType, GpuKernelType kernelType,
bool useLucas,
bool useOrder,
bool mersenneOnGpu,
bool orderOnGpu,
bool orderOnHybrid,
ulong residueKMax) ulong residueKMax)
{ {
return (method, device) switch if (cacheStatus != CacheStatus.Disabled)
{ {
(CalculationMethod.Residue, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForGpu( throw new NotSupportedException("CacheStatus.Enabled is not wired into Program.cs yet.");
}
useOrderCache: false, return (method, orderDevice, mersenneDevice) switch
kernelType: kernelType, {
useOrder: useOrder, (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
useGpuLucas: mersenneOnGpu, (CalculationMethod.Residue, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useGpuScan: mersenneOnGpu, (CalculationMethod.Residue, OrderDevice.Gpu, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useGpuOrder: orderOnGpu || orderOnHybrid, (CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
maxK: residueKMax, (CalculationMethod.Residue, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
orderDevice: device), (CalculationMethod.Residue, OrderDevice.Hybrid, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.Residue, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForHybrid( (CalculationMethod.Residue, _, ComputationDevice.Gpu) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.Residue, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.Residue, _, _) => new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useOrderCache: false, (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
kernelType: kernelType, (CalculationMethod.LucasLehmer, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useOrder: useOrder, (CalculationMethod.LucasLehmer, OrderDevice.Gpu, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useGpuLucas: mersenneOnGpu, (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
useGpuScan: mersenneOnGpu, (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useGpuOrder: orderOnGpu || orderOnHybrid, (CalculationMethod.LucasLehmer, OrderDevice.Hybrid, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
maxK: residueKMax, (CalculationMethod.LucasLehmer, _, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
orderDevice: device), (CalculationMethod.LucasLehmer, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.Residue, _) => new MersenneNumberTesterForResidueCalculationMethodForCpu( (CalculationMethod.LucasLehmer, _, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useOrderCache: false, (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
kernelType: kernelType, (CalculationMethod.Divisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useOrder: useOrder, (CalculationMethod.Divisor, OrderDevice.Gpu, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useGpuLucas: mersenneOnGpu, (CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
useGpuScan: mersenneOnGpu, (CalculationMethod.Divisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useGpuOrder: orderOnGpu || orderOnHybrid, (CalculationMethod.Divisor, OrderDevice.Hybrid, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
maxK: residueKMax, (CalculationMethod.Divisor, _, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
orderDevice: device), (CalculationMethod.Divisor, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.Divisor, _, _) => new MersenneNumberTesterForDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.LucasLehmer, ComputationDevice.Gpu) => new MersenneNumberTesterForLucasLehmerCalculationMethodForGpu( (CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, OrderDevice.Gpu, _) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, OrderDevice.Hybrid, _) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, _, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.ByDivisor, _, _) => new MersenneNumberTesterForByDivisorCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useOrderCache: false, (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
kernelType: kernelType, (CalculationMethod.Pow2Mod, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useOrder: useOrder, (CalculationMethod.Pow2Mod, OrderDevice.Gpu, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useGpuLucas: mersenneOnGpu, (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
useGpuScan: mersenneOnGpu, (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useGpuOrder: orderOnGpu || orderOnHybrid, (CalculationMethod.Pow2Mod, OrderDevice.Hybrid, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
maxK: residueKMax, (CalculationMethod.Pow2Mod, _, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
orderDevice: device), (CalculationMethod.Pow2Mod, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.LucasLehmer, ComputationDevice.Hybrid) => new MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid( (CalculationMethod.Pow2Mod, _, _) => new MersenneNumberTesterForPow2ModCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useOrderCache: false, (_, OrderDevice.Gpu, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
kernelType: kernelType, (_, OrderDevice.Gpu, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useOrder: useOrder, (_, OrderDevice.Gpu, _) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForGpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useGpuLucas: mersenneOnGpu, (_, OrderDevice.Hybrid, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
useGpuScan: mersenneOnGpu, (_, OrderDevice.Hybrid, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
useGpuOrder: orderOnGpu || orderOnHybrid, (_, OrderDevice.Hybrid, _) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForHybridOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
maxK: residueKMax, (_, _, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForGpu(kernelType: kernelType, maxK: residueKMax),
orderDevice: device), (_, _, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForHybrid(kernelType: kernelType, maxK: residueKMax),
(CalculationMethod.LucasLehmer, _) => new MersenneNumberTesterForLucasLehmerCalculationMethodForCpu( _ => new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(kernelType: kernelType, maxK: residueKMax),
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.Divisor, ComputationDevice.Gpu) => new MersenneNumberTesterForDivisorCalculationMethodForGpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.Divisor, ComputationDevice.Hybrid) => new MersenneNumberTesterForDivisorCalculationMethodForHybrid(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.Divisor, _) => new MersenneNumberTesterForDivisorCalculationMethodForCpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.ByDivisor, ComputationDevice.Gpu) => new MersenneNumberTesterForByDivisorCalculationMethodForGpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.ByDivisor, ComputationDevice.Hybrid) => new MersenneNumberTesterForByDivisorCalculationMethodForHybrid(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.ByDivisor, _) => new MersenneNumberTesterForByDivisorCalculationMethodForCpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.Pow2Mod, ComputationDevice.Gpu) => new MersenneNumberTesterForPow2ModCalculationMethodForGpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.Pow2Mod, ComputationDevice.Hybrid) => new MersenneNumberTesterForPow2ModCalculationMethodForHybrid(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(CalculationMethod.Pow2Mod, _) => new MersenneNumberTesterForPow2ModCalculationMethodForCpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(_, ComputationDevice.Gpu) => new MersenneNumberTesterForIncrementalCalculationMethodForGpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
(_, ComputationDevice.Hybrid) => new MersenneNumberTesterForIncrementalCalculationMethodForHybrid(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
_ => new MersenneNumberTesterForIncrementalCalculationMethodForCpu(
useOrderCache: false,
kernelType: kernelType,
useOrder: useOrder,
useGpuLucas: mersenneOnGpu,
useGpuScan: mersenneOnGpu,
useGpuOrder: orderOnGpu || orderOnHybrid,
maxK: residueKMax,
orderDevice: device),
}; };
} }
private static void WarmUpOrders(object tester, ComputationDevice device, ulong exponent, ulong limit) private static void WarmUpOrders(object tester, OrderDevice orderDevice, ComputationDevice device, ulong exponent, ulong limit)
{ {
switch (_calculationMethod, device) if (_cacheStatus == CacheStatus.Disabled)
{ {
case (CalculationMethod.Residue, ComputationDevice.Gpu): return;
((MersenneNumberTesterForResidueCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Residue, ComputationDevice.Hybrid):
((MersenneNumberTesterForResidueCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Residue, _):
((MersenneNumberTesterForResidueCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.LucasLehmer, ComputationDevice.Gpu):
((MersenneNumberTesterForLucasLehmerCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.LucasLehmer, ComputationDevice.Hybrid):
((MersenneNumberTesterForLucasLehmerCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.LucasLehmer, _):
((MersenneNumberTesterForLucasLehmerCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Divisor, ComputationDevice.Gpu):
((MersenneNumberTesterForDivisorCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Divisor, ComputationDevice.Hybrid):
((MersenneNumberTesterForDivisorCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Divisor, _):
((MersenneNumberTesterForDivisorCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.ByDivisor, ComputationDevice.Gpu):
((MersenneNumberTesterForByDivisorCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.ByDivisor, ComputationDevice.Hybrid):
((MersenneNumberTesterForByDivisorCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.ByDivisor, _):
((MersenneNumberTesterForByDivisorCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Pow2Mod, ComputationDevice.Gpu):
((MersenneNumberTesterForPow2ModCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Pow2Mod, ComputationDevice.Hybrid):
((MersenneNumberTesterForPow2ModCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit);
break;
case (CalculationMethod.Pow2Mod, _):
((MersenneNumberTesterForPow2ModCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit);
break;
case (_, ComputationDevice.Gpu):
((MersenneNumberTesterForIncrementalCalculationMethodForGpu)tester).WarmUpOrders(exponent, limit);
break;
case (_, ComputationDevice.Hybrid):
((MersenneNumberTesterForIncrementalCalculationMethodForHybrid)tester).WarmUpOrders(exponent, limit);
break;
default:
((MersenneNumberTesterForIncrementalCalculationMethodForCpu)tester).WarmUpOrders(exponent, limit);
break;
} }
// When cache warming is enabled, add calls for the generated classes keyed by orderDevice and device.
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -13,7 +13,7 @@ public class MersenneNumberTesterTests
[InlineData(136_000_005UL)] [InlineData(136_000_005UL)]
public void IsMersennePrime_detects_small_prime_divisors_for_large_exponents(ulong p) public void IsMersennePrime_detects_small_prime_divisors_for_large_exponents(ulong p)
{ {
var tester = new MersenneNumberTesterForIncrementalCalculationMethodForCpu(); var tester = new MersenneNumberTesterForIncrementalCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu();
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
try try
{ {
@@ -29,7 +29,7 @@ public class MersenneNumberTesterTests
[InlineData(125UL)] [InlineData(125UL)]
public void WarmUpOrdersCpu_populates_cache_without_affecting_results(ulong p) public void WarmUpOrdersCpu_populates_cache_without_affecting_results(ulong p)
{ {
var tester = new MersenneNumberTesterForIncrementalCalculationMethodForCpu(useOrderCache: true, useGpuOrder: true); var tester = new MersenneNumberTesterForIncrementalCalculationMethodForEnabledCacheStatusForGpuOrderDeviceForCpu();
tester.WarmUpOrders(p, 1_000UL); tester.WarmUpOrders(p, 1_000UL);
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
try try
@@ -46,7 +46,7 @@ public class MersenneNumberTesterTests
[InlineData(125UL)] [InlineData(125UL)]
public void WarmUpOrdersGpu_populates_cache_without_affecting_results(ulong p) public void WarmUpOrdersGpu_populates_cache_without_affecting_results(ulong p)
{ {
var tester = new MersenneNumberTesterForIncrementalCalculationMethodForGpu(useOrderCache: true, useGpuOrder: true); var tester = new MersenneNumberTesterForIncrementalCalculationMethodForEnabledCacheStatusForGpuOrderDeviceForGpu();
tester.WarmUpOrders(p, 1_000UL); tester.WarmUpOrders(p, 1_000UL);
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
try try
@@ -10,10 +10,7 @@ public class MersenneResidueModeTests
[Fact] [Fact]
public void IsMersennePrime_residue_mode_rejects_composite_exponent() public void IsMersennePrime_residue_mode_rejects_composite_exponent()
{ {
var tester = new MersenneNumberTesterForResidueCalculationMethodForCpu( var tester = new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu();
useGpuScan: false,
useGpuOrder: false);
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
try try
{ {
@@ -28,10 +25,7 @@ public class MersenneResidueModeTests
[Fact] [Fact]
public void IsMersennePrime_residue_mode_accepts_prime_exponent() public void IsMersennePrime_residue_mode_accepts_prime_exponent()
{ {
var tester = new MersenneNumberTesterForResidueCalculationMethodForCpu( var tester = new MersenneNumberTesterForResidueCalculationMethodForDisabledCacheStatusForCpuOrderDeviceForCpu(
useGpuScan: false,
useGpuOrder: false,
maxK: 1_000UL); maxK: 1_000UL);
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
try try
@@ -1,3 +1,4 @@
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Buffers; using System.Buffers;
@@ -26,32 +27,49 @@ public enum CalculationMethod
Residue, Residue,
} }
public enum CacheStatus
{
Disabled,
Enabled,
}
public enum OrderDevice
{
Cpu,
Hybrid,
Gpu,
}
[EnumDependentTemplate(typeof(CalculationMethod))] [EnumDependentTemplate(typeof(CalculationMethod))]
[EnumDependentTemplate(typeof(CacheStatus))]
[EnumDependentTemplate(typeof(OrderDevice))]
[DeviceDependentTemplate(typeof(ComputationDevice))] [DeviceDependentTemplate(typeof(ComputationDevice))]
public sealed class MersenneNumberTesterTemplate( public sealed class MersenneNumberTesterTemplate(
bool useOrderCache = false,
GpuKernelType kernelType = GpuKernelType.Incremental, GpuKernelType kernelType = GpuKernelType.Incremental,
bool useOrder = false, ulong maxK = 5_000_000UL)
bool useGpuLucas = true,
bool useGpuScan = true,
bool useGpuOrder = true,
ulong maxK = 5_000_000UL,
ComputationDevice orderDevice = ComputationDevice.Gpu)
{ {
#if CacheStatus_Enabled
private static readonly ConcurrentDictionary<UInt128, ulong> _orderCache = []; private static readonly ConcurrentDictionary<UInt128, ulong> _orderCache = [];
// TODO: Swap this ConcurrentDictionary for the pooled dictionary variant highlighted in #endif
// Pow2MontgomeryModBenchmarks once order warmups reuse deterministic divisor-cycle snapshots; the pooled approach removed
// the locking overhead when scanning p >= 138M in those benchmarks.
#if CalculationMethod_Residue #if CalculationMethod_Residue
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
private readonly MersenneNumberResidueGpuTester _residueTester = new(useGpuOrder); #if OrderDevice_Gpu || OrderDevice_Hybrid
private readonly MersenneNumberResidueGpuTester _residueTester = new(true);
#else
private readonly MersenneNumberResidueGpuTester _residueTester = new(false);
#endif
#else #else
private readonly MersenneNumberResidueCpuTester _residueTester = new(); private readonly MersenneNumberResidueCpuTester _residueTester = new();
#endif #endif
private readonly ulong _maxK = maxK; private readonly ulong _maxK = maxK;
#elif CalculationMethod_LucasLehmer #elif CalculationMethod_LucasLehmer
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, useGpuOrder); #if OrderDevice_Cpu
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
#else
private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, true);
#endif
private readonly MersenneNumberLucasLehmerGpuTester _lucasLehmerTester = new(); private readonly MersenneNumberLucasLehmerGpuTester _lucasLehmerTester = new();
#else #else
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType); private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
@@ -59,13 +77,21 @@ public sealed class MersenneNumberTesterTemplate(
#endif #endif
#elif CalculationMethod_Divisor || CalculationMethod_ByDivisor #elif CalculationMethod_Divisor || CalculationMethod_ByDivisor
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
private readonly MersenneNumberOrderGpuTester _orderTester = new(kernelType, useGpuOrder); #if OrderDevice_Cpu
private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType);
#else
private readonly MersenneNumberOrderGpuTester _orderTester = new(kernelType, true);
#endif
#else #else
private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType); private readonly MersenneNumberOrderCpuTester _orderTester = new(kernelType);
#endif #endif
#else #else
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, useGpuOrder); #if OrderDevice_Cpu
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
#else
private readonly MersenneNumberIncrementalGpuTester _incrementalTester = new(kernelType, true);
#endif
#else #else
private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType); private readonly MersenneNumberIncrementalCpuTester _incrementalTester = new(kernelType);
#endif #endif
@@ -75,23 +101,17 @@ public sealed class MersenneNumberTesterTemplate(
public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL) public void WarmUpOrders(ulong exponent, ulong limit = 5_000_000UL)
{ {
if (!useOrderCache) #if !CacheStatus_Enabled
{
return; return;
} #else
UInt128 k, q;
UInt128 twoP = (UInt128)exponent << 1; // 2 * p UInt128 twoP = (UInt128)exponent << 1; // 2 * p
bool lastIsSeven = (exponent & 3UL) == 3UL; bool lastIsSeven = (exponent & 3UL) == 3UL;
#if DEVICE_GPU || DEVICE_HYBRID
var gpu = PrimeOrderCalculatorAccelerator.Rent(1); #if OrderDevice_Cpu
#endif UInt128 k = UInt128.One;
if (!useGpuOrder)
{
k = UInt128.One;
for (; k <= limit; k++) for (; k <= limit; k++)
{ {
q = twoP * k + UInt128.One; UInt128 q = twoP * k + UInt128.One;
ulong remainder = q.Mod10(); ulong remainder = q.Mod10();
bool shouldCheck = lastIsSeven bool shouldCheck = lastIsSeven
? remainder == 7UL || remainder == 9UL || remainder == 3UL ? remainder == 7UL || remainder == 9UL || remainder == 3UL
@@ -116,59 +136,48 @@ public sealed class MersenneNumberTesterTemplate(
continue; continue;
} }
_orderCache[q] = _orderCache[q] = q.CalculateOrderCpu();
#if DEVICE_GPU
q.CalculateOrderGpu(gpu);
#elif DEVICE_HYBRID
q.CalculateOrderHybrid(gpu);
#else
q.CalculateOrderCpu();
#endif
} }
#if DEVICE_GPU || DEVICE_HYBRID
PrimeOrderCalculatorAccelerator.Return(gpu);
#endif
return; return;
} #else
#if DEVICE_GPU || DEVICE_HYBRID
var gpu = PrimeOrderCalculatorAccelerator.Rent(1);
ArrayPool<UInt128> uInt128Pool = ThreadStaticPools.UInt128Pool; ArrayPool<UInt128> uInt128Pool = ThreadStaticPools.UInt128Pool;
UInt128[] qsBuffer = uInt128Pool.Rent((int)limit); UInt128[] qsBuffer = uInt128Pool.Rent((int)limit);
int idx = 0; int idx = 0;
k = UInt128.One; UInt128 k2 = 1UL;
for (; k <= limit; k++) for (; k2 <= limit; k2++)
{ {
q = twoP * k + UInt128.One; UInt128 q2 = twoP * k2 + 1UL;
ulong remainder2 = q.Mod10(); ulong remainder2 = q2.Mod10();
bool shouldCheck2 = lastIsSeven bool shouldCheck2 = lastIsSeven
? remainder2 == 7UL || remainder2 == 9UL || remainder2 == 3UL ? remainder2 == 7UL || remainder2 == 9UL || remainder2 == 3UL
: remainder2 == 1UL || remainder2 == 3UL || remainder2 == 9UL; : remainder2 == 1UL || remainder2 == 3UL || remainder2 == 9UL;
if (shouldCheck2) if (shouldCheck2)
{ {
ulong mod8 = q.Mod8(); ulong mod8 = q2.Mod8();
if (mod8 != 1UL && mod8 != 7UL) if (mod8 != 1UL && mod8 != 7UL)
{ {
shouldCheck2 = false; shouldCheck2 = false;
} }
else if (q.Mod3() == 0UL || q.Mod5() == 0UL) else if (q2.Mod3() == 0UL || q2.Mod5() == 0UL)
{ {
shouldCheck2 = false; shouldCheck2 = false;
} }
} }
if (!shouldCheck2 || _orderCache.ContainsKey(q)) if (!shouldCheck2 || _orderCache.ContainsKey(q2))
{ {
continue; continue;
} }
qsBuffer[idx++] = q; qsBuffer[idx++] = q2;
} }
if (idx == 0) if (idx == 0)
{ {
#if DEVICE_GPU || DEVICE_HYBRID
PrimeOrderCalculatorAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
#endif
ThreadStaticPools.UInt128Pool.Return(qsBuffer); ThreadStaticPools.UInt128Pool.Return(qsBuffer);
return; return;
} }
@@ -210,21 +219,11 @@ public sealed class MersenneNumberTesterTemplate(
ulong order = orders[i]; ulong order = orders[i];
if (order == 0UL) if (order == 0UL)
{ {
order = order = qs[offset + i].CalculateOrderGpu(gpu);
#if DEVICE_GPU
qs[offset + i].CalculateOrderGpu(gpu);
#elif DEVICE_HYBRID
qs[offset + i].CalculateOrderHybrid(gpu);
#else
qs[offset + i].CalculateOrderCpu();
#endif
} }
if (useOrderCache)
{
_orderCache[qs[offset + i]] = order; _orderCache[qs[offset + i]] = order;
} }
}
offset += count; offset += count;
orderBuffer.Dispose(); orderBuffer.Dispose();
@@ -232,10 +231,42 @@ public sealed class MersenneNumberTesterTemplate(
} }
AcceleratorStreamPool.Return(acceleratorIndex,stream); AcceleratorStreamPool.Return(acceleratorIndex,stream);
#if DEVICE_GPU || DEVICE_HYBRID
PrimeOrderCalculatorAccelerator.Return(gpu); PrimeOrderCalculatorAccelerator.Return(gpu);
#endif
uInt128Pool.Return(qs); uInt128Pool.Return(qs);
#else
UInt128 kFallback = UInt128.One;
for (; kFallback <= limit; kFallback++)
{
UInt128 qFallback = twoP * kFallback + UInt128.One;
ulong remainderFallback = qFallback.Mod10();
bool shouldCheckFallback = lastIsSeven
? remainderFallback == 7UL || remainderFallback == 9UL || remainderFallback == 3UL
: remainderFallback == 1UL || remainderFallback == 3UL || remainderFallback == 9UL;
if (shouldCheckFallback)
{
ulong mod8Fallback = qFallback.Mod8();
if (mod8Fallback != 1UL && mod8Fallback != 7UL)
{
continue;
}
if (qFallback.Mod3() == 0UL || qFallback.Mod5() == 0UL)
{
continue;
}
}
if (!shouldCheckFallback || _orderCache.ContainsKey(qFallback))
{
continue;
}
_orderCache[qFallback] = qFallback.CalculateOrderCpu();
}
#endif
#endif
#endif
} }
public bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent) public bool IsMersennePrime(PrimeOrderCalculatorAccelerator gpu, ulong exponent)
@@ -272,6 +303,10 @@ public sealed class MersenneNumberTesterTemplate(
return false; return false;
} }
#if CalculationMethod_Divisor || CalculationMethod_ByDivisor
// When using order/divisor scanning the theoretical maxK is huge; cache or GPU selection already fixed at compile time.
#endif
UInt128 twoP = (UInt128)exponent << 1; // 2 * p UInt128 twoP = (UInt128)exponent << 1; // 2 * p
UInt128 maxK = UInt128Numbers.Two.Pow(exponent) / 2 + 1; UInt128 maxK = UInt128Numbers.Two.Pow(exponent) / 2 + 1;
LastDigit lastDigit = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One; LastDigit lastDigit = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One;
@@ -296,7 +331,11 @@ public sealed class MersenneNumberTesterTemplate(
UInt128 maxKPre = (UInt128)PreLucasPreScanK; UInt128 maxKPre = (UInt128)PreLucasPreScanK;
LastDigit lastDigitPre = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One; LastDigit lastDigitPre = (exponent & 3UL) == 3UL ? LastDigit.Seven : LastDigit.One;
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
#if OrderDevice_Cpu
_incrementalTester.Scan(gpu, exponent, twoPPre, lastDigitPre, maxKPre, ref prePrime);
#else
_incrementalTester.Scan(exponent, twoPPre, lastDigitPre, maxKPre, ref prePrime); _incrementalTester.Scan(exponent, twoPPre, lastDigitPre, maxKPre, ref prePrime);
#endif
if (!prePrime) if (!prePrime)
{ {
return false; return false;
@@ -315,7 +354,11 @@ public sealed class MersenneNumberTesterTemplate(
#elif CalculationMethod_Divisor || CalculationMethod_ByDivisor #elif CalculationMethod_Divisor || CalculationMethod_ByDivisor
bool isPrime = true; bool isPrime = true;
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
#if OrderDevice_Cpu
_orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
#else
_orderTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime); _orderTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime);
#endif
#else #else
_orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime); _orderTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
#endif #endif
@@ -323,7 +366,11 @@ public sealed class MersenneNumberTesterTemplate(
#else #else
bool isPrime = true; bool isPrime = true;
#if DEVICE_GPU || DEVICE_HYBRID #if DEVICE_GPU || DEVICE_HYBRID
#if OrderDevice_Cpu
_incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
#else
_incrementalTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime); _incrementalTester.Scan(exponent, twoP, lastDigit, maxK, ref isPrime);
#endif
#else #else
_incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime); _incrementalTester.Scan(gpu, exponent, twoP, lastDigit, maxK, ref isPrime);
#endif #endif