Divisor checking optimized to only flag if divisor was found or not without returning complete array of hits. We'll now also track residues for 13, 17 & 19 as the most frequent ones.
This commit is contained in:
1 parent
85a90c70bf
commit
86192a71b0
7 files changed
+158
-62
No files matched your search
@@ -104,7 +104,7 @@ public class MersenneNumberDivisorByDivisorTesterTests
|
|||||||
|
|
||||||
private sealed class DummySession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
|
private sealed class DummySession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
|
||||||
{
|
{
|
||||||
public void CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes, Span<byte> hits)
|
public bool CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,16 +47,18 @@ public class MersenneNumberDivisorCpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] primes = [5UL, 7UL, 11UL, 13UL];
|
ulong[] primes = [5UL, 7UL, 11UL, 13UL];
|
||||||
byte[] hits = new byte[primes.Length];
|
|
||||||
|
|
||||||
ulong cycle23 = MersenneDivisorCycles.CalculateCycleLengthCpu(23UL, MontgomeryDivisorDataPool.Shared.FromModulus(23UL));
|
ulong cycle23 = MersenneDivisorCycles.CalculateCycleLengthCpu(23UL, MontgomeryDivisorDataPool.Shared.FromModulus(23UL));
|
||||||
session.CheckDivisor(23UL, MontgomeryDivisorDataPool.Shared.FromModulus(23UL), cycle23, primes, hits);
|
session.CheckDivisor(23UL, MontgomeryDivisorDataPool.Shared.FromModulus(23UL), cycle23, primes).Should().BeTrue();
|
||||||
hits.Should().ContainInOrder([0, 0, 1, 0]);
|
|
||||||
|
ulong[] primesWithoutHit = [5UL, 7UL, 13UL];
|
||||||
|
session.CheckDivisor(23UL, MontgomeryDivisorDataPool.Shared.FromModulus(23UL), cycle23, primesWithoutHit).Should().BeFalse();
|
||||||
|
|
||||||
Array.Fill(hits, (byte)0);
|
|
||||||
ulong cycle31 = MersenneDivisorCycles.CalculateCycleLengthCpu(31UL, MontgomeryDivisorDataPool.Shared.FromModulus(31UL));
|
ulong cycle31 = MersenneDivisorCycles.CalculateCycleLengthCpu(31UL, MontgomeryDivisorDataPool.Shared.FromModulus(31UL));
|
||||||
session.CheckDivisor(31UL, MontgomeryDivisorDataPool.Shared.FromModulus(31UL), cycle31, primes, hits);
|
session.CheckDivisor(31UL, MontgomeryDivisorDataPool.Shared.FromModulus(31UL), cycle31, primes).Should().BeTrue();
|
||||||
hits.Should().ContainInOrder([1, 0, 0, 0]);
|
|
||||||
|
ulong[] primesBeforeHit = [7UL, 11UL, 13UL];
|
||||||
|
session.CheckDivisor(31UL, MontgomeryDivisorDataPool.Shared.FromModulus(31UL), cycle31, primesBeforeHit).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -77,13 +79,13 @@ public class MersenneNumberDivisorCpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] exponents = [6UL, 7UL, 9UL, 10UL, 12UL];
|
ulong[] exponents = [6UL, 7UL, 9UL, 10UL, 12UL];
|
||||||
byte[] hits = new byte[exponents.Length];
|
|
||||||
|
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(7UL);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(7UL);
|
||||||
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthCpu(7UL, divisorData);
|
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthCpu(7UL, divisorData);
|
||||||
session.CheckDivisor(7UL, divisorData, cycle, exponents, hits);
|
session.CheckDivisor(7UL, divisorData, cycle, exponents).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().Equal([1, 0, 1, 0, 1]);
|
ulong[] nonDivisibleExponents = [5UL, 11UL];
|
||||||
|
session.CheckDivisor(7UL, divisorData, cycle, nonDivisibleExponents).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -104,13 +106,13 @@ public class MersenneNumberDivisorCpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] exponents = [10UL, 11UL, 20UL, 21UL, 30UL];
|
ulong[] exponents = [10UL, 11UL, 20UL, 21UL, 30UL];
|
||||||
byte[] hits = new byte[exponents.Length];
|
|
||||||
|
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(11UL);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(11UL);
|
||||||
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthCpu(11UL, divisorData);
|
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthCpu(11UL, divisorData);
|
||||||
session.CheckDivisor(11UL, divisorData, cycle, exponents, hits);
|
session.CheckDivisor(11UL, divisorData, cycle, exponents).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().Equal([1, 0, 1, 0, 1]);
|
ulong[] nonDivisibleExponents = [5UL, 17UL];
|
||||||
|
session.CheckDivisor(11UL, divisorData, cycle, nonDivisibleExponents).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -229,11 +229,11 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] primes = [31UL, 37UL, 41UL];
|
ulong[] primes = [31UL, 37UL, 41UL];
|
||||||
byte[] hits = new byte[primes.Length];
|
|
||||||
|
|
||||||
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), 0UL, primes, hits);
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), 0UL, primes).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().ContainInOrder([0, 1, 0]);
|
ulong[] primesWithoutHit = [31UL, 41UL];
|
||||||
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), 0UL, primesWithoutHit).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -254,16 +254,18 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] primes = [31UL, 37UL, 41UL, 43UL];
|
ulong[] primes = [31UL, 37UL, 41UL, 43UL];
|
||||||
byte[] hits = new byte[primes.Length];
|
|
||||||
|
|
||||||
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL));
|
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL));
|
||||||
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primes, hits);
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primes).Should().BeTrue();
|
||||||
hits.Should().ContainInOrder([0, 1, 0, 0]);
|
|
||||||
|
ulong[] primesBeforeHit = [31UL];
|
||||||
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primesBeforeHit).Should().BeFalse();
|
||||||
|
|
||||||
Array.Fill(hits, (byte)0);
|
|
||||||
ulong cycle13367 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 13367UL, MontgomeryDivisorDataPool.Shared.FromModulus(13367UL));
|
ulong cycle13367 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 13367UL, MontgomeryDivisorDataPool.Shared.FromModulus(13367UL));
|
||||||
session.CheckDivisor(13367UL, MontgomeryDivisorDataPool.Shared.FromModulus(13367UL), cycle13367, primes, hits);
|
session.CheckDivisor(13367UL, MontgomeryDivisorDataPool.Shared.FromModulus(13367UL), cycle13367, primes).Should().BeTrue();
|
||||||
hits.Should().ContainInOrder([0, 0, 1, 0]);
|
|
||||||
|
ulong[] primesWithoutMatchingExponent = [31UL, 37UL, 43UL];
|
||||||
|
session.CheckDivisor(13367UL, MontgomeryDivisorDataPool.Shared.FromModulus(13367UL), cycle13367, primesWithoutMatchingExponent).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -288,12 +290,12 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] primes = [31UL, 37UL, 41UL, 43UL, 47UL];
|
ulong[] primes = [31UL, 37UL, 41UL, 43UL, 47UL];
|
||||||
byte[] hits = new byte[primes.Length];
|
|
||||||
|
|
||||||
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL));
|
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL));
|
||||||
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primes, hits);
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primes).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().ContainInOrder([0, 1, 0, 0, 0]);
|
ulong[] primesBeforeHit = [31UL];
|
||||||
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primesBeforeHit).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -317,14 +319,14 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] exponents = [6UL, 7UL, 9UL, 10UL, 12UL];
|
ulong[] exponents = [6UL, 7UL, 9UL, 10UL, 12UL];
|
||||||
byte[] hits = new byte[exponents.Length];
|
|
||||||
|
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(7UL);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(7UL);
|
||||||
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 7UL, divisorData);
|
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 7UL, divisorData);
|
||||||
|
|
||||||
session.CheckDivisor(7UL, divisorData, cycle, exponents, hits);
|
session.CheckDivisor(7UL, divisorData, cycle, exponents).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().Equal([1, 0, 1, 0, 1]);
|
ulong[] nonDivisibleExponents = [5UL, 11UL];
|
||||||
|
session.CheckDivisor(7UL, divisorData, cycle, nonDivisibleExponents).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -348,14 +350,14 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] exponents = [10UL, 11UL, 20UL, 21UL, 30UL];
|
ulong[] exponents = [10UL, 11UL, 20UL, 21UL, 30UL];
|
||||||
byte[] hits = new byte[exponents.Length];
|
|
||||||
|
|
||||||
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(11UL);
|
MontgomeryDivisorData divisorData = MontgomeryDivisorDataPool.Shared.FromModulus(11UL);
|
||||||
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 11UL, divisorData);
|
ulong cycle = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 11UL, divisorData);
|
||||||
|
|
||||||
session.CheckDivisor(11UL, divisorData, cycle, exponents, hits);
|
session.CheckDivisor(11UL, divisorData, cycle, exponents).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().Equal([1, 0, 1, 0, 1]);
|
ulong[] nonDivisibleExponents = [5UL, 17UL];
|
||||||
|
session.CheckDivisor(11UL, divisorData, cycle, nonDivisibleExponents).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -424,12 +426,12 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
ulong[] primes = [31UL, 37UL, 41UL, 43UL, 47UL];
|
ulong[] primes = [31UL, 37UL, 41UL, 43UL, 47UL];
|
||||||
byte[] hits = new byte[primes.Length];
|
|
||||||
|
|
||||||
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL));
|
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLengthGpu(gpu, 223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL));
|
||||||
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primes, hits);
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primes).Should().BeTrue();
|
||||||
|
|
||||||
hits.Should().ContainInOrder([0, 1, 0, 0, 0]);
|
ulong[] primesBeforeHit = [31UL];
|
||||||
|
session.CheckDivisor(223UL, MontgomeryDivisorDataPool.Shared.FromModulus(223UL), cycle223, primesBeforeHit).Should().BeFalse();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,35 +21,36 @@ internal sealed class MersenneCpuDivisorScanSession(PrimeOrderCalculatorAccelera
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckDivisor(
|
public bool CheckDivisor(
|
||||||
ulong divisor,
|
ulong divisor,
|
||||||
in MontgomeryDivisorData divisorData,
|
in MontgomeryDivisorData divisorData,
|
||||||
ulong divisorCycle,
|
ulong divisorCycle,
|
||||||
in ReadOnlySpan<ulong> primes,
|
in ReadOnlySpan<ulong> primes)
|
||||||
Span<byte> hits)
|
|
||||||
{
|
{
|
||||||
int length = primes.Length;
|
int length = primes.Length;
|
||||||
// EvenPerfectBitScanner always provides at least one exponent on this path.
|
// EvenPerfectBitScanner always provides at least one exponent on this path.
|
||||||
// Keep the guard commented out for tests that might reuse the session differently.
|
// Keep the guard commented out for tests that might reuse the session differently.
|
||||||
// if (length == 0)
|
// if (length == 0)
|
||||||
// {
|
// {
|
||||||
// return;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (divisorData.Modulus != divisor)
|
// This never kicks off in production code
|
||||||
{
|
// if (divisorData.Modulus != divisor)
|
||||||
throw new InvalidOperationException("Divisor data is for a different modulus");
|
// {
|
||||||
// cachedData = MontgomeryDivisorData.FromModulus(divisor);
|
// throw new InvalidOperationException("Divisor data is for a different modulus");
|
||||||
}
|
// // cachedData = MontgomeryDivisorData.FromModulus(divisor);
|
||||||
|
// }
|
||||||
|
|
||||||
if (divisorCycle == 0UL)
|
if (divisorCycle == 0UL)
|
||||||
{
|
{
|
||||||
divisorCycle = _getCycleLength(divisor);
|
divisorCycle = _getCycleLength(divisor);
|
||||||
if (divisorCycle == 0UL)
|
// This never kicks off in production code
|
||||||
{
|
// if (divisorCycle == 0UL)
|
||||||
// DivisorCycleCache guarantees a positive cycle for divisors greater than one.
|
// {
|
||||||
throw new InvalidOperationException($"Divisor cycle solver returned zero for divisor {divisor}.");
|
// // DivisorCycleCache guarantees a positive cycle for divisors greater than one.
|
||||||
}
|
// throw new InvalidOperationException($"Divisor cycle solver returned zero for divisor {divisor}.");
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep these remainder steppers in place so future updates continue reusing the previously computed residues.
|
// Keep these remainder steppers in place so future updates continue reusing the previously computed residues.
|
||||||
@@ -60,21 +61,26 @@ internal sealed class MersenneCpuDivisorScanSession(PrimeOrderCalculatorAccelera
|
|||||||
|
|
||||||
bool initialUnity = exponentStepper.InitializeCpuIsUnity(primes[0]);
|
bool initialUnity = exponentStepper.InitializeCpuIsUnity(primes[0]);
|
||||||
ulong remainder = cycleStepper.Initialize(primes[0]);
|
ulong remainder = cycleStepper.Initialize(primes[0]);
|
||||||
hits[0] = remainder == 0UL
|
if (remainder == 0UL && initialUnity)
|
||||||
? (initialUnity ? (byte)1 : (byte)0)
|
{
|
||||||
: (byte)0;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; i < length; i++)
|
for (int i = 1; i < length; i++)
|
||||||
{
|
{
|
||||||
remainder = cycleStepper.ComputeNext(primes[i]);
|
remainder = cycleStepper.ComputeNext(primes[i]);
|
||||||
if (remainder != 0UL)
|
if (remainder != 0UL)
|
||||||
{
|
{
|
||||||
hits[i] = 0;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
hits[i] = exponentStepper.ComputeNextIsUnity(primes[i]) ? (byte)1 : (byte)0;
|
if (exponentStepper.ComputeNextIsUnity(primes[i]))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Return()
|
public void Return()
|
||||||
|
|||||||
@@ -231,12 +231,18 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
byte step3;
|
byte step3;
|
||||||
byte step7;
|
byte step7;
|
||||||
byte step11;
|
byte step11;
|
||||||
|
byte step13;
|
||||||
|
byte step17;
|
||||||
|
byte step19;
|
||||||
|
|
||||||
byte remainder10;
|
byte remainder10;
|
||||||
byte remainder8;
|
byte remainder8;
|
||||||
byte remainder3;
|
byte remainder3;
|
||||||
byte remainder7;
|
byte remainder7;
|
||||||
byte remainder11;
|
byte remainder11;
|
||||||
|
byte remainder13;
|
||||||
|
byte remainder17;
|
||||||
|
byte remainder19;
|
||||||
|
|
||||||
if (stepHigh == 0UL && limitHigh == 0UL)
|
if (stepHigh == 0UL && limitHigh == 0UL)
|
||||||
{
|
{
|
||||||
@@ -245,6 +251,9 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
step3 = (byte)(stepLow % 3UL);
|
step3 = (byte)(stepLow % 3UL);
|
||||||
step7 = (byte)(stepLow % 7UL);
|
step7 = (byte)(stepLow % 7UL);
|
||||||
step11 = (byte)(stepLow % 11UL);
|
step11 = (byte)(stepLow % 11UL);
|
||||||
|
step13 = (byte)(stepLow % 13UL);
|
||||||
|
step17 = (byte)(stepLow % 17UL);
|
||||||
|
step19 = (byte)(stepLow % 19UL);
|
||||||
|
|
||||||
ulong maxK = allowedMax > 0UL ? (allowedMax - 1UL) / stepLow : 0UL;
|
ulong maxK = allowedMax > 0UL ? (allowedMax - 1UL) / stepLow : 0UL;
|
||||||
if (maxK == 0UL)
|
if (maxK == 0UL)
|
||||||
@@ -274,6 +283,9 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
step3,
|
step3,
|
||||||
step7,
|
step7,
|
||||||
step11,
|
step11,
|
||||||
|
step13,
|
||||||
|
step17,
|
||||||
|
step19,
|
||||||
ref currentK,
|
ref currentK,
|
||||||
out processedTop,
|
out processedTop,
|
||||||
out foundDivisor);
|
out foundDivisor);
|
||||||
@@ -302,6 +314,9 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
step3,
|
step3,
|
||||||
step7,
|
step7,
|
||||||
step11,
|
step11,
|
||||||
|
step13,
|
||||||
|
step17,
|
||||||
|
step19,
|
||||||
ref currentK,
|
ref currentK,
|
||||||
out processedBottom,
|
out processedBottom,
|
||||||
out foundDivisor);
|
out foundDivisor);
|
||||||
@@ -317,17 +332,23 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
step3 = (byte)(((stepHigh % 3UL) + (stepLow % 3UL)) % 3UL);
|
step3 = (byte)(((stepHigh % 3UL) + (stepLow % 3UL)) % 3UL);
|
||||||
step7 = (byte)((((stepHigh % 7UL) * 2UL) + (stepLow % 7UL)) % 7UL);
|
step7 = (byte)((((stepHigh % 7UL) * 2UL) + (stepLow % 7UL)) % 7UL);
|
||||||
step11 = (byte)((((stepHigh % 11UL) * 5UL) + (stepLow % 11UL)) % 11UL);
|
step11 = (byte)((((stepHigh % 11UL) * 5UL) + (stepLow % 11UL)) % 11UL);
|
||||||
|
step13 = (byte)((((stepHigh % 13UL) * 3UL) + (stepLow % 13UL)) % 13UL);
|
||||||
|
step17 = (byte)(((stepHigh % 17UL) + (stepLow % 17UL)) % 17UL);
|
||||||
|
step19 = (byte)((((stepHigh % 19UL) * 17UL) + (stepLow % 19UL)) % 19UL);
|
||||||
|
|
||||||
remainder10 = (byte)((((divisorHigh % 10UL) * 6UL) + (divisorLow % 10UL)) % 10UL);
|
remainder10 = (byte)((((divisorHigh % 10UL) * 6UL) + (divisorLow % 10UL)) % 10UL);
|
||||||
remainder8 = (byte)(divisorLow % 8UL);
|
remainder8 = (byte)(divisorLow % 8UL);
|
||||||
remainder3 = (byte)(((divisorHigh % 3UL) + (divisorLow % 3UL)) % 3UL);
|
remainder3 = (byte)(((divisorHigh % 3UL) + (divisorLow % 3UL)) % 3UL);
|
||||||
remainder7 = (byte)((((divisorHigh % 7UL) * 2UL) + (divisorLow % 7UL)) % 7UL);
|
remainder7 = (byte)((((divisorHigh % 7UL) * 2UL) + (divisorLow % 7UL)) % 7UL);
|
||||||
remainder11 = (byte)((((divisorHigh % 11UL) * 5UL) + (divisorLow % 11UL)) % 11UL);
|
remainder11 = (byte)((((divisorHigh % 11UL) * 5UL) + (divisorLow % 11UL)) % 11UL);
|
||||||
|
remainder13 = (byte)((((divisorHigh % 13UL) * 3UL) + (divisorLow % 13UL)) % 13UL);
|
||||||
|
remainder17 = (byte)(((divisorHigh % 17UL) + (divisorLow % 17UL)) % 17UL);
|
||||||
|
remainder19 = (byte)((((divisorHigh % 19UL) * 17UL) + (divisorLow % 19UL)) % 19UL);
|
||||||
|
|
||||||
var divisorPool = MontgomeryDivisorDataPool.Shared;
|
var divisorPool = MontgomeryDivisorDataPool.Shared;
|
||||||
while (divisor.CompareTo(limit) <= 0)
|
while (divisor.CompareTo(limit) <= 0)
|
||||||
{
|
{
|
||||||
bool passesSmallModuli = remainder3 != 0 && remainder7 != 0 && remainder11 != 0;
|
bool passesSmallModuli = remainder3 != 0 && remainder7 != 0 && remainder11 != 0 && remainder13 != 0 && remainder17 != 0 && remainder19 != 0;
|
||||||
if (passesSmallModuli && (remainder8 == 1 || remainder8 == 7) && ((decimalMask >> remainder10) & 1) != 0)
|
if (passesSmallModuli && (remainder8 == 1 || remainder8 == 7) && ((decimalMask >> remainder10) & 1) != 0)
|
||||||
{
|
{
|
||||||
ulong candidate = divisor.Low;
|
ulong candidate = divisor.Low;
|
||||||
@@ -379,6 +400,9 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
remainder3 = AddMod3(remainder3, step3);
|
remainder3 = AddMod3(remainder3, step3);
|
||||||
remainder7 = AddMod7(remainder7, step7);
|
remainder7 = AddMod7(remainder7, step7);
|
||||||
remainder11 = AddMod11(remainder11, step11);
|
remainder11 = AddMod11(remainder11, step11);
|
||||||
|
remainder13 = AddMod13(remainder13, step13);
|
||||||
|
remainder17 = AddMod17(remainder17, step17);
|
||||||
|
remainder19 = AddMod19(remainder19, step19);
|
||||||
}
|
}
|
||||||
|
|
||||||
processedAll = true;
|
processedAll = true;
|
||||||
@@ -399,6 +423,9 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
byte step3,
|
byte step3,
|
||||||
byte step7,
|
byte step7,
|
||||||
byte step11,
|
byte step11,
|
||||||
|
byte step13,
|
||||||
|
byte step17,
|
||||||
|
byte step19,
|
||||||
ref ulong currentK,
|
ref ulong currentK,
|
||||||
out bool processedAll,
|
out bool processedAll,
|
||||||
out ulong foundDivisor)
|
out ulong foundDivisor)
|
||||||
@@ -435,6 +462,9 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
byte remainder3 = (byte)(startDivisor % 3UL);
|
byte remainder3 = (byte)(startDivisor % 3UL);
|
||||||
byte remainder7 = (byte)(startDivisor % 7UL);
|
byte remainder7 = (byte)(startDivisor % 7UL);
|
||||||
byte remainder11 = (byte)(startDivisor % 11UL);
|
byte remainder11 = (byte)(startDivisor % 11UL);
|
||||||
|
byte remainder13 = (byte)(startDivisor % 13UL);
|
||||||
|
byte remainder17 = (byte)(startDivisor % 17UL);
|
||||||
|
byte remainder19 = (byte)(startDivisor % 19UL);
|
||||||
|
|
||||||
return CheckDivisors64(
|
return CheckDivisors64(
|
||||||
gpu,
|
gpu,
|
||||||
@@ -448,11 +478,17 @@ public sealed class MersenneNumberDivisorByDivisorCpuTester : IMersenneNumberDiv
|
|||||||
step3,
|
step3,
|
||||||
step7,
|
step7,
|
||||||
step11,
|
step11,
|
||||||
|
step13,
|
||||||
|
step17,
|
||||||
|
step19,
|
||||||
remainder10,
|
remainder10,
|
||||||
remainder8,
|
remainder8,
|
||||||
remainder3,
|
remainder3,
|
||||||
remainder7,
|
remainder7,
|
||||||
remainder11,
|
remainder11,
|
||||||
|
remainder13,
|
||||||
|
remainder17,
|
||||||
|
remainder19,
|
||||||
ref currentK,
|
ref currentK,
|
||||||
out processedAll,
|
out processedAll,
|
||||||
out foundDivisor);
|
out foundDivisor);
|
||||||
@@ -470,11 +506,17 @@ private bool CheckDivisors64(
|
|||||||
byte step3,
|
byte step3,
|
||||||
byte step7,
|
byte step7,
|
||||||
byte step11,
|
byte step11,
|
||||||
|
byte step13,
|
||||||
|
byte step17,
|
||||||
|
byte step19,
|
||||||
byte remainder10,
|
byte remainder10,
|
||||||
byte remainder8,
|
byte remainder8,
|
||||||
byte remainder3,
|
byte remainder3,
|
||||||
byte remainder7,
|
byte remainder7,
|
||||||
byte remainder11,
|
byte remainder11,
|
||||||
|
byte remainder13,
|
||||||
|
byte remainder17,
|
||||||
|
byte remainder19,
|
||||||
ref ulong currentK,
|
ref ulong currentK,
|
||||||
out bool processedAll,
|
out bool processedAll,
|
||||||
out ulong foundDivisor)
|
out ulong foundDivisor)
|
||||||
@@ -485,7 +527,7 @@ private bool CheckDivisors64(
|
|||||||
{
|
{
|
||||||
if (divisor <= limit)
|
if (divisor <= limit)
|
||||||
{
|
{
|
||||||
if (remainder3 != 0 && remainder7 != 0 && remainder11 != 0 && (remainder8 == 1 || remainder8 == 7) && ((decimalMask >> remainder10) & 1) != 0)
|
if (remainder3 != 0 && remainder7 != 0 && remainder11 != 0 && remainder13 != 0 && remainder17 != 0 && remainder19 != 0 && (remainder8 == 1 || remainder8 == 7) && ((decimalMask >> remainder10) & 1) != 0)
|
||||||
{
|
{
|
||||||
MontgomeryDivisorData divisorData = divisorPool.FromModulus(divisor);
|
MontgomeryDivisorData divisorData = divisorPool.FromModulus(divisor);
|
||||||
ulong divisorCycle;
|
ulong divisorCycle;
|
||||||
@@ -539,7 +581,7 @@ private bool CheckDivisors64(
|
|||||||
ulong remainingIterations = ((limit - divisor) / step) + 1UL;
|
ulong remainingIterations = ((limit - divisor) / step) + 1UL;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
bool passesSmallModuli = remainder3 != 0 && remainder7 != 0 && remainder11 != 0;
|
bool passesSmallModuli = remainder3 != 0 && remainder7 != 0 && remainder11 != 0 && remainder13 != 0 && remainder17 != 0 && remainder19 != 0;
|
||||||
if (passesSmallModuli && (remainder8 == 1 || remainder8 == 7) && ((decimalMask >> remainder10) & 1) != 0)
|
if (passesSmallModuli && (remainder8 == 1 || remainder8 == 7) && ((decimalMask >> remainder10) & 1) != 0)
|
||||||
{
|
{
|
||||||
MontgomeryDivisorData divisorData = divisorPool.FromModulus(divisor);
|
MontgomeryDivisorData divisorData = divisorPool.FromModulus(divisor);
|
||||||
@@ -593,6 +635,9 @@ private bool CheckDivisors64(
|
|||||||
remainder3 = AddMod3(remainder3, step3);
|
remainder3 = AddMod3(remainder3, step3);
|
||||||
remainder7 = AddMod7(remainder7, step7);
|
remainder7 = AddMod7(remainder7, step7);
|
||||||
remainder11 = AddMod11(remainder11, step11);
|
remainder11 = AddMod11(remainder11, step11);
|
||||||
|
remainder13 = AddMod13(remainder13, step13);
|
||||||
|
remainder17 = AddMod17(remainder17, step17);
|
||||||
|
remainder19 = AddMod19(remainder19, step19);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,6 +778,48 @@ private bool CheckDivisors64(
|
|||||||
return (byte)sum;
|
return (byte)sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static byte AddMod13(byte value, byte delta)
|
||||||
|
{
|
||||||
|
const int Modulus = 13;
|
||||||
|
int sum = value + delta;
|
||||||
|
|
||||||
|
if (sum >= Modulus)
|
||||||
|
{
|
||||||
|
sum -= Modulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (byte)sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static byte AddMod17(byte value, byte delta)
|
||||||
|
{
|
||||||
|
const int Modulus = 17;
|
||||||
|
int sum = value + delta;
|
||||||
|
|
||||||
|
if (sum >= Modulus)
|
||||||
|
{
|
||||||
|
sum -= Modulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (byte)sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static byte AddMod19(byte value, byte delta)
|
||||||
|
{
|
||||||
|
const int Modulus = 19;
|
||||||
|
int sum = value + delta;
|
||||||
|
|
||||||
|
if (sum >= Modulus)
|
||||||
|
{
|
||||||
|
sum -= Modulus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (byte)sum;
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static byte AddMod10(byte value, byte delta)
|
private static byte AddMod10(byte value, byte delta)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -717,13 +717,13 @@ public sealed partial class MersenneNumberDivisorByDivisorGpuTester : IMersenneN
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes, Span<byte> hits)
|
public bool CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes)
|
||||||
{
|
{
|
||||||
int length = primes.Length;
|
int length = primes.Length;
|
||||||
// EvenPerfectBitScanner always supplies at least one exponent per divisor check, so the guard stays commented out.
|
// EvenPerfectBitScanner always supplies at least one exponent per divisor check, so the guard stays commented out.
|
||||||
// if (length == 0)
|
// if (length == 0)
|
||||||
// {
|
// {
|
||||||
// return;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// The GPU divisor sessions only materialize odd moduli greater than one (q = 2kp + 1),
|
// The GPU divisor sessions only materialize odd moduli greater than one (q = 2kp + 1),
|
||||||
@@ -792,12 +792,11 @@ public sealed partial class MersenneNumberDivisorByDivisorGpuTester : IMersenneN
|
|||||||
|
|
||||||
kernel(stream, new Index1D(1), divisorView, offsetView, countView, exponentView, cycleView, hitView, firstHitView);
|
kernel(stream, new Index1D(1), divisorView, offsetView, countView, exponentView, cycleView, hitView, firstHitView);
|
||||||
|
|
||||||
Span<byte> hitSlice = hits.Slice(0, length);
|
firstHitView.CopyToCPU(stream, ref sentinel, 1);
|
||||||
ref byte hitRef = ref MemoryMarshal.GetReference(hitSlice);
|
|
||||||
hitView.CopyToCPU(stream, ref hitRef, length);
|
|
||||||
stream.Synchronize();
|
stream.Synchronize();
|
||||||
|
|
||||||
// Monitor.Exit(_lease.ExecutionLock);
|
// Monitor.Exit(_lease.ExecutionLock);
|
||||||
|
return sentinel == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Return()
|
public void Return()
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public interface IMersenneNumberDivisorByDivisorTester
|
|||||||
|
|
||||||
public interface IDivisorScanSession
|
public interface IDivisorScanSession
|
||||||
{
|
{
|
||||||
void CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes, Span<byte> hits);
|
bool CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes);
|
||||||
|
|
||||||
void Return();
|
void Return();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user