Require filtered primes for by-divisor scanning
This commit is contained in:
1 parent
b705488b35
commit
5ce0cf74fc
3 files changed
+91
-11
No files matched your search
@@ -376,6 +376,12 @@ internal static class Program
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useByDivisor && string.IsNullOrEmpty(filterFile))
|
||||||
|
{
|
||||||
|
Console.WriteLine("--mersenne=bydivisor requires --filter-p=<path>.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (showHelp)
|
if (showHelp)
|
||||||
{
|
{
|
||||||
PrintHelp();
|
PrintHelp();
|
||||||
@@ -601,6 +607,17 @@ internal static class Program
|
|||||||
// filter.Sort();
|
// filter.Sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (useByDivisor)
|
||||||
|
{
|
||||||
|
if (maxP <= 1UL)
|
||||||
|
{
|
||||||
|
Console.WriteLine("The filter specified by --filter-p must contain at least one prime exponent greater than 1 for --mersenne=bydivisor.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_byDivisorTester!.ConfigureFromMaxPrime(maxP);
|
||||||
|
}
|
||||||
|
|
||||||
if (_primeCount >= 2)
|
if (_primeCount >= 2)
|
||||||
{
|
{
|
||||||
_primeFoundAfterInit = true;
|
_primeFoundAfterInit = true;
|
||||||
@@ -785,7 +802,7 @@ internal static class Program
|
|||||||
Console.WriteLine(" --use-order test primality via q order");
|
Console.WriteLine(" --use-order test primality via q order");
|
||||||
Console.WriteLine(" --workaround-mod avoid '%' operator on the GPU");
|
Console.WriteLine(" --workaround-mod avoid '%' operator on the GPU");
|
||||||
// mod-automaton removed
|
// mod-automaton removed
|
||||||
Console.WriteLine(" --filter-p=<path> process only p from previous run results");
|
Console.WriteLine(" --filter-p=<path> process only p from previous run results (required for --mersenne=bydivisor)");
|
||||||
Console.WriteLine(" --write-batch-size=<value> overwrite frequency of disk writes (default 100 lines)");
|
Console.WriteLine(" --write-batch-size=<value> overwrite frequency of disk writes (default 100 lines)");
|
||||||
Console.WriteLine(" --gcd-filter enable early sieve based on GCD");
|
Console.WriteLine(" --gcd-filter enable early sieve based on GCD");
|
||||||
Console.WriteLine(" --help, -help, --?, -?, /? show this help message");
|
Console.WriteLine(" --help, -help, --?, -?, /? show this help message");
|
||||||
@@ -1143,7 +1160,7 @@ internal static class Program
|
|||||||
searchedMersenne = true;
|
searchedMersenne = true;
|
||||||
if (_useByDivisorMode)
|
if (_useByDivisorMode)
|
||||||
{
|
{
|
||||||
return _byDivisorTester!.IsPrime(p, divisorCyclesSearchLimit, out detailedCheck);
|
return _byDivisorTester!.IsPrime(p, out detailedCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_useDivisor)
|
if (_useDivisor)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using PerfectNumbers.Core.Gpu;
|
using PerfectNumbers.Core.Gpu;
|
||||||
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -66,14 +67,40 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void ByDivisor_tester_tracks_divisors_across_primes()
|
public void ByDivisor_tester_tracks_divisors_across_primes()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.IsPrime(5UL, 64UL, out bool exhausted).Should().BeTrue();
|
tester.ConfigureFromMaxPrime(11UL);
|
||||||
|
|
||||||
|
tester.IsPrime(5UL, out bool exhausted).Should().BeTrue();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
|
||||||
tester.IsPrime(7UL, 96UL, out exhausted).Should().BeTrue();
|
tester.IsPrime(7UL, out exhausted).Should().BeTrue();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
|
||||||
tester.IsPrime(11UL, 128UL, out exhausted).Should().BeFalse();
|
tester.IsPrime(11UL, out exhausted).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
public void ByDivisor_tester_requires_configuration()
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
Action act = () => tester.IsPrime(5UL, out _);
|
||||||
|
act.Should().Throw<InvalidOperationException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
public void ByDivisor_tester_respects_filter_based_limit()
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
tester.ConfigureFromMaxPrime(5UL);
|
||||||
|
|
||||||
|
tester.IsPrime(5UL, out _).Should().BeTrue();
|
||||||
|
tester.IsPrime(7UL, out bool exhausted).Should().BeTrue();
|
||||||
|
exhausted.Should().BeTrue();
|
||||||
|
|
||||||
|
tester.IsPrime(11UL, out bool divisorsExhausted).Should().BeTrue();
|
||||||
|
divisorsExhausted.Should().BeTrue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,6 +16,7 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
private readonly List<ulong> _lastPrimes = new();
|
private readonly List<ulong> _lastPrimes = new();
|
||||||
private readonly object _sync = new();
|
private readonly object _sync = new();
|
||||||
private ulong _divisorLimit;
|
private ulong _divisorLimit;
|
||||||
|
private bool _isConfigured;
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>> _updateKernelCache = new();
|
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>> _updateKernelCache = new();
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>> _initialKernelCache = new();
|
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>> _initialKernelCache = new();
|
||||||
@@ -26,12 +27,32 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> GetInitialKernel(Accelerator accelerator) =>
|
private Action<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>> GetInitialKernel(Accelerator accelerator) =>
|
||||||
_initialKernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(InitialKernel));
|
_initialKernelCache.GetOrAdd(accelerator, acc => acc.LoadAutoGroupedStreamKernel<Index1D, ulong, ArrayView<ulong>, ArrayView<ulong>, ArrayView<byte>>(InitialKernel));
|
||||||
|
|
||||||
public bool IsPrime(ulong prime, ulong divisorLimit, out bool divisorsExhausted)
|
public void ConfigureFromMaxPrime(ulong maxPrime)
|
||||||
{
|
{
|
||||||
lock (_sync)
|
lock (_sync)
|
||||||
{
|
{
|
||||||
_divisorLimit = divisorLimit;
|
if (_divisors.Count > 0)
|
||||||
ulong allowedMax = ComputeAllowedMaxDivisor(prime, divisorLimit);
|
{
|
||||||
|
_divisors.Clear();
|
||||||
|
_remainders.Clear();
|
||||||
|
_lastPrimes.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
_divisorLimit = ComputeDivisorLimitFromMaxPrime(maxPrime);
|
||||||
|
_isConfigured = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPrime(ulong prime, out bool divisorsExhausted)
|
||||||
|
{
|
||||||
|
lock (_sync)
|
||||||
|
{
|
||||||
|
if (!_isConfigured)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong allowedMax = ComputeAllowedMaxDivisor(prime);
|
||||||
if (allowedMax < 3UL)
|
if (allowedMax < 3UL)
|
||||||
{
|
{
|
||||||
divisorsExhausted = true;
|
divisorsExhausted = true;
|
||||||
@@ -177,7 +198,22 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
return composite;
|
return composite;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong ComputeAllowedMaxDivisor(ulong prime, ulong divisorLimit)
|
private static ulong ComputeDivisorLimitFromMaxPrime(ulong maxPrime)
|
||||||
|
{
|
||||||
|
if (maxPrime <= 1UL)
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxPrime - 1UL >= 64UL)
|
||||||
|
{
|
||||||
|
return ulong.MaxValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (1UL << (int)(maxPrime - 1UL)) - 1UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong ComputeAllowedMaxDivisor(ulong prime)
|
||||||
{
|
{
|
||||||
if (prime <= 1UL)
|
if (prime <= 1UL)
|
||||||
{
|
{
|
||||||
@@ -186,11 +222,11 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester
|
|||||||
|
|
||||||
if (prime - 1UL >= 64UL)
|
if (prime - 1UL >= 64UL)
|
||||||
{
|
{
|
||||||
return divisorLimit;
|
return _divisorLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ulong maxByPrime = (1UL << (int)(prime - 1UL)) - 1UL;
|
ulong maxByPrime = (1UL << (int)(prime - 1UL)) - 1UL;
|
||||||
return Math.Min(maxByPrime, divisorLimit);
|
return Math.Min(maxByPrime, _divisorLimit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateKernel(Index1D index, ulong prime, ArrayView<ulong> divisors, ArrayView<ulong> remainders, ArrayView<ulong> lastPrimes, ArrayView<byte> hits)
|
private static void UpdateKernel(Index1D index, ulong prime, ArrayView<ulong> divisors, ArrayView<ulong> remainders, ArrayView<ulong> lastPrimes, ArrayView<byte> hits)
|
||||||
|
|||||||
Reference in new issue
Block a user