Mark divisor-based candidates composite only on factor discovery
This commit is contained in:
1 parent
873328b944
commit
8562696b13
2 files changed
+58
-8
No files matched your search
@@ -68,7 +68,7 @@ public class ProgramTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Divisor_mode_checks_all_candidates_when_none_specified()
|
public void Divisor_mode_scans_dynamic_cycles_when_none_specified()
|
||||||
{
|
{
|
||||||
var useDivisorField = typeof(Program).GetField("_useDivisor", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var useDivisorField = typeof(Program).GetField("_useDivisor", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
var divisorField = typeof(Program).GetField("_divisor", BindingFlags.NonPublic | BindingFlags.Static)!;
|
var divisorField = typeof(Program).GetField("_divisor", BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
@@ -80,7 +80,7 @@ public class ProgramTests
|
|||||||
|
|
||||||
useDivisorField.SetValue(null, true);
|
useDivisorField.SetValue(null, true);
|
||||||
divisorField.SetValue(null, 0UL);
|
divisorField.SetValue(null, 0UL);
|
||||||
testerField.SetValue(null, new MersenneNumberDivisorGpuTester());
|
testerField.SetValue(null, null);
|
||||||
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
primeField.SetValue(null, new ThreadLocal<PrimeTester>(() => new PrimeTester(), trackAllValues: true));
|
||||||
residueField.SetValue(null, new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
|
residueField.SetValue(null, new ThreadLocal<ModResidueTracker>(() => new ModResidueTracker(ResidueModel.Identity, 2UL, true), trackAllValues: true));
|
||||||
candidatesField.SetValue(null, new (ulong, uint)[] { (7UL, 3U), (23UL, 11U) });
|
candidatesField.SetValue(null, new (ulong, uint)[] { (7UL, 3U), (23UL, 11U) });
|
||||||
@@ -88,8 +88,8 @@ public class ProgramTests
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Program.IsEvenPerfectCandidate(11UL).Should().BeTrue();
|
Program.IsEvenPerfectCandidate(11UL).Should().BeFalse();
|
||||||
Program.IsEvenPerfectCandidate(5UL).Should().BeFalse();
|
Program.IsEvenPerfectCandidate(5UL).Should().BeTrue();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ internal static class Program
|
|||||||
private static ulong _divisor;
|
private static ulong _divisor;
|
||||||
private static MersenneNumberDivisorGpuTester? _divisorTester;
|
private static MersenneNumberDivisorGpuTester? _divisorTester;
|
||||||
private static (ulong divisor, uint cycle)[]? _divisorCandidates;
|
private static (ulong divisor, uint cycle)[]? _divisorCandidates;
|
||||||
|
private const int ExtraDivisorCycleSearchLimit = 32;
|
||||||
private static ulong? _orderWarmupLimitOverride;
|
private static ulong? _orderWarmupLimitOverride;
|
||||||
private static unsafe delegate*<ulong, ref ulong, ulong> _transformP;
|
private static unsafe delegate*<ulong, ref ulong, ulong> _transformP;
|
||||||
private static long _state;
|
private static long _state;
|
||||||
@@ -921,6 +922,26 @@ internal static class Program
|
|||||||
return list.ToArray();
|
return list.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsDivisible(ulong exponent, ulong divisor)
|
||||||
|
{
|
||||||
|
if (_divisorTester is not null)
|
||||||
|
{
|
||||||
|
return _divisorTester.IsDivisible(exponent, divisor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong remainder = 1UL;
|
||||||
|
for (ulong i = 0; i < exponent; i++)
|
||||||
|
{
|
||||||
|
remainder <<= 1;
|
||||||
|
if (remainder >= divisor)
|
||||||
|
{
|
||||||
|
remainder -= divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return remainder == 1UL;
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
internal static bool IsEvenPerfectCandidate(ulong p)
|
internal static bool IsEvenPerfectCandidate(ulong p)
|
||||||
{
|
{
|
||||||
@@ -995,8 +1016,14 @@ internal static class Program
|
|||||||
{
|
{
|
||||||
if (_divisor != 0UL)
|
if (_divisor != 0UL)
|
||||||
{
|
{
|
||||||
detailedCheck = _divisorTester!.IsDivisible(p, _divisor);
|
if (IsDivisible(p, _divisor))
|
||||||
return detailedCheck;
|
{
|
||||||
|
detailedCheck = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
detailedCheck = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var candidates = _divisorCandidates!;
|
var candidates = _divisorCandidates!;
|
||||||
@@ -1009,15 +1036,38 @@ internal static class Program
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_divisorTester!.IsDivisible(p, d))
|
if (IsDivisible(p, d))
|
||||||
{
|
{
|
||||||
detailedCheck = true;
|
detailedCheck = true;
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int k = 1; k <= ExtraDivisorCycleSearchLimit; k++)
|
||||||
|
{
|
||||||
|
ulong kMul2 = 2UL * (ulong)k;
|
||||||
|
if (p > ulong.MaxValue / kMul2)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong d = kMul2 * p + 1UL;
|
||||||
|
ulong cycle = MersenneDivisorCycles.Shared.GetCycle(d);
|
||||||
|
if (p % cycle != 0UL)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsDivisible(p, d))
|
||||||
|
{
|
||||||
|
detailedCheck = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
detailedCheck = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
detailedCheck = MersenneTesters.Value!.IsMersennePrime(p);
|
detailedCheck = MersenneTesters.Value!.IsMersennePrime(p);
|
||||||
return detailedCheck;
|
return detailedCheck;
|
||||||
|
|||||||
Reference in new issue
Block a user