Allow test mode to seed by-divisor runs

This commit is contained in:
Marek Lemańczyk committed 2025-10-16 03:42:55 +02:00
1 parent 03751c27be
commit ff724732f8
1 file changed
+118 -58
+118 -58
View File
@@ -407,18 +407,17 @@ internal static class Program
} }
} }
int testPrimeCandidateLimit = 0;
if (_testMode) if (_testMode)
{ {
currentP = 31UL; currentP = 31UL;
remainder = currentP % 6UL; remainder = currentP % 6UL;
useDivisor = false;
useByDivisor = false;
useResidue = false;
useLucas = false;
filterFile = string.Empty; filterFile = string.Empty;
maxPrimeLimit = UInt128.MaxValue; maxPrimeLimit = UInt128.MaxValue;
maxPrimeConfigured = false; maxPrimeConfigured = false;
startPrimeProvided = true; startPrimeProvided = true;
testPrimeCandidateLimit = Math.Max(1, threadCount) * 3;
} }
if (useByDivisor) if (useByDivisor)
@@ -430,7 +429,7 @@ internal static class Program
_byDivisorStartPrime = 0UL; _byDivisorStartPrime = 0UL;
} }
if (useByDivisor && string.IsNullOrEmpty(filterFile)) if (useByDivisor && !_testMode && string.IsNullOrEmpty(filterFile))
{ {
Console.WriteLine("--mersenne=bydivisor requires --filter-p=<path>."); Console.WriteLine("--mersenne=bydivisor requires --filter-p=<path>.");
return; return;
@@ -654,11 +653,16 @@ internal static class Program
ulong maxP = 0UL; ulong maxP = 0UL;
ulong[] localFilter = Array.Empty<ulong>(); ulong[] localFilter = Array.Empty<ulong>();
int filterCount = 0; int filterCount = 0;
if (useFilter)
if (_useByDivisorMode)
{ {
Console.WriteLine("Loading filter..."); if (_testMode)
if (_useByDivisorMode)
{ {
byDivisorCandidates = BuildTestPrimeCandidates(testPrimeCandidateLimit);
}
else
{
Console.WriteLine("Loading filter...");
int skippedByLimit = 0; int skippedByLimit = 0;
byDivisorCandidates = LoadByDivisorCandidates(filterFile, maxPrimeLimit, maxPrimeConfigured, out skippedByLimit); byDivisorCandidates = LoadByDivisorCandidates(filterFile, maxPrimeLimit, maxPrimeConfigured, out skippedByLimit);
if (maxPrimeConfigured) if (maxPrimeConfigured)
@@ -675,63 +679,70 @@ internal static class Program
} }
} }
} }
else }
else if (useFilter)
{
Console.WriteLine("Loading filter...");
// TODO: Rent this filter buffer from ArrayPool<ulong> and reuse it across reload batches so
// we do not allocate fresh arrays while replaying large result filters.
localFilter = new ulong[1024];
filterCount = 0;
bool addedWithinLimit = false;
int skippedByLimit = 0;
LoadResultsFile(filterFile, (p, detailedCheck, passedAllTests) =>
{ {
// TODO: Rent this filter buffer from ArrayPool<ulong> and reuse it across reload batches so if (!passedAllTests)
// we do not allocate fresh arrays while replaying large result filters.
localFilter = new ulong[1024];
filterCount = 0;
bool addedWithinLimit = false;
int skippedByLimit = 0;
LoadResultsFile(filterFile, (p, detailedCheck, passedAllTests) =>
{ {
if (!passedAllTests) return;
{ }
return;
}
if (maxPrimeConfigured && (UInt128)p > maxPrimeLimit) if (maxPrimeConfigured && (UInt128)p > maxPrimeLimit)
{ {
skippedByLimit++; skippedByLimit++;
return; return;
} }
localFilter[filterCount++] = p; localFilter[filterCount++] = p;
addedWithinLimit = true; addedWithinLimit = true;
if (p > maxP) if (p > maxP)
{ {
maxP = p; maxP = p;
} }
if (filterCount == 1024) if (filterCount == 1024)
{
filter.AddRange(localFilter[..filterCount]);
filterCount = 0;
Console.WriteLine($"Added {p}");
}
});
if (filterCount > 0)
{ {
filter.AddRange(localFilter[..filterCount]); filter.AddRange(localFilter[..filterCount]);
filterCount = 0;
Console.WriteLine($"Added {p}");
}
});
if (filterCount > 0)
{
filter.AddRange(localFilter[..filterCount]);
}
if (maxPrimeConfigured)
{
if (!addedWithinLimit)
{
Console.WriteLine("No filter candidates fall within the --max-prime limit.");
return;
} }
if (maxPrimeConfigured) if (skippedByLimit > 0)
{ {
if (!addedWithinLimit) Console.WriteLine($"Skipped {skippedByLimit} filter candidate(s) above --max-prime limit.");
{
Console.WriteLine("No filter candidates fall within the --max-prime limit.");
return;
}
if (skippedByLimit > 0)
{
Console.WriteLine($"Skipped {skippedByLimit} filter candidate(s) above --max-prime limit.");
}
} }
} }
} }
if (_testMode)
{
_testTargetPrimeCount = testPrimeCandidateLimit;
}
if (_primeCount >= 2) if (_primeCount >= 2)
{ {
_primeFoundAfterInit = true; _primeFoundAfterInit = true;
@@ -744,6 +755,12 @@ internal static class Program
// Configure batch size for GPU primality sieve // Configure batch size for GPU primality sieve
PrimeTester.GpuBatchSize = gpuPrimeBatch; PrimeTester.GpuBatchSize = gpuPrimeBatch;
Stopwatch? stopwatch = null;
if (_testMode)
{
stopwatch = Stopwatch.StartNew();
}
Console.WriteLine("Starting scan..."); Console.WriteLine("Starting scan...");
if (_useByDivisorMode) if (_useByDivisorMode)
@@ -751,6 +768,12 @@ internal static class Program
RunByDivisorMode(byDivisorCandidates, threadCount); RunByDivisorMode(byDivisorCandidates, threadCount);
FlushBuffer(); FlushBuffer();
StringBuilderPool.Return(_outputBuilder!); StringBuilderPool.Return(_outputBuilder!);
if (stopwatch is not null)
{
stopwatch.Stop();
ReportTestTime(stopwatch.Elapsed);
}
return; return;
} }
@@ -767,17 +790,12 @@ internal static class Program
if (_testMode) if (_testMode)
{ {
_testTargetPrimeCount = Math.Max(1, threadCount) * 3; testPrimeCandidateLimit = Math.Max(1, threadCount) * 3;
_testTargetPrimeCount = testPrimeCandidateLimit;
} }
_state = ((long)currentP << 3) | (long)remainder; _state = ((long)currentP << 3) | (long)remainder;
Stopwatch? stopwatch = null;
if (_testMode)
{
stopwatch = Stopwatch.StartNew();
}
Task[] tasks = new Task[threadCount]; Task[] tasks = new Task[threadCount];
int taskIndex = 0; int taskIndex = 0;
@@ -866,6 +884,48 @@ internal static class Program
} }
} }
private static List<ulong> BuildTestPrimeCandidates(int targetCount)
{
if (targetCount <= 0)
{
return [];
}
List<ulong> candidates = new(targetCount);
ulong previous = 29UL;
int remaining = targetCount;
ulong nextPrime = 0UL;
while (remaining > 0)
{
try
{
nextPrime = PrimeIterator.Next(in previous);
}
catch (InvalidOperationException)
{
break;
}
if (nextPrime < 31UL)
{
previous = nextPrime;
continue;
}
candidates.Add(nextPrime);
remaining--;
previous = nextPrime;
}
if (remaining > 0)
{
Console.WriteLine("Unable to populate the requested number of test primes before reaching the 64-bit limit.");
}
return candidates;
}
private static List<ulong> LoadByDivisorCandidates(string candidateFile, UInt128 maxPrimeLimit, bool maxPrimeConfigured, out int skippedByLimit) private static List<ulong> LoadByDivisorCandidates(string candidateFile, UInt128 maxPrimeLimit, bool maxPrimeConfigured, out int skippedByLimit)
{ {
List<ulong> candidates = []; List<ulong> candidates = [];