DivisorSet scans added as EnumDependentTemplate to MersenneNumberDivisorByDivisorCpuTesterWithTemplate. New Pow2Groups scan implemented based on statistics for high divisors. MersenneNumberDivisorByDivisorPrimeScan sessions integrated into MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate. Various micro optimizations to eliminate variable, unnecessary struct creations and continue scans in higher divisor ranges, when lower ranges are exhausted. --bydivisor-k-increment command-line argument added.

This commit is contained in:
mlemanczyk committed 2025-12-28 00:45:08 +01:00
1 parent 759614de54
commit 87a66e4eca
13 files changed
+2407 -364

No files matched your search

@@ -2,6 +2,7 @@ using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs; using BenchmarkDotNet.Jobs;
using Open.Numeric.Primes; using Open.Numeric.Primes;
using PerfectNumbers.Core; using PerfectNumbers.Core;
using PerfectNumbers.Core.Gpu;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
namespace EvenPerfectBitScanner.Benchmarks; namespace EvenPerfectBitScanner.Benchmarks;
@@ -18,6 +19,8 @@ public class PrimeTesterBenchmarks
[GlobalSetup] [GlobalSetup]
public void GlobalSetup() public void GlobalSetup()
{ {
EnvironmentConfiguration.RollingAccelerators = 1;
_candidates = BenchmarkCase.Candidates; _candidates = BenchmarkCase.Candidates;
if (_candidates.Length == 0) if (_candidates.Length == 0)
@@ -25,7 +28,6 @@ public class PrimeTesterBenchmarks
return; return;
} }
EnvironmentConfiguration.RollingAccelerators = 1;
PrimeOrderCalculatorAccelerator.WarmUp(); PrimeOrderCalculatorAccelerator.WarmUp();
// HeuristicGroupABPrimeTesterAccelerator.WarmUp(); // HeuristicGroupABPrimeTesterAccelerator.WarmUp();
+48 -1
View File
@@ -25,6 +25,8 @@ internal readonly struct CliArguments
internal readonly bool UseResidue; internal readonly bool UseResidue;
internal readonly bool UseDivisor; internal readonly bool UseDivisor;
internal readonly bool UseByDivisor; internal readonly bool UseByDivisor;
internal readonly bool UseDivisorPow2Increment;
internal readonly int ByDivisorSpecialRange;
internal readonly bool UseGcdFilter; internal readonly bool UseGcdFilter;
internal readonly bool TestMode; internal readonly bool TestMode;
internal readonly bool UseGpuCycles; internal readonly bool UseGpuCycles;
@@ -72,6 +74,8 @@ internal readonly struct CliArguments
bool useDivisor, bool useDivisor,
bool useByDivisor, bool useByDivisor,
bool useGcdFilter, bool useGcdFilter,
bool useDivisorPow2Increment,
int byDivisorSpecialRange,
bool testMode, bool testMode,
bool useGpuCycles, bool useGpuCycles,
ComputationDevice mersenneDevice, ComputationDevice mersenneDevice,
@@ -116,6 +120,8 @@ internal readonly struct CliArguments
UseResidue = useResidue; UseResidue = useResidue;
UseDivisor = useDivisor; UseDivisor = useDivisor;
UseByDivisor = useByDivisor; UseByDivisor = useByDivisor;
UseDivisorPow2Increment = useDivisorPow2Increment;
ByDivisorSpecialRange = byDivisorSpecialRange;
UseGcdFilter = useGcdFilter; UseGcdFilter = useGcdFilter;
TestMode = testMode; TestMode = testMode;
UseGpuCycles = useGpuCycles; UseGpuCycles = useGpuCycles;
@@ -166,6 +172,8 @@ internal readonly struct CliArguments
bool useResidue = false; bool useResidue = false;
bool useDivisor = false; bool useDivisor = false;
bool useByDivisor = false; bool useByDivisor = false;
bool useDivisorPow2Increment = false;
int byDivisorSpecialRange = 0;
bool useGcdFilter = false; bool useGcdFilter = false;
bool testMode = false; bool testMode = false;
bool useGpuCycles = true; bool useGpuCycles = true;
@@ -293,6 +301,41 @@ internal readonly struct CliArguments
continue; continue;
} }
if (argument.StartsWith("--bydivisor-k-increment=", StringComparison.OrdinalIgnoreCase))
{
string value = argument["--bydivisor-k-increment=".Length..].Trim();
if (value.Equals("pow2groups", StringComparison.OrdinalIgnoreCase))
{
useDivisorPow2Increment = true;
}
else if (value.Equals("sequential", StringComparison.OrdinalIgnoreCase))
{
useDivisorPow2Increment = false;
}
else
{
Console.WriteLine("Invalid value for --bydivisor-k-increment. Use onebyone or pow2groups.");
return default;
}
continue;
}
if (argument.StartsWith("--bydivisor-special-range=", StringComparison.OrdinalIgnoreCase))
{
if (Utf8CliParser.TryParseInt32(argument.AsSpan("--bydivisor-special-range=".Length), out int parsedRange) && parsedRange >= 0)
{
byDivisorSpecialRange = parsedRange;
}
else
{
Console.WriteLine("Invalid value for --bydivisor-special-range. Use a non-negative integer.");
return default;
}
continue;
}
if (argument.StartsWith("--divisor-cycles-limit=", StringComparison.OrdinalIgnoreCase)) if (argument.StartsWith("--divisor-cycles-limit=", StringComparison.OrdinalIgnoreCase))
{ {
if (Utf8CliParser.TryParseUInt64(argument.AsSpan("--divisor-cycles-limit=".Length), out ulong parsedLimit)) if (Utf8CliParser.TryParseUInt64(argument.AsSpan("--divisor-cycles-limit=".Length), out ulong parsedLimit))
@@ -593,6 +636,8 @@ internal readonly struct CliArguments
useDivisor, useDivisor,
useByDivisor, useByDivisor,
useGcdFilter, useGcdFilter,
useDivisorPow2Increment,
byDivisorSpecialRange,
testMode, testMode,
useGpuCycles, useGpuCycles,
mersenneDevice, mersenneDevice,
@@ -632,7 +677,9 @@ internal readonly struct CliArguments
Console.WriteLine(" --max-prime=<value> inclusive upper bound for primes from filter files"); Console.WriteLine(" --max-prime=<value> inclusive upper bound for primes from filter files");
Console.WriteLine(" --increment=bit|add exponent increment method (default add)"); Console.WriteLine(" --increment=bit|add exponent increment method (default add)");
Console.WriteLine(" --threads=<value> number of worker threads"); Console.WriteLine(" --threads=<value> number of worker threads");
Console.WriteLine(" --mersenne=pow2mod|incremental|lucas|residue|divisor|bydivisor Mersenne test method"); S Console.WriteLine(" --mersenne=pow2mod|incremental|lucas|residue|divisor|bydivisor Mersenne test method");
Console.WriteLine(" --bydivisor-k-increment=sequential|pow2groups k iteration strategy for --mersenne=bydivisor (default sequential)");
Console.WriteLine(" --bydivisor-special-range=<n> widen pow2groups special values to +/- n percent (default 0 = points)");
Console.WriteLine(" --residue-max-k=<value> max k for residue Mersenne test (q = 2*p*k + 1)"); Console.WriteLine(" --residue-max-k=<value> max k for residue Mersenne test (q = 2*p*k + 1)");
Console.WriteLine(" --mersenne-device=cpu|gpu|hybrid Device for Mersenne method (default gpu)"); Console.WriteLine(" --mersenne-device=cpu|gpu|hybrid Device for Mersenne method (default gpu)");
Console.WriteLine(" --primes-device=cpu|gpu device for prime-scan kernels (default gpu)"); Console.WriteLine(" --primes-device=cpu|gpu device for prime-scan kernels (default gpu)");
+96 -3
View File
@@ -8,6 +8,13 @@ using PerfectNumbers.Core;
using PerfectNumbers.Core.Cpu; using PerfectNumbers.Core.Cpu;
using PerfectNumbers.Core.Gpu; using PerfectNumbers.Core.Gpu;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
using MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
using MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForHybridOrder;
using MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForGpuOrder;
using ByDivisorCpuOrderPow2 = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder;
using ByDivisorHybridOrderPow2 = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder;
using ByDivisorGpuOrderPow2 = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder;
using System.Globalization;
namespace EvenPerfectBitScanner; namespace EvenPerfectBitScanner;
@@ -21,6 +28,9 @@ private static ThreadLocal<object>? MersenneTesters;
private static MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder _byDivisorCpuOrderTester; private static MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder _byDivisorCpuOrderTester;
private static MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder _byDivisorHybridOrderTester; private static MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder _byDivisorHybridOrderTester;
private static MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder _byDivisorGpuOrderTester; private static MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder _byDivisorGpuOrderTester;
private static ByDivisorCpuOrderPow2 _byDivisorCpuOrderTesterPow2;
private static ByDivisorHybridOrderPow2 _byDivisorHybridOrderTesterPow2;
private static ByDivisorGpuOrderPow2 _byDivisorGpuOrderTesterPow2;
private static Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? _byDivisorPreviousResults; private static Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? _byDivisorPreviousResults;
private static bool _limitReached; private static bool _limitReached;
private static ulong _byDivisorStartPrime; private static ulong _byDivisorStartPrime;
@@ -64,6 +74,8 @@ private static ThreadLocal<object>? MersenneTesters;
EnvironmentConfiguration.GpuBatchSize = Math.Max(1, _cliArguments.ScanBatchSize); EnvironmentConfiguration.GpuBatchSize = Math.Max(1, _cliArguments.ScanBatchSize);
EnvironmentConfiguration.GpuRatio = _cliArguments.GpuRatio; EnvironmentConfiguration.GpuRatio = _cliArguments.GpuRatio;
EnvironmentConfiguration.OrderDevice = _cliArguments.OrderDevice; EnvironmentConfiguration.OrderDevice = _cliArguments.OrderDevice;
EnvironmentConfiguration.UsePow2GroupDivisors = _cliArguments.UseDivisorPow2Increment;
EnvironmentConfiguration.ByDivisorSpecialRange = _cliArguments.ByDivisorSpecialRange;
EnvironmentConfiguration.RollingAccelerators = Math.Min(Math.Min(PerfectNumberConstants.RollingAccelerators, gpuPrimeThreads), threadCount); EnvironmentConfiguration.RollingAccelerators = Math.Min(Math.Min(PerfectNumberConstants.RollingAccelerators, gpuPrimeThreads), threadCount);
EnvironmentConfiguration.Initialize(); EnvironmentConfiguration.Initialize();
@@ -257,19 +269,41 @@ private static ThreadLocal<object>? MersenneTesters;
throw new NotSupportedException("--mersenne-device=gpu is not supported for --mersenne=bydivisor on this execution path."); throw new NotSupportedException("--mersenne-device=gpu is not supported for --mersenne=bydivisor on this execution path.");
} }
bool usePow2Divisors = _cliArguments.UseDivisorPow2Increment;
if (EnvironmentConfiguration.UseCpuOrder) if (EnvironmentConfiguration.UseCpuOrder)
{
if (usePow2Divisors)
{
_byDivisorCpuOrderTesterPow2 = new ByDivisorCpuOrderPow2();
}
else
{ {
_byDivisorCpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder(); _byDivisorCpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder();
} }
}
else if (EnvironmentConfiguration.UseHybridOrder) else if (EnvironmentConfiguration.UseHybridOrder)
{
if (usePow2Divisors)
{
_byDivisorHybridOrderTesterPow2 = new ByDivisorHybridOrderPow2();
}
else
{ {
_byDivisorHybridOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder(); _byDivisorHybridOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder();
} }
}
else
{
if (usePow2Divisors)
{
_byDivisorGpuOrderTesterPow2 = new ByDivisorGpuOrderPow2();
}
else else
{ {
_byDivisorGpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder(); _byDivisorGpuOrderTester = new MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder();
} }
} }
}
// Load RLE blacklist (optional) // Load RLE blacklist (optional)
if (!string.IsNullOrEmpty(_cliArguments.RleBlacklistPath)) if (!string.IsNullOrEmpty(_cliArguments.RleBlacklistPath))
@@ -483,7 +517,24 @@ private static ThreadLocal<object>? MersenneTesters;
if (useByDivisor) if (useByDivisor)
{ {
int byDivisorPrimeRange = Math.Max(1, _cliArguments.BlockSize); int byDivisorPrimeRange = Math.Max(1, _cliArguments.BlockSize);
bool usePow2Divisors = _cliArguments.UseDivisorPow2Increment;
if (EnvironmentConfiguration.UseCpuOrder) if (EnvironmentConfiguration.UseCpuOrder)
{
if (usePow2Divisors)
{
Console.WriteLine("Using by-divisor pow2groups increment (CPU order).");
MersenneNumberDivisorByDivisorTester.Run(
byDivisorCandidates,
ref _byDivisorCpuOrderTesterPow2,
_byDivisorPreviousResults,
_byDivisorStartPrime,
static () => _lastCompositeP = true,
static () => _lastCompositeP = false,
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
threadCount,
byDivisorPrimeRange);
}
else
{ {
MersenneNumberDivisorByDivisorTester.Run( MersenneNumberDivisorByDivisorTester.Run(
byDivisorCandidates, byDivisorCandidates,
@@ -496,7 +547,24 @@ private static ThreadLocal<object>? MersenneTesters;
threadCount, threadCount,
byDivisorPrimeRange); byDivisorPrimeRange);
} }
}
else if (EnvironmentConfiguration.UseHybridOrder) else if (EnvironmentConfiguration.UseHybridOrder)
{
if (usePow2Divisors)
{
Console.WriteLine("Using by-divisor pow2groups increment (Hybrid order).");
MersenneNumberDivisorByDivisorTester.Run(
byDivisorCandidates,
ref _byDivisorHybridOrderTesterPow2,
_byDivisorPreviousResults,
_byDivisorStartPrime,
static () => _lastCompositeP = true,
static () => _lastCompositeP = false,
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
threadCount,
byDivisorPrimeRange);
}
else
{ {
MersenneNumberDivisorByDivisorTester.Run( MersenneNumberDivisorByDivisorTester.Run(
byDivisorCandidates, byDivisorCandidates,
@@ -509,6 +577,23 @@ private static ThreadLocal<object>? MersenneTesters;
threadCount, threadCount,
byDivisorPrimeRange); byDivisorPrimeRange);
} }
}
else
{
if (usePow2Divisors)
{
Console.WriteLine("Using by-divisor pow2groups increment (GPU order).");
MersenneNumberDivisorByDivisorTester.Run(
byDivisorCandidates,
ref _byDivisorGpuOrderTesterPow2,
_byDivisorPreviousResults,
_byDivisorStartPrime,
static () => _lastCompositeP = true,
static () => _lastCompositeP = false,
static (candidate, searchedMersenne, detailedCheck, passedAllTests, divisor) => CalculationResultHandler.HandleResult(candidate, divisor, searchedMersenne, detailedCheck, passedAllTests, _lastCompositeP),
threadCount,
byDivisorPrimeRange);
}
else else
{ {
MersenneNumberDivisorByDivisorTester.Run( MersenneNumberDivisorByDivisorTester.Run(
@@ -522,6 +607,7 @@ private static ThreadLocal<object>? MersenneTesters;
threadCount, threadCount,
byDivisorPrimeRange); byDivisorPrimeRange);
} }
}
CalculationResultHandler.FlushBuffer(); CalculationResultHandler.FlushBuffer();
CalculationResultHandler.ReleaseOutputBuffer(); CalculationResultHandler.ReleaseOutputBuffer();
@@ -907,17 +993,24 @@ private static ThreadLocal<object>? MersenneTesters;
if (_cliArguments.UseByDivisor) if (_cliArguments.UseByDivisor)
{ {
// Windowed pow2mod kernel handles by-divisor scans. // Windowed pow2mod kernel handles by-divisor scans.
bool usePow2Divisors = _cliArguments.UseDivisorPow2Increment;
if (EnvironmentConfiguration.UseCpuOrder) if (EnvironmentConfiguration.UseCpuOrder)
{ {
return _byDivisorCpuOrderTester.IsPrime(p, out detailedCheck, out _); return usePow2Divisors
? _byDivisorCpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _)
: _byDivisorCpuOrderTester.IsPrime(p, out detailedCheck, out _);
} }
if (EnvironmentConfiguration.UseHybridOrder) if (EnvironmentConfiguration.UseHybridOrder)
{ {
return _byDivisorHybridOrderTester.IsPrime(p, out detailedCheck, out _); return usePow2Divisors
? _byDivisorHybridOrderTesterPow2.IsPrime(p, out detailedCheck, out _)
: _byDivisorHybridOrderTester.IsPrime(p, out detailedCheck, out _);
} }
return _byDivisorGpuOrderTester.IsPrime(p, out detailedCheck, out _); return usePow2Divisors
? _byDivisorGpuOrderTesterPow2.IsPrime(p, out detailedCheck, out _)
: _byDivisorGpuOrderTester.IsPrime(p, out detailedCheck, out _);
} }
detailedCheck = IsMersennePrime(gpu, p); detailedCheck = IsMersennePrime(gpu, p);
@@ -1,6 +1,7 @@
using System.Numerics; using System.Numerics;
using FluentAssertions; using FluentAssertions;
using PerfectNumbers.Core.Cpu; using PerfectNumbers.Core.Cpu;
using MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
using Xunit; using Xunit;
namespace PerfectNumbers.Core.Tests; namespace PerfectNumbers.Core.Tests;
@@ -8,27 +8,38 @@ namespace PerfectNumbers.Core;
/// Mirrors <see cref="CycleRemainderStepper"/> for values that exceed 64 bits. /// Mirrors <see cref="CycleRemainderStepper"/> for values that exceed 64 bits.
/// </summary> /// </summary>
[method: MethodImpl(MethodImplOptions.AggressiveInlining)] [method: MethodImpl(MethodImplOptions.AggressiveInlining)]
public struct BigIntegerCycleRemainderStepper(BigInteger cycleLength) public struct BigIntegerCycleRemainderStepper(byte cycleLength)
{ {
private readonly BigInteger _cycleLength = cycleLength; private readonly BigInteger _cycleLength = (BigInteger)cycleLength;
private BigInteger _previousValue = BigInteger.Zero; private BigInteger _previousValue = BigInteger.Zero;
private BigInteger _currentRemainder = BigInteger.Zero; private BigInteger _currentRemainder = 0;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public BigInteger Initialize(BigInteger value) public byte Initialize(BigInteger value)
{ {
_previousValue = value; _previousValue = value;
_currentRemainder = value.ReduceCycleRemainder(_cycleLength); _currentRemainder = value % _cycleLength;
return _currentRemainder; return (byte)_currentRemainder;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public BigInteger ComputeNext(BigInteger value) public bool NextIsNotDivisible(BigInteger value)
{ {
BigInteger delta = value - _previousValue; BigInteger delta = value - _previousValue;
_previousValue = value; _previousValue = value;
_currentRemainder = (_currentRemainder + delta).ReduceCycleRemainder(_cycleLength); delta = (_currentRemainder + delta) % _cycleLength;
_currentRemainder = delta;
return !delta.IsZero;
}
return _currentRemainder; [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public byte ComputeNext(BigInteger value)
{
BigInteger delta = value - _previousValue;
_previousValue = value;
delta = (_currentRemainder + delta) % _cycleLength;
_currentRemainder = delta;
return (byte)delta;
} }
} }
@@ -0,0 +1,185 @@
#define DIVISOR_SPECIALIZED
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PerfectNumbers.Core.Cpu;
public static class DivisorByDivisorConfig
{
#if DIVISOR_SPECIALIZED
public const int PercentScale = 10_000;
public static readonly (int Start, int End)[] PercentGroupsPromille =
[
(9998, 10000),
(9844, 9845),
(9561, 9562),
(9402, 9403),
(9307, 9308),
(9127, 9128),
(8900, 8901),
(8682, 8683),
(8546, 8547),
(8381, 8382),
(7988, 7989),
(7693, 7694),
(7426, 7427),
(7184, 7185),
(6705, 6706),
(6473, 6474),
(6218, 6219),
(5944, 5945),
(5791, 5792),
(5530, 5531),
(4902, 4903),
(4657, 4658),
(4388, 4389),
(4119, 4120),
(3844, 3845),
(3602, 3603),
(3477, 3478),
(3112, 3113),
(2901, 2902),
(2742, 2743),
(2358, 2359),
(2134, 2135),
(1827, 1828),
(1611, 1612),
(1439, 1440),
(1354, 1355),
(1281, 1284),
(0906, 0907),
(0847, 0848),
(0706, 0707),
(0694, 0695),
(0569, 0570),
(0244, 0245),
(0204, 0205),
(0143, 0144),
(0095, 0096),
(0070, 0071),
];
public static readonly int[] SpecialPercentPromille = [
0070,
0143,
0095,
0204,
0244,
0569,
0694,
0706,
0847,
0906,
0955,
0958,
1060,
1018,
1132,
1308,
1416,
1782,
1875,
2026,
2349,
2451,
2464,
2782,
3065,
3088,
3113,
3257,
3284,
3304,
3318,
3343,
3351,
3383,
3431,
3566,
3617,
3938,
3985,
3994,
4053,
4166,
4248,
4337,
4344,
4467,
4493,
4866,
5043,
5189,
5208,
5510,
5530,
5925,
6198,
6281,
6324,
6363,
6366,
6387,
6474,
6477,
6546,
6548,
6729,
6741,
6841,
7203,
7211,
7234,
7589,
7593,
7664,
7775,
8076,
8203,
8273,
8331,
8381,
8546,
8682,
8900,
9127,
9307,
9402,
9561,
9844,
9998,
1000,
];
#elif DIVISOR_SPECIALIZED_LOW_DIVISORS
public const int PercentScale = 10_000;
public static readonly (int Start, int End)[] PercentGroupsPromille =
[
(4500, 5500),
(7000, 8000),
(9500, 9800),
(9800, 10000),
(3000, 4500),
(0, 1000),
];
public static readonly int[] SpecialPercentPromille = [9840, 10000, 7500, 5000, 3910, 0292, 0297, 0325, 0354, 0314, 0339, 0337, 0316, 0341, 0352, 0351, 0283, 0313, 0330, 0301, 0348, 0298, 0290, 0335, 0309, 0322, 0321, 0312, 0323, 0303, 0349, 0344, 0327, 0295, 0299, 0320, 0285, 0306, 0310, 0287, 0332, 0340, 0293, 0317, 0305, 0342, 0311, 0318, 0346, 0294, 0350, 0284, 0308, 0307, 0286, 0324, 0353, 0336, 0288, 0291, 0334, 0326, 0355, 0356, 0319, 0300, 0338, 0331, 0333, 0302, 0304, 0328, 0345, 0347, 0315, 0343, 0289, 0296, 0329, 5444, 0282, 5426, 5424, 5443, 5434, 5470, 5430, 5528, 5517, 5464, 5484, 5495, 5428, 5427, 5505, 5425, 5454, 5521, 5497, 5501, 5461, 5436, 5468, 5490, 5508, 5515, 5456, 5437, 5438, 5448, 5479, 5524, 5500, 5446, 5473, 5486, 5531, 5472, 5469, 5463, 5460, 5485, 5502, 5519, 5489, 5518, 5442, 5510, 5487, 5482, 5493, 5471, 5522, 5514, 1631, 5496, 1639, 5520, 1649, 5527, 5498, 5530, 5440, 5534, 5532, 5433, 5480, 5488, 5511, 5529, 5492, 5465, 5504, 5445, 5491, 1643, 5476, 5432, 5449, 5439, 5512, 5478, 5525, 1622, 5506, 5523, 5474, 5451, 5467, 5457, 5431, 5452, 5481, 1568, 1610, 5450, 1587, 1572, 1603, 5507, 1641, 1635, 5441, 5509, 5429, 5494, 5475, 5458, 5483, 5526, 5513, 1611, 1605, 1602, 1594, 5459, 1623, 1577, 1638, 1613, 1573, 6754, 1599, 1644, 3532, 1570, 5435, 1647, 7999, 1618, 1616, 3582, 5453, 4236, 1604, 1640, 1608, 3572, 1645, 1578, 1588, 5466, 8120, 1607, 1632, 1569, 1646, 8045, 9326, 1637, 3531, 3510, 1571, 5499, 1600, 1597, 8081, 3559, 0191, 5533, 5447, 9390, 1634, 8025, 9308, 1574, 0951, 1586, 4149, 1583, 8103, 2762, 5477, 8115, 5924, 1576, 1619, 8019, 3504, 2908, 1591, 0628, 5503, 1592, 2877, 3521, 1617, 0618, 2927, 8069, 0942, 1584, 2853, 3574, 8119, 1595, 0647, 2294, 1620, 0274, 1255, 1899, 1596, 8071, 2864, 1590, 3900, 2939, 1135, 9319, 1502, 1475, 8021, 0950, 0027, 8056, 1630, 0988, 7440, 0962, 3579, 9340, 9285, 2562, 3002, 8039, 1589, 4154, 8005, 4205, 6755, 9320, 4189, 9301, 4216, 9282, 4167, 8033, 1606, 3577, 3571, 8092, 5462, 1314, 5516, 3501, 2945, 3034, 0646, 3535, 1257, 0958, 1612, 1001, 1651, 1648, 8051, 1626, 8067, 1601, 7406, 3589, 4219, 4074, 9295, 1120, 2867, 9313, 2250, 2882, 7415, 9291, 3512, 4171, 9304, 8653, 1615, 2905, 8068, 9370, 4218, 1258, 5455, 8090, 3190, 0960, 7362, 8063, 1642, 9335, 9343, 9401, 9310, 2402, 9318, 8048, 9374, 3526, 9325, 3152, 8052, 2895, 5847, 3546, 1081, 9280, 2233, 1628, 6790, 2854, 4203, 9322, 4200, 0001, 6774, 4459, 7994, 6822, 1650, 3585, 3395, 1625, 3207, 6770, 4204, 2890, 8055, 9346, 0522, 4191, 9352, 0021, 8696, 3498, 6803, 9345, 3426, 7442, 3541, 9405, 9384, 0984, 2866, 3220, 0249, 0625, 1751, 2920, 2916, 0965, 2851, 7473, 9336, 9380, 2565, 0517, 2249, 4161, 0012, 0640, 9373, 1271, 8113, 2253, 2938, 2925, 4827, 0636, 1636, 3563, 2260, 0642, 0928, 1627, 3547, 2865, 8020, 1579, 9297, 0983, 9377, 0837, 8376, 0968, 0635, 1593, 3565, 9395, 8078, 0262, 0442, 0785, 2076, 9415, 3079, 9366, 1581, 0931, 8118, 8034, 8004, 4175, 5282, 1790, 7998, 3209, 2052, 9391, 0970, 0156, 0934, 4211, 9410, 9383, 7446, 2961, 0121, 3583, 1299, 4797, 2102, 2926, 4978, 8111, 7418, 9375, 9372, 7401, 1909, 6736, 0243, 2210, 8035, 3558, 9353, 9356, 9357, 3025, 9368, 1324, 2440, 6798, 2080, 2270, 2742, 1152, 4796, 8080, 0124, 6752, 8123, 6727, 2374, 3684, 9414, 0648, 1580, 2817, 5753, 1318, 0641, 6737, 2269, 2911, 8341, 6807, 9341, 6468, 9398, 1614, 4150, 8029, 9315, 2683, 2457, 3502, 6761, 3539, 4176, 2618, 1973, 2947, 3047, 9329, 9351, 8102, 6414, 8093, 1294, 0622, 0969, 2078, 2934, 4422, 2165, 3036, 8084, 0164, 0664, 0456, 6777, 6808, 4863, 3217, 3529, 4385, 5733, 2915, 9358, 3499, 2786, 0981, 5194, 3561, 1964, 2544, 0766, 8022, 1090, 7508, 5780, 0775, 2085, 8018, 3540, 7366, 1598, 4170, 5307, 0671, 3511, 1624, 9416, 3021, 0952, 3580, 3073, 5953, 1371, 8044, 4477, 0992, 0652, 9359, 0957, 8392, 3588, 4213, 4141, 9364, 1871, 3367, 8700, 4916, 8013, 5043, 4057, 7126, 1945, 3174, 3562, 0093, 3537, 3096, 0659, 7394, 0630, 3509, 5619, 2310, 0814, 1471, 0609, 8038, 1268, 0666, 0023, 3587, 4138, 0935, 4786, 8076, 9393, 9404, 6235, 1290, 0224, 2955, 0547, 8121, 4857, 4838, 2880, 1330, 6758, 3748, 2421, 0038, 8001, 6744, 7785, 0658, 6158, 8032, 1957, 0166, 0989, 1156, 0947, 2448, 3065, 2935, 2442, 2697, 6805, 6826, 3523, 7384, 2940, 1686, 2235, 1609, 8697, 3039, 4181, 2064, 4563, 1437, 1115, 0939, 5207, 4826, 8098, 0364, 3522, 9363, 0660, 2869, 4144, 1750, 8673, 1121, 2770, 7359, 2910, 9947, 0528, 0967, 3763, 9075, 3260, 5779, 1935, 1237, 1582, 2518, 0819, 3518, 1286, 1295, 0644, 1377, 8091, 3473, 8083, 9417, 2323, 1124, 0069, 0973, 0409, 0842, 0674, 6728, 4803, 0035, 1575, 2057, 2932, 2888, 9348, 4185, 8027, 3624, 0982, 1806, 1907, 8638, 4160, 0729, 1709, 8495, 4212, 0926, 8108, 1106, 6731, 0424, 8100, 1254, 5877, 2244, 5181, 2859, 1758, 2071, 3497, 2285, 4187, 5595, 3576, 2236, 9412, 6472, 6453, 6719, 3862, 4220, 4184, 2781, 8766, 4022, 2839, 6434, 1493, 0611, 9289, 5596, 2861, 6743, 8031, 1972, 8023, 8053, 0138, 4880, 2259, 4230, 2893, 2937, 9333, 3292, 7206, 5200Line truncated
#else
public const int PercentScale = 100_000;
public static readonly (int Start, int End)[] PercentGroupsPromille =
[
(45000, 55000),
(70000, 80000),
(95000, 98000),
(98000, 100000),
(30000, 45000),
(0, 10000),
];
public static readonly int[] SpecialPercentPromille = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 10Line truncated
#endif
}
File diff suppressed because it is too large. Load diff
@@ -1,88 +0,0 @@
using System.Globalization;
using System.Numerics;
using PerfectNumbers.Core.Gpu;
namespace PerfectNumbers.Core.Cpu;
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithCpuOrder(
in MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder prototype,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult)
{
private MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder _tester = new()
{
DivisorLimit = prototype.DivisorLimit,
MinK = EnvironmentConfiguration.MinK,
};
private MersenneCpuDivisorScanSessionWithCpuOrder _divisorScanSession = new();
private readonly Action _markComposite = markComposite;
private readonly Action _clearComposite = clearComposite;
private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult = printResult;
public void ProcessPrime(ulong prime)
{
try
{
Console.WriteLine($"Processing {prime}");
string stateFile = Path.Combine(
PerfectNumberConstants.ByDivisorStateDirectory,
prime.ToString(CultureInfo.InvariantCulture) + ".bin");
ConfigureForPrime(stateFile);
bool isPrime = _tester.IsPrime(prime, out bool divisorsExhausted, out BigInteger divisor);
if (!isPrime)
{
if (!string.IsNullOrEmpty(stateFile) && File.Exists(stateFile))
{
File.Delete(stateFile);
}
_markComposite();
_printResult(prime, true, true, false, divisor);
Console.WriteLine($"Finished processing {prime}");
return;
}
_clearComposite();
_printResult(prime, true, divisorsExhausted, true, divisor);
Console.WriteLine($"Finished processing {prime}");
}
catch (Exception ex)
{
Console.WriteLine($"Error processing {ex.Message} {ex.StackTrace}");
Environment.Exit(1);
}
}
private void ConfigureForPrime(string stateFile)
{
BigInteger resumeK = EnvironmentConfiguration.MinK;
if (File.Exists(stateFile))
{
if (MersenneNumberDivisorByDivisorTester.TryReadLastSavedK(stateFile, out BigInteger lastK))
{
resumeK = lastK + BigInteger.One;
_tester.ResumeFromState(stateFile, lastK, resumeK);
}
else
{
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
}
}
else
{
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
}
_tester.ResetStateTracking();
}
public void Dispose()
{
}
}
@@ -1,101 +0,0 @@
using System.Globalization;
using System.Numerics;
using PerfectNumbers.Core.Gpu;
using PerfectNumbers.Core.Gpu.Accelerators;
namespace PerfectNumbers.Core.Cpu;
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder
{
private MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder _tester;
private MersenneCpuDivisorScanSessionWithHybridOrder _divisorScanSession;
private readonly Action _markComposite;
private readonly Action _clearComposite;
private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult;
public MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder(
in MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder prototype,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult)
{
_tester = new MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder
{
DivisorLimit = prototype.DivisorLimit,
MinK = EnvironmentConfiguration.MinK,
};
_divisorScanSession = new MersenneCpuDivisorScanSessionWithHybridOrder();
_divisorScanSession.Configure(_tester.Accelerator);
_markComposite = markComposite;
_clearComposite = clearComposite;
_printResult = printResult;
}
public void ProcessPrime(ulong prime)
{
try
{
Console.WriteLine($"Processing {prime}");
string stateFile = Path.Combine(
PerfectNumberConstants.ByDivisorStateDirectory,
prime.ToString(CultureInfo.InvariantCulture) + ".bin");
ConfigureForPrime(stateFile);
bool isPrime = _tester.IsPrime(prime, out bool divisorsExhausted, out BigInteger divisor);
if (!isPrime)
{
if (!string.IsNullOrEmpty(stateFile) && File.Exists(stateFile))
{
File.Delete(stateFile);
}
_markComposite();
_printResult(prime, true, true, false, divisor);
Console.WriteLine($"Finished processing {prime}");
return;
}
_clearComposite();
_printResult(prime, true, divisorsExhausted, true, divisor);
Console.WriteLine($"Finished processing {prime}");
}
catch (Exception ex)
{
Console.WriteLine($"Error processing {ex.Message} {ex.StackTrace}");
Environment.Exit(1);
}
}
private void ConfigureForPrime(string stateFile)
{
BigInteger resumeK = EnvironmentConfiguration.MinK;
if (File.Exists(stateFile))
{
if (MersenneNumberDivisorByDivisorTester.TryReadLastSavedK(stateFile, out BigInteger lastK))
{
resumeK = lastK + BigInteger.One;
_tester.ResumeFromState(stateFile, lastK, resumeK);
}
else
{
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
}
}
else
{
_tester.ResumeFromState(stateFile, BigInteger.Zero, resumeK);
}
_tester.ResetStateTracking();
}
public void Dispose()
{
PrimeOrderCalculatorAccelerator.Return(_tester.Accelerator);
}
}
@@ -1,34 +1,59 @@
using System.Globalization; using System.Globalization;
using System.Globalization;
using System.IO;
using System.Numerics; using System.Numerics;
using PerfectNumbers.Core.Gpu; using PerfectNumbers.Core.Gpu;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
using System.Runtime.CompilerServices;
#if DivisorSet_Pow2Groups
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder;
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder;
using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder;
#else
using TesterCpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
using TesterHybrid = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForHybridOrder;
using TesterGpu = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForGpuOrder;
#endif
namespace PerfectNumbers.Core.Cpu; namespace PerfectNumbers.Core.Cpu;
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder [EnumDependentTemplate(typeof(DivisorSet))]
[DeviceDependentTemplate(typeof(ComputationDevice))]
[NameSuffix("Order")]
internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate
{ {
private MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder _tester; #if DEVICE_GPU
private MersenneCpuDivisorScanSessionWithGpuOrder _divisorScanSession; private TesterGpu _tester;
#elif DEVICE_HYBRID
private TesterHybrid _tester;
#else
private TesterCpu _tester;
#endif
private readonly Action _markComposite; private readonly Action _markComposite;
private readonly Action _clearComposite; private readonly Action _clearComposite;
private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult; private readonly Action<ulong, bool, bool, bool, BigInteger> _printResult;
public MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder( public MersenneNumberDivisorByDivisorPrimeScanSessionWithTemplate(
in MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder prototype, #if DEVICE_GPU
in TesterGpu prototype,
#elif DEVICE_HYBRID
in TesterHybrid prototype,
#else
in TesterCpu prototype,
#endif
Action markComposite, Action markComposite,
Action clearComposite, Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult) Action<ulong, bool, bool, bool, BigInteger> printResult)
{ {
_tester = new MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder _tester = new()
{ {
DivisorLimit = prototype.DivisorLimit, DivisorLimit = prototype.DivisorLimit,
MinK = EnvironmentConfiguration.MinK, MinK = EnvironmentConfiguration.MinK,
}; };
_divisorScanSession = new MersenneCpuDivisorScanSessionWithGpuOrder();
_divisorScanSession.Configure(_tester.Accelerator);
_markComposite = markComposite; _markComposite = markComposite;
_clearComposite = clearComposite; _clearComposite = clearComposite;
_printResult = printResult; _printResult = printResult;
@@ -94,8 +119,11 @@ internal struct MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder
_tester.ResetStateTracking(); _tester.ResetStateTracking();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public void Dispose() public void Dispose()
{ {
#if DEVICE_GPU || DEVICE_HYBRID
PrimeOrderCalculatorAccelerator.Return(_tester.Accelerator); PrimeOrderCalculatorAccelerator.Return(_tester.Accelerator);
#endif
} }
} }
@@ -18,6 +18,8 @@ public static class EnvironmentConfiguration
public static bool UseGpuOrder; public static bool UseGpuOrder;
public static bool UseHybridOrder; public static bool UseHybridOrder;
public static bool UseCpuOrder; public static bool UseCpuOrder;
public static bool UsePow2GroupDivisors;
public static int ByDivisorSpecialRange;
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void Initialize() public static void Initialize()
@@ -6,6 +6,9 @@ using PerfectNumbers.Core.Gpu;
using PerfectNumbers.Core.Gpu.Accelerators; using PerfectNumbers.Core.Gpu.Accelerators;
using PerfectNumbers.Core.Cpu; using PerfectNumbers.Core.Cpu;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using MersenneNumberDivisorByDivisorCpuTesterWithCpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForCpuOrder;
using MersenneNumberDivisorByDivisorCpuTesterWithHybridOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForHybridOrder;
using MersenneNumberDivisorByDivisorCpuTesterWithGpuOrder = PerfectNumbers.Core.Cpu.MersenneNumberDivisorByDivisorCpuTesterWithForOneByOneDivisorSetForGpuOrder;
namespace PerfectNumbers.Core; namespace PerfectNumbers.Core;
@@ -104,6 +107,99 @@ public static class MersenneNumberDivisorByDivisorTester
Action<ulong, bool, bool, bool, BigInteger> pr) => Action<ulong, bool, bool, bool, BigInteger> pr) =>
RunGpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr)); RunGpuOrderFiltered(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void Run(
List<ulong> candidates,
ref MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder tester,
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
ulong startPrime,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult,
int threadCount,
int primesPerTask)
=> RunStructTester(
candidates,
ref tester,
previousResults,
startPrime,
markComposite,
clearComposite,
printResult,
threadCount,
primesPerTask,
static (
List<ulong> filteredPrimes,
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder prototype,
int workerCount,
int partitionSize,
Action mc,
Action cc,
Action<ulong, bool, bool, bool, BigInteger> pr) =>
RunCpuOrderFilteredPow2(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void Run(
List<ulong> candidates,
ref MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder tester,
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
ulong startPrime,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult,
int threadCount,
int primesPerTask)
=> RunStructTester(
candidates,
ref tester,
previousResults,
startPrime,
markComposite,
clearComposite,
printResult,
threadCount,
primesPerTask,
static (
List<ulong> filteredPrimes,
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder prototype,
int workerCount,
int partitionSize,
Action mc,
Action cc,
Action<ulong, bool, bool, bool, BigInteger> pr) =>
RunHybridOrderFilteredPow2(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static void Run(
List<ulong> candidates,
ref MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder tester,
Dictionary<ulong, (bool DetailedCheck, bool PassedAllTests)>? previousResults,
ulong startPrime,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult,
int threadCount,
int primesPerTask)
=> RunStructTester(
candidates,
ref tester,
previousResults,
startPrime,
markComposite,
clearComposite,
printResult,
threadCount,
primesPerTask,
static (
List<ulong> filteredPrimes,
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder prototype,
int workerCount,
int partitionSize,
Action mc,
Action cc,
Action<ulong, bool, bool, bool, BigInteger> pr) =>
RunGpuOrderFilteredPow2(filteredPrimes, prototype, workerCount, partitionSize, mc, cc, pr));
internal static bool TryReadLastSavedK(string stateFile, out BigInteger lastSavedK) internal static bool TryReadLastSavedK(string stateFile, out BigInteger lastSavedK)
{ {
lastSavedK = BigInteger.Zero; lastSavedK = BigInteger.Zero;
@@ -224,7 +320,7 @@ public static class MersenneNumberDivisorByDivisorTester
if (maxPrime - 1UL >= 64UL) if (maxPrime - 1UL >= 64UL)
{ {
return (BigInteger.One << 256) - BigInteger.One; return BigIntegerNumbers.OneShiftedLeft256MinusOne;
} }
return (BigInteger.One << (int)(maxPrime - 1UL)) - BigInteger.One; return (BigInteger.One << (int)(maxPrime - 1UL)) - BigInteger.One;
@@ -901,7 +997,7 @@ public static class MersenneNumberDivisorByDivisorTester
if (workerCount == 1) if (workerCount == 1)
{ {
DeterministicRandomCpu.Initialize(); DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithCpuOrder(prototypeCopy, markComposite, clearComposite, printResult); var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
foreach (ulong prime in filteredPrimes) foreach (ulong prime in filteredPrimes)
{ {
session.ProcessPrime(prime); session.ProcessPrime(prime);
@@ -923,7 +1019,7 @@ public static class MersenneNumberDivisorByDivisorTester
() => () =>
{ {
DeterministicRandomCpu.Initialize(); DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithCpuOrder(prototypeCopy, markComposite, clearComposite, printResult); var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
startGate.Wait(); startGate.Wait();
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}"); Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
@@ -986,7 +1082,7 @@ public static class MersenneNumberDivisorByDivisorTester
if (workerCount == 1) if (workerCount == 1)
{ {
DeterministicRandomCpu.Initialize(); DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder(prototypeCopy, markComposite, clearComposite, printResult); var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
GpuPrimeWorkLimiter.Acquire(); GpuPrimeWorkLimiter.Acquire();
foreach (ulong prime in filteredPrimes) foreach (ulong prime in filteredPrimes)
@@ -1012,7 +1108,7 @@ public static class MersenneNumberDivisorByDivisorTester
() => () =>
{ {
DeterministicRandomCpu.Initialize(); DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithHybridOrder(prototypeCopy, markComposite, clearComposite, printResult); var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
startGate.Wait(); startGate.Wait();
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}"); Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
@@ -1077,7 +1173,7 @@ public static class MersenneNumberDivisorByDivisorTester
if (workerCount == 1) if (workerCount == 1)
{ {
DeterministicRandomCpu.Initialize(); DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder(prototypeCopy, markComposite, clearComposite, printResult); var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
GpuPrimeWorkLimiter.Acquire(); GpuPrimeWorkLimiter.Acquire();
foreach (ulong prime in filteredPrimes) foreach (ulong prime in filteredPrimes)
@@ -1103,7 +1199,7 @@ public static class MersenneNumberDivisorByDivisorTester
() => () =>
{ {
DeterministicRandomCpu.Initialize(); DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithGpuOrder(prototypeCopy, markComposite, clearComposite, printResult); var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForOneByOneDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
startGate.Wait(); startGate.Wait();
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}"); Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
@@ -1231,5 +1327,255 @@ public static class MersenneNumberDivisorByDivisorTester
Task.WaitAll(tasks); Task.WaitAll(tasks);
startGate.Dispose(); startGate.Dispose();
} }
private static void RunCpuOrderFilteredPow2(
List<ulong> filteredPrimes,
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder prototype,
int workerCount,
int partitionSize,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult)
{
MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForCpuOrder prototypeCopy = prototype;
int totalCount = filteredPrimes.Count;
if (partitionSize > totalCount)
{
partitionSize = totalCount;
}
if (workerCount == 1)
{
DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
foreach (ulong prime in filteredPrimes)
{
session.ProcessPrime(prime);
}
session.Dispose();
return;
}
TaskScheduler scheduler = UnboundedTaskScheduler.Instance;
int nextIndex = 0;
Task[] tasks = new Task[workerCount];
var startGate = new ManualResetEventSlim(initialState: false);
for (int taskIndex = 0; taskIndex < workerCount; taskIndex++)
{
int workerIndex = taskIndex;
tasks[taskIndex] = Task.Factory.StartNew(
() =>
{
DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForCpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
startGate.Wait();
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
while (true)
{
int start = Interlocked.Add(ref nextIndex, partitionSize) - partitionSize;
if (start >= totalCount)
{
break;
}
int end = start + partitionSize;
if (end > totalCount)
{
end = totalCount;
}
for (int index = start; index < end; index++)
{
ulong prime = filteredPrimes[index];
if (prime > 1)
{
session.ProcessPrime(prime);
}
}
}
session.Dispose();
Console.WriteLine($"Task finished for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
},
CancellationToken.None,
TaskCreationOptions.None,
scheduler);
}
startGate.Set();
Console.WriteLine("All tasks started");
for (int index = 0; index < tasks.Length; index++)
{
tasks[index].Wait();
Console.WriteLine($"Task {index.ToString(CultureInfo.InvariantCulture)} finished");
}
}
private static void RunHybridOrderFilteredPow2(
List<ulong> filteredPrimes,
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder prototype,
int workerCount,
int partitionSize,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult)
{
MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForHybridOrder prototypeCopy = prototype;
int totalCount = filteredPrimes.Count;
if (partitionSize > totalCount)
{
partitionSize = totalCount;
}
if (workerCount == 1)
{
DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
foreach (ulong prime in filteredPrimes)
{
session.ProcessPrime(prime);
}
session.Dispose();
return;
}
TaskScheduler scheduler = UnboundedTaskScheduler.Instance;
int nextIndex = 0;
Task[] tasks = new Task[workerCount];
var startGate = new ManualResetEventSlim(initialState: false);
for (int taskIndex = 0; taskIndex < workerCount; taskIndex++)
{
int workerIndex = taskIndex;
tasks[taskIndex] = Task.Factory.StartNew(
() =>
{
DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForHybridOrder(prototypeCopy, markComposite, clearComposite, printResult);
startGate.Wait();
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
while (true)
{
int start = Interlocked.Add(ref nextIndex, partitionSize) - partitionSize;
if (start >= totalCount)
{
break;
}
int end = start + partitionSize;
if (end > totalCount)
{
end = totalCount;
}
for (int index = start; index < end; index++)
{
ulong prime = filteredPrimes[index];
if (prime > 1)
{
session.ProcessPrime(prime);
}
}
}
session.Dispose();
Console.WriteLine($"Task finished for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
},
CancellationToken.None,
TaskCreationOptions.None,
scheduler);
}
startGate.Set();
for (int index = 0; index < tasks.Length; index++)
{
tasks[index].Wait();
Console.WriteLine($"Task finished {index.ToString(CultureInfo.InvariantCulture)}");
}
}
private static void RunGpuOrderFilteredPow2(
List<ulong> filteredPrimes,
in MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder prototype,
int workerCount,
int partitionSize,
Action markComposite,
Action clearComposite,
Action<ulong, bool, bool, bool, BigInteger> printResult)
{
MersenneNumberDivisorByDivisorCpuTesterWithForPow2GroupsDivisorSetForGpuOrder prototypeCopy = prototype;
int totalCount = filteredPrimes.Count;
if (partitionSize > totalCount)
{
partitionSize = totalCount;
}
if (workerCount == 1)
{
DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
foreach (ulong prime in filteredPrimes)
{
session.ProcessPrime(prime);
}
session.Dispose();
return;
}
TaskScheduler scheduler = UnboundedTaskScheduler.Instance;
int nextIndex = 0;
Task[] tasks = new Task[workerCount];
var startGate = new ManualResetEventSlim(initialState: false);
for (int taskIndex = 0; taskIndex < workerCount; taskIndex++)
{
int workerIndex = taskIndex;
tasks[taskIndex] = Task.Factory.StartNew(
() =>
{
DeterministicRandomCpu.Initialize();
var session = new MersenneNumberDivisorByDivisorPrimeScanSessionWithForPow2GroupsDivisorSetForGpuOrder(prototypeCopy, markComposite, clearComposite, printResult);
startGate.Wait();
Console.WriteLine($"Task started for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
while (true)
{
int start = Interlocked.Add(ref nextIndex, partitionSize) - partitionSize;
if (start >= totalCount)
{
break;
}
int end = start + partitionSize;
if (end > totalCount)
{
end = totalCount;
}
for (int index = start; index < end; index++)
{
ulong prime = filteredPrimes[index];
if (prime > 1)
{
session.ProcessPrime(prime);
}
}
}
session.Dispose();
Console.WriteLine($"Task finished for worker {workerIndex.ToString(CultureInfo.InvariantCulture)}");
},
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
scheduler);
}
startGate.Set();
Task.WaitAll(tasks);
startGate.Dispose();
}
} }
@@ -170,20 +170,20 @@ public static partial class PrimeOrderCalculatorTemplate
private static int GetGroupWide(in UInt128 value, in UInt128 prime) private static int GetGroupWide(in UInt128 value, in UInt128 prime)
{ {
UInt128 threshold1 = prime >> 3; UInt128 threshold = prime >> 3;
if (value <= threshold1) if (value <= threshold)
{ {
return 1; return 1;
} }
UInt128 threshold2 = prime >> 2; threshold = prime >> 2;
if (value <= threshold2) if (value <= threshold)
{ {
return 2; return 2;
} }
UInt128 threshold3 = (UInt128)(((BigInteger)prime * 3) >> 3); threshold = (UInt128)(((BigInteger)prime * 3) >> 3);
if (value <= threshold3) if (value <= threshold)
{ {
return 3; return 3;
} }
@@ -306,6 +306,7 @@ public static partial class PrimeOrderCalculatorTemplate
} }
FactorEntry128 factor = factors[index]; FactorEntry128 factor = factors[index];
index++;
UInt128 primeFactor = factor.Value; UInt128 primeFactor = factor.Value;
UInt128 contribution = UInt128.One; UInt128 contribution = UInt128.One;
for (int exponent = 0; exponent <= factor.Exponent; exponent++) for (int exponent = 0; exponent <= factor.Exponent; exponent++)
@@ -316,7 +317,7 @@ public static partial class PrimeOrderCalculatorTemplate
break; break;
} }
BuildCandidatesRecursiveWide(order, factors, index + 1, nextDivisor, candidates, limit); BuildCandidatesRecursiveWide(order, factors, index, nextDivisor, candidates, limit);
if (candidates.Count >= limit) if (candidates.Count >= limit)
{ {
return; return;
@@ -1267,48 +1268,49 @@ public static partial class PrimeOrderCalculatorTemplate
private static int ExtractSmallPrimeExponent(ref ulong value, ulong primeValue, ulong quotient) private static int ExtractSmallPrimeExponent(ref ulong value, ulong primeValue, ulong quotient)
{ {
ulong dividend = quotient; ulong dividend = quotient;
int exponent = 1;
if (dividend < primeValue) if (dividend < primeValue)
{ {
value = dividend; value = dividend;
return exponent; return 1;
} }
quotient = dividend / primeValue; quotient = dividend / primeValue;
ulong product = quotient * primeValue; if (dividend - quotient * primeValue != 0UL)
if (dividend - product != 0UL)
{ {
value = dividend; value = dividend;
return exponent; return 1;
} }
dividend = quotient; dividend = quotient;
exponent++;
if (dividend < primeValue) if (dividend < primeValue)
{ {
value = dividend; value = dividend;
return exponent; return 2;
} }
quotient = dividend / primeValue; quotient = dividend / primeValue;
product = quotient * primeValue; if (dividend - quotient * primeValue != 0UL)
if (dividend - product != 0UL)
{ {
value = dividend; value = dividend;
return exponent; return 2;
} }
dividend = quotient; return ExtractSmallPrimeExponentWithLoop(ref value, primeValue, quotient);
exponent++; }
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
private static int ExtractSmallPrimeExponentWithLoop(ref ulong value, ulong primeValue, ulong quotient)
{
ulong dividend = quotient;
int exponent = 3;
while (true) while (true)
{ {
quotient = dividend / primeValue; quotient = dividend / primeValue;
product = quotient * primeValue;
if (dividend - product != 0UL) if (dividend - quotient * primeValue != 0UL)
{ {
break; break;
} }
@@ -1320,6 +1322,7 @@ public static partial class PrimeOrderCalculatorTemplate
value = dividend; value = dividend;
return exponent; return exponent;
} }
#endif #endif
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
@@ -1336,16 +1339,13 @@ public static partial class PrimeOrderCalculatorTemplate
} }
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static ulong AdvancePolynomial(ulong x, ulong c, ulong modulus) private static ulong AdvancePolynomial(ulong x, ulong c, ulong modulus) => unchecked(x * x % modulus + c) % modulus;
{
return unchecked((x * x) % modulus + c) % modulus;
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
private static ulong AdvancePolynomialTwice(ulong x, ulong c, ulong modulus) private static ulong AdvancePolynomialTwice(ulong x, ulong c, ulong modulus)
{ {
x = AdvancePolynomial(x, c, modulus); x = unchecked(x * x % modulus + c) % modulus;
return AdvancePolynomial(x, c, modulus); return unchecked(x * x % modulus + c) % modulus;
} }
[MethodImpl(MethodImplOptions.AggressiveOptimization)] [MethodImpl(MethodImplOptions.AggressiveOptimization)]
@@ -1911,7 +1911,20 @@ public static partial class PrimeOrderCalculatorTemplate
List<PartialFactorPendingEntry> pending = result.PendingFactors; List<PartialFactorPendingEntry> pending = result.PendingFactors;
pending.Clear(); pending.Clear();
// #if DEVICE_HYBRID
// bool pollardRhoDeadlineReached = false;
// CollectSmallFactors(gpu, config, exponentSlots, primeSlots, ref value, ref pollardRhoDeadlineReached, out int factorCount);
// if (factorCount == 0 && !pollardRhoDeadlineReached)
// {
// PopulateSmallPrimeFactors(
// value,
// config.SmallFactorLimit,
// primeSlots,
// exponentSlots,
// out factorCount,
// out value);
// }
// #elif DEVICE_CPU
PopulateSmallPrimeFactors( PopulateSmallPrimeFactors(
value, value,
config.SmallFactorLimit, config.SmallFactorLimit,
@@ -1919,6 +1932,8 @@ public static partial class PrimeOrderCalculatorTemplate
exponentSlots, exponentSlots,
out int factorCount, out int factorCount,
out value); out value);
// #endif
bool cofactorContainsComposite; bool cofactorContainsComposite;
if (value > 1UL) if (value > 1UL)
@@ -3051,7 +3066,7 @@ public static partial class PrimeOrderCalculatorTemplate
return true; return true;
} }
#if DEVICE_GPU #if DEVICE_GPU //|| DEVICE_HYBRID
private const int GpuSmallPrimeFactorSlots = 64; private const int GpuSmallPrimeFactorSlots = 64;
// GPU specific. It doesn't make sense to consolidate into one method. // GPU specific. It doesn't make sense to consolidate into one method.