Expand GPU coverage for even perfect candidate tests
This commit is contained in:
1 parent
b676d89293
commit
94b314df23
4 files changed
+189
No files matched your search
@@ -1,6 +1,7 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -398,6 +399,143 @@ public class ProgramTests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(KnownMersennePrimeExponents))]
|
||||||
|
public void IsEvenPerfectCandidate_accepts_known_small_mersenne_primes(ulong exponent)
|
||||||
|
{
|
||||||
|
var useDivisorField = typeof(Program).GetField("_useDivisor", 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 residueField = typeof(Program).GetField("PResidue", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
var gcdFilterField = typeof(Program).GetField("_useGcdFilter", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
var forceCpuProp = typeof(GpuContextPool).GetProperty("ForceCpu");
|
||||||
|
|
||||||
|
useDivisorField.SetValue(null, false);
|
||||||
|
gcdFilterField.SetValue(null, false);
|
||||||
|
mersenneField.SetValue(null, new ThreadLocal<MersenneNumberTester>(() => new MersenneNumberTester(
|
||||||
|
useIncremental: true,
|
||||||
|
useGpuScan: false,
|
||||||
|
useGpuOrder: false,
|
||||||
|
useResidue: true,
|
||||||
|
maxK: 1_024UL,
|
||||||
|
residueDivisorSets: 1UL), trackAllValues: true));
|
||||||
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
|
residueField.SetValue(null, new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true));
|
||||||
|
forceCpuProp!.SetValue(null, true);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Program.IsEvenPerfectCandidate(exponent, 0UL, out bool searched, out bool detailedCheck).Should().BeTrue();
|
||||||
|
searched.Should().BeTrue();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
useDivisorField.SetValue(null, false);
|
||||||
|
mersenneField.SetValue(null, null);
|
||||||
|
primeField.SetValue(null, null);
|
||||||
|
residueField.SetValue(null, null);
|
||||||
|
gcdFilterField.SetValue(null, false);
|
||||||
|
forceCpuProp!.SetValue(null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[MemberData(nameof(KnownMersennePrimeGpuConfigurations))]
|
||||||
|
public void IsEvenPerfectCandidate_accepts_known_small_mersenne_primes_on_gpu(
|
||||||
|
ulong exponent,
|
||||||
|
MersenneGpuCandidateConfig configuration)
|
||||||
|
{
|
||||||
|
var useDivisorField = typeof(Program).GetField("_useDivisor", 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 residueField = typeof(Program).GetField("PResidue", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
var gcdFilterField = typeof(Program).GetField("_useGcdFilter", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
var forceCpuProp = typeof(GpuContextPool).GetProperty("ForceCpu");
|
||||||
|
|
||||||
|
useDivisorField.SetValue(null, false);
|
||||||
|
gcdFilterField.SetValue(null, false);
|
||||||
|
mersenneField.SetValue(null, new ThreadLocal<MersenneNumberTester>(() => new MersenneNumberTester(
|
||||||
|
useIncremental: false,
|
||||||
|
kernelType: configuration.KernelType,
|
||||||
|
useGpuScan: true,
|
||||||
|
useGpuOrder: configuration.UseGpuOrder,
|
||||||
|
useResidue: true,
|
||||||
|
maxK: (UInt128)configuration.ResidueMaxK,
|
||||||
|
residueDivisorSets: (UInt128)configuration.ResidueSetCount), trackAllValues: true));
|
||||||
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
|
residueField.SetValue(null, new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, exponent, true), trackAllValues: true));
|
||||||
|
forceCpuProp!.SetValue(null, false);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Program.IsEvenPerfectCandidate(exponent, 0UL, out bool searched, out bool detailedCheck).Should().BeTrue();
|
||||||
|
searched.Should().BeTrue();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
useDivisorField.SetValue(null, false);
|
||||||
|
mersenneField.SetValue(null, null);
|
||||||
|
primeField.SetValue(null, null);
|
||||||
|
residueField.SetValue(null, null);
|
||||||
|
gcdFilterField.SetValue(null, false);
|
||||||
|
forceCpuProp!.SetValue(null, false);
|
||||||
|
GpuContextPool.DisposeAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> KnownMersennePrimeExponents()
|
||||||
|
{
|
||||||
|
foreach (ulong exponent in KnownMersennePrimeExponentValues)
|
||||||
|
{
|
||||||
|
yield return new object[] { exponent };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> KnownMersennePrimeGpuConfigurations()
|
||||||
|
{
|
||||||
|
MersenneGpuCandidateConfig[] configs =
|
||||||
|
{
|
||||||
|
new(GpuKernelType.Incremental, true, 1_024UL, 1UL),
|
||||||
|
new(GpuKernelType.Incremental, false, 2_048UL, 1UL),
|
||||||
|
new(GpuKernelType.Pow2Mod, true, 4_096UL, 2UL),
|
||||||
|
new(GpuKernelType.Pow2Mod, false, 512UL, 2UL),
|
||||||
|
};
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
foreach (ulong exponent in KnownMersennePrimeExponentValues)
|
||||||
|
{
|
||||||
|
var config = configs[index % configs.Length];
|
||||||
|
yield return new object[] { exponent, config };
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly ulong[] KnownMersennePrimeExponentValues =
|
||||||
|
[
|
||||||
|
31UL,
|
||||||
|
61UL,
|
||||||
|
89UL,
|
||||||
|
107UL,
|
||||||
|
127UL,
|
||||||
|
521UL,
|
||||||
|
607UL,
|
||||||
|
1279UL,
|
||||||
|
2203UL,
|
||||||
|
2281UL,
|
||||||
|
3217UL,
|
||||||
|
4253UL,
|
||||||
|
4423UL,
|
||||||
|
9689UL,
|
||||||
|
9941UL,
|
||||||
|
11213UL,
|
||||||
|
];
|
||||||
|
|
||||||
|
public readonly record struct MersenneGpuCandidateConfig(
|
||||||
|
GpuKernelType KernelType,
|
||||||
|
bool UseGpuOrder,
|
||||||
|
ulong ResidueMaxK,
|
||||||
|
ulong ResidueSetCount);
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Composite_candidates_flagged_for_residue_output_skip()
|
public void Composite_candidates_flagged_for_residue_output_skip()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,6 +21,18 @@ public class MersenneNumberResidueCpuTesterTests
|
|||||||
RunCase(tester, 127UL, 1_000UL, expectedPrime: true);
|
RunCase(tester, 127UL, 1_000UL, expectedPrime: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
public void Scan_recognizes_all_known_small_mersenne_primes()
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberResidueCpuTester();
|
||||||
|
|
||||||
|
foreach (ulong exponent in MersennePrimeTestData.Exponents)
|
||||||
|
{
|
||||||
|
RunCase(tester, exponent, 1UL, expectedPrime: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void RunCase(MersenneNumberResidueCpuTester tester, ulong exponent, ulong maxK, bool expectedPrime)
|
private static void RunCase(MersenneNumberResidueCpuTester tester, ulong exponent, ulong maxK, bool expectedPrime)
|
||||||
{
|
{
|
||||||
bool isPrime = true;
|
bool isPrime = true;
|
||||||
|
|||||||
@@ -25,6 +25,20 @@ public class MersenneNumberResidueGpuTesterTests
|
|||||||
RunCase(tester, 127UL, 1_001UL, expectedPrime: true);
|
RunCase(tester, 127UL, 1_001UL, expectedPrime: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(false)]
|
||||||
|
[InlineData(true)]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
public void Scan_recognizes_all_known_small_mersenne_primes(bool useGpuOrder)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberResidueGpuTester(useGpuOrder);
|
||||||
|
|
||||||
|
foreach (ulong exponent in MersennePrimeTestData.Exponents)
|
||||||
|
{
|
||||||
|
RunCase(tester, exponent, 1UL, expectedPrime: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(false)]
|
[InlineData(false)]
|
||||||
[InlineData(true)]
|
[InlineData(true)]
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
namespace PerfectNumbers.Core.Tests;
|
||||||
|
|
||||||
|
internal static class MersennePrimeTestData
|
||||||
|
{
|
||||||
|
public static readonly ulong[] Exponents =
|
||||||
|
{
|
||||||
|
31UL,
|
||||||
|
61UL,
|
||||||
|
89UL,
|
||||||
|
107UL,
|
||||||
|
127UL,
|
||||||
|
521UL,
|
||||||
|
607UL,
|
||||||
|
1279UL,
|
||||||
|
2203UL,
|
||||||
|
2281UL,
|
||||||
|
3217UL,
|
||||||
|
4253UL,
|
||||||
|
4423UL,
|
||||||
|
9689UL,
|
||||||
|
9941UL,
|
||||||
|
11213UL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Reference in new issue
Block a user