Renaming isPerfect to passedAllTests variables and parameters

This commit is contained in:
Marek Lemańczyk committed 2025-09-19 20:11:48 +02:00
1 parent e3f2cf1f2c
commit 3a3da488b0
2 files changed
+168 -161

No files matched your search

+152 -145
View File
@@ -19,149 +19,153 @@ internal static class Program
"/help" "/help"
}; };
private const string DefaultHeader = "p,searchedMersenne,detailedCheck,isPerfect"; private const string DefaultHeader = "p,searchedMersenne,detailedCheck,passedAllTests";
private static int Main(string[] args) private static int Main(string[] args)
{ {
if (args.Length == 0) if (args.Length == 0)
{ {
PrintHelp(); PrintHelp();
return 1; return 1;
} }
if (args.Length == 1 && IsHelpOption(args[0])) if (args.Length == 1 && IsHelpOption(args[0]))
{ {
PrintHelp(); PrintHelp();
return 0; return 0;
} }
string inputPath = args[0]; string inputPath = args[0];
if (IsHelpOption(inputPath)) if (IsHelpOption(inputPath))
{ {
PrintHelp(); PrintHelp();
return 0; return 0;
} }
if (!File.Exists(inputPath)) if (!File.Exists(inputPath))
{ {
Console.Error.WriteLine($"Input file '{inputPath}' was not found."); Console.Error.WriteLine($"Input file '{inputPath}' was not found.");
return 1; return 1;
} }
if (!TryParseRangeArguments(args.AsSpan(1), out ulong pMin, out ulong pMax)) if (!TryParseRangeArguments(args.AsSpan(1), out ulong pMin, out ulong pMax))
{ {
return 1; return 1;
} }
if (pMin > pMax) if (pMin > pMax)
{ {
Console.Error.WriteLine("The --p-min value cannot be greater than --p-max."); Console.Error.WriteLine("The --p-min value cannot be greater than --p-max.");
return 1; return 1;
} }
try try
{ {
ProcessFile(inputPath, pMin, pMax); ProcessFile(inputPath, pMin, pMax);
return 0; return 0;
} }
catch (Exception exception) catch (Exception exception)
{ {
Console.Error.WriteLine($"Processing failed: {exception.Message}"); Console.Error.WriteLine($"Processing failed: {exception.Message}");
return 1; return 1;
} }
} }
private static bool IsHelpOption(string value) => HelpOptions.Contains(value); private static bool IsHelpOption(string value) => HelpOptions.Contains(value);
private static bool TryParseRangeArguments(ReadOnlySpan<string> arguments, out ulong pMin, out ulong pMax) private static bool TryParseRangeArguments(ReadOnlySpan<string> arguments, out ulong pMin, out ulong pMax)
{ {
pMin = 0UL; pMin = 0UL;
pMax = ulong.MaxValue; pMax = ulong.MaxValue;
if (arguments.Length == 0) if (arguments.Length == 0)
{ {
return true; return true;
} }
if ((arguments.Length & 1) == 1) if ((arguments.Length & 1) == 1)
{ {
Console.Error.WriteLine("Each range option must be followed by a numeric value."); Console.Error.WriteLine("Each range option must be followed by a numeric value.");
PrintHelp(); PrintHelp();
return false; return false;
} }
for (int i = 0; i < arguments.Length; i += 2) int index;
{ string option, optionAndValue, value;
string option = arguments[i]; for (int i = 0; i < arguments.Length; i += 2)
string value = arguments[i + 1]; {
optionAndValue = arguments[i];
index = optionAndValue.IndexOf('=');
option = optionAndValue[..index];
value = optionAndValue[(index + 1)..];
try try
{ {
switch (option) switch (option)
{ {
case "--p-min": case "--p-min":
pMin = ParseRangeValue(option, value); pMin = ParseRangeValue(option, value);
break; break;
case "--p-max": case "--p-max":
pMax = ParseRangeValue(option, value); pMax = ParseRangeValue(option, value);
break; break;
default: default:
Console.Error.WriteLine($"Unsupported option '{option}'."); Console.Error.WriteLine($"Unsupported option '{option}'.");
PrintHelp(); PrintHelp();
return false; return false;
} }
} }
catch (FormatException exception) catch (FormatException exception)
{ {
Console.Error.WriteLine(exception.Message); Console.Error.WriteLine(exception.Message);
PrintHelp(); PrintHelp();
return false; return false;
} }
} }
return true; return true;
} }
private static ulong ParseRangeValue(string option, string value) private static ulong ParseRangeValue(string option, string value)
{ {
if (!ulong.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong parsed)) if (!ulong.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong parsed))
{ {
throw new FormatException($"Value '{value}' for option '{option}' is not a valid non-negative integer."); throw new FormatException($"Value '{value}' for option '{option}' is not a valid non-negative integer.");
} }
return parsed; return parsed;
} }
private static void PrintHelp() private static void PrintHelp()
{ {
Console.WriteLine("EvenPerfectBitScanner.ResultsParser"); Console.WriteLine("EvenPerfectBitScanner.ResultsParser");
Console.WriteLine("Parses CSV results produced by the candidate scanner."); Console.WriteLine("Parses CSV results produced by the candidate scanner.");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Usage:"); Console.WriteLine("Usage:");
Console.WriteLine(" EvenPerfectBitScanner.ResultsParser <results.csv> [--p-min <value>] [--p-max <value>]"); Console.WriteLine(" EvenPerfectBitScanner.ResultsParser <results.csv> [--p-min <value>] [--p-max <value>]");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("The program accepts the following help switches:"); Console.WriteLine("The program accepts the following help switches:");
Console.WriteLine(" --?, -?, /?, -help, --help, --h, -h, /h, /help"); Console.WriteLine(" --?, -?, /?, -help, --help, --h, -h, /h, /help");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Optional range arguments allow filtering primes by exponent:"); Console.WriteLine("Optional range arguments allow filtering primes by exponent:");
Console.WriteLine(" --p-min <value> - include entries with p >= value"); Console.WriteLine(" --p-min <value> - include entries with p >= value");
Console.WriteLine(" --p-max <value> - include entries with p <= value"); Console.WriteLine(" --p-max <value> - include entries with p <= value");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Outputs prime results into four files placed next to the source file:"); Console.WriteLine("Outputs prime results into four files placed next to the source file:");
Console.WriteLine(" raw-primes-<name> - prime entries in the original order"); Console.WriteLine(" raw-primes-<name> - prime entries in the original order");
Console.WriteLine(" sorted-primes-<name> - prime entries sorted by p"); Console.WriteLine(" sorted-primes-<name> - prime entries sorted by p");
Console.WriteLine(" sorted-primes-passed-<name> - sorted prime entries with isPerfect = true"); Console.WriteLine(" sorted-primes-passed-<name> - sorted prime entries with passedAllTests = true");
Console.WriteLine(" sorted-primes-rejected-<name> - sorted prime entries with isPerfect = false"); Console.WriteLine(" sorted-primes-rejected-<name> - sorted prime entries with passedAllTests = false");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Example:"); Console.WriteLine("Example:");
Console.WriteLine(" EvenPerfectBitScanner.ResultsParser results.csv --p-min 89 --p-max 107"); Console.WriteLine(" EvenPerfectBitScanner.ResultsParser results.csv --p-min 89 --p-max 107");
} }
private static void ProcessFile(string inputPath, ulong pMin, ulong pMax) private static void ProcessFile(string inputPath, ulong pMin, ulong pMax)
{ {
using IEnumerator<string> enumerator = File.ReadLines(inputPath).GetEnumerator(); using IEnumerator<string> enumerator = File.ReadLines(inputPath).GetEnumerator();
if (!enumerator.MoveNext()) if (!enumerator.MoveNext())
{ {
Console.WriteLine("Input file did not contain any data. Created empty outputs using the default header."); Console.WriteLine("Input file did not contain any data. Created empty outputs using the default header.");
string fallbackHeader = DefaultHeader; string fallbackHeader = DefaultHeader;
string rawFallbackPath = BuildOutputPath(inputPath, "raw-primes-"); string rawFallbackPath = BuildOutputPath(inputPath, "raw-primes-");
WriteCsv(rawFallbackPath, fallbackHeader, Array.Empty<CandidateResult>()); WriteCsv(rawFallbackPath, fallbackHeader, Array.Empty<CandidateResult>());
@@ -182,25 +186,25 @@ internal static class Program
List<CandidateResult> pendingResults = new(); List<CandidateResult> pendingResults = new();
List<CandidateResult> primeResults = new(); List<CandidateResult> primeResults = new();
int consoleProgress = 0; int consoleProgress = 0;
while (enumerator.MoveNext()) while (enumerator.MoveNext())
{ {
string currentLine = enumerator.Current; string currentLine = enumerator.Current;
if (string.IsNullOrWhiteSpace(currentLine)) if (string.IsNullOrWhiteSpace(currentLine))
{ {
continue; continue;
} }
CandidateResult result = ParseLine(currentLine); CandidateResult result = ParseLine(currentLine);
if (result.P < pMin || result.P > pMax) if (result.P < pMin || result.P > pMax)
{ {
continue; continue;
} }
InsertPendingResult(pendingResults, result); InsertPendingResult(pendingResults, result);
DrainPrimeMatches(pendingResults, primeResults, ref currentPrime, primeEnumerator, false); DrainPrimeMatches(pendingResults, primeResults, ref currentPrime, primeEnumerator, false);
if (++consoleProgress == 10_000) if (++consoleProgress == 10_000)
{ {
Console.WriteLine($"Processed {result.P}"); Console.WriteLine($"Processed {result.P}");
consoleProgress = 0; consoleProgress = 0;
} }
} }
@@ -219,15 +223,17 @@ internal static class Program
} }
List<CandidateResult> sortedResults = [.. primeResults]; List<CandidateResult> sortedResults = [.. primeResults];
Console.WriteLine("Sorting candidates...");
BubbleSort(sortedResults); BubbleSort(sortedResults);
List<CandidateResult> passedResults = []; Console.WriteLine("Splitting results...");
List<CandidateResult> rejectedResults = []; List<CandidateResult> passedResults = new(sortedResults.Count);
List<CandidateResult> rejectedResults = new(sortedResults.Count);
for (int i = 0; i < sortedResults.Count; i++) for (int i = 0; i < sortedResults.Count; i++)
{ {
CandidateResult candidate = sortedResults[i]; CandidateResult candidate = sortedResults[i];
if (candidate.IsPerfect) if (candidate.PassedAllTests)
{ {
passedResults.Add(candidate); passedResults.Add(candidate);
} }
@@ -237,6 +243,7 @@ internal static class Program
} }
} }
Console.WriteLine("Saving files...");
string sortedOutputPath = BuildOutputPath(inputPath, "sorted-primes-"); string sortedOutputPath = BuildOutputPath(inputPath, "sorted-primes-");
string passedOutputPath = BuildOutputPath(inputPath, "sorted-primes-passed-"); string passedOutputPath = BuildOutputPath(inputPath, "sorted-primes-passed-");
string rejectedOutputPath = BuildOutputPath(inputPath, "sorted-primes-rejected-"); string rejectedOutputPath = BuildOutputPath(inputPath, "sorted-primes-rejected-");
@@ -276,10 +283,10 @@ internal static class Program
} }
ReadOnlySpan<char> pSpan = span[..firstCommaIndex]; ReadOnlySpan<char> pSpan = span[..firstCommaIndex];
ReadOnlySpan<char> isPerfectSpan = span[(lastCommaIndex + 1)..]; ReadOnlySpan<char> passedAllTestsSpan = span[(lastCommaIndex + 1)..];
ulong p = ulong.Parse(pSpan, NumberStyles.Integer, CultureInfo.InvariantCulture); ulong p = ulong.Parse(pSpan, NumberStyles.Integer, CultureInfo.InvariantCulture);
bool isPerfect = bool.Parse(isPerfectSpan); bool passedAllTests = bool.Parse(passedAllTestsSpan);
return new CandidateResult(p, isPerfect, trimmedLine); return new CandidateResult(p, passedAllTests, trimmedLine);
} }
private static string BuildOutputPath(string inputPath, string prefix) private static string BuildOutputPath(string inputPath, string prefix)
@@ -475,13 +482,13 @@ internal static class Program
return low; return low;
} }
private readonly record struct CandidateResult(ulong P, bool IsPerfect, string Csv) private readonly record struct CandidateResult(ulong P, bool PassedAllTests, string Csv)
{ {
public string ToCsv() => Csv; public string ToCsv() => Csv;
public readonly string Csv = Csv; public readonly string Csv = Csv;
public readonly ulong P = P; public readonly ulong P = P;
public readonly bool IsPerfect = IsPerfect; public readonly bool PassedAllTests = PassedAllTests;
} }
} }
+16 -16
View File
@@ -476,7 +476,7 @@ internal static class Program
ulong remainder = currentP % 6UL; ulong remainder = currentP % 6UL;
if (currentP == InitialP && string.IsNullOrEmpty(filterFile)) if (currentP == InitialP && string.IsNullOrEmpty(filterFile))
{ {
// bool isPerfect = IsEvenPerfectCandidate(InitialP, out bool searchedMersenne, out bool detailedCheck); // bool passedAllTests = IsEvenPerfectCandidate(InitialP, out bool searchedMersenne, out bool detailedCheck);
// Skip the already processed range below 138 million // Skip the already processed range below 138 million
while (currentP < 138_000_000UL && !Volatile.Read(ref _limitReached)) while (currentP < 138_000_000UL && !Volatile.Read(ref _limitReached))
{ {
@@ -527,9 +527,9 @@ internal static class Program
if (File.Exists(ResultsFileName)) if (File.Exists(ResultsFileName))
{ {
Console.WriteLine("Processing previous results..."); Console.WriteLine("Processing previous results...");
LoadResultsFile(ResultsFileName, (p, detailedCheck, isPerfect) => LoadResultsFile(ResultsFileName, (p, detailedCheck, passedAllTests) =>
{ {
if (detailedCheck && isPerfect) if (detailedCheck && passedAllTests)
{ {
_primeCount++; _primeCount++;
} }
@@ -546,9 +546,9 @@ internal static class Program
if (useFilter) if (useFilter)
{ {
Console.WriteLine("Loading filter..."); Console.WriteLine("Loading filter...");
LoadResultsFile(filterFile, (p, detailedCheck, isPerfect) => LoadResultsFile(filterFile, (p, detailedCheck, passedAllTests) =>
{ {
if (isPerfect) if (passedAllTests)
{ {
Console.WriteLine($"Adding {p}"); Console.WriteLine($"Adding {p}");
filter.Add(p); filter.Add(p);
@@ -597,7 +597,7 @@ internal static class Program
{ {
int count, j; int count, j;
ulong p; ulong p;
bool isPerfect, searchedMersenne, detailedCheck; bool passedAllTests, searchedMersenne, detailedCheck;
ulong[] buffer = new ulong[blockSize]; ulong[] buffer = new ulong[blockSize];
while (!Volatile.Read(ref _limitReached)) while (!Volatile.Read(ref _limitReached))
{ {
@@ -612,8 +612,8 @@ internal static class Program
for (j = 0; j < count && !Volatile.Read(ref _limitReached); j++) for (j = 0; j < count && !Volatile.Read(ref _limitReached); j++)
{ {
p = buffer[j]; p = buffer[j];
isPerfect = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck); passedAllTests = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck);
PrintResult(p, searchedMersenne, detailedCheck, isPerfect); PrintResult(p, searchedMersenne, detailedCheck, passedAllTests);
} }
} }
else else
@@ -630,8 +630,8 @@ internal static class Program
Console.WriteLine($"Testing {p}"); Console.WriteLine($"Testing {p}");
} }
isPerfect = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck); passedAllTests = IsEvenPerfectCandidate(p, divisorCyclesSearchLimit, out searchedMersenne, out detailedCheck);
PrintResult(p, searchedMersenne, detailedCheck, isPerfect); PrintResult(p, searchedMersenne, detailedCheck, passedAllTests);
if (p == maxP) if (p == maxP)
{ {
Volatile.Write(ref _limitReached, true); Volatile.Write(ref _limitReached, true);
@@ -690,11 +690,11 @@ internal static class Program
} }
ReadOnlySpan<char> detailedSpan = span[..third]; ReadOnlySpan<char> detailedSpan = span[..third];
ReadOnlySpan<char> perfectSpan = span[(third + 1)..]; ReadOnlySpan<char> passedAllTestsSpan = span[(third + 1)..];
if (bool.TryParse(detailedSpan, out bool detailed) && bool.TryParse(perfectSpan, out bool isPerfect)) if (bool.TryParse(detailedSpan, out bool detailed) && bool.TryParse(passedAllTestsSpan, out bool passedAllTests))
{ {
lineProcessorAction(p, detailed, isPerfect); lineProcessorAction(p, detailed, passedAllTests);
} }
} }
} }
@@ -790,9 +790,9 @@ internal static class Program
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void PrintResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool isPerfect) private static void PrintResult(ulong currentP, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
{ {
if (isPerfect) if (passedAllTests)
{ {
int newCount = Interlocked.Increment(ref _primeCount); int newCount = Interlocked.Increment(ref _primeCount);
if (newCount >= 2) if (newCount >= 2)
@@ -813,7 +813,7 @@ internal static class Program
.Append(currentP).Append(',') .Append(currentP).Append(',')
.Append(searchedMersenne).Append(',') .Append(searchedMersenne).Append(',')
.Append(detailedCheck).Append(',') .Append(detailedCheck).Append(',')
.Append(isPerfect).Append('\n'); .Append(passedAllTests).Append('\n');
lock (Sync) lock (Sync)
{ {