Optimize filtering strategy for previous Mersenne results

This commit is contained in:
Marek Lemańczyk committed 2025-10-09 05:28:59 +02:00
1 parent 77cc1fc280
commit e1d4bbf12d
1 file changed
+50 -23
@@ -38,34 +38,65 @@ public static class MersenneNumberDivisorByDivisorTester
if (previousResults is not null && previousResults.Count > 0) if (previousResults is not null && previousResults.Count > 0)
{ {
int recordedCount = previousResults.Count; int recordedCount = previousResults.Count;
ulong[] recordedCandidates = ArrayPool<ulong>.Shared.Rent(recordedCount); bool preferSortedMerge = recordedCount <= 4096 || (recordedCount * 4L) <= candidateCount;
try if (preferSortedMerge)
{ {
Span<ulong> recordedSpan = recordedCandidates.AsSpan(0, recordedCount); ulong[] recordedCandidates = ArrayPool<ulong>.Shared.Rent(recordedCount);
int recordedIndex = 0; try
foreach (ulong value in previousResults.Keys)
{ {
recordedSpan[recordedIndex++] = value; Span<ulong> recordedSpan = recordedCandidates.AsSpan(0, recordedCount);
int recordedIndex = 0;
foreach (ulong value in previousResults.Keys)
{
recordedSpan[recordedIndex++] = value;
}
recordedSpan.Sort();
int writeIndex = 0;
int skipIndex = 0;
for (int readIndex = 0; readIndex < candidateCount; readIndex++)
{
ulong candidate = candidateSpan[readIndex];
while (skipIndex < recordedCount && recordedSpan[skipIndex] < candidate)
{
skipIndex++;
}
if (skipIndex < recordedCount && recordedSpan[skipIndex] == candidate)
{
skippedByPreviousResults++;
skipIndex++;
continue;
}
candidateSpan[writeIndex++] = candidate;
}
if (writeIndex < candidateCount)
{
candidates.RemoveRange(writeIndex, candidateCount - writeIndex);
candidateSpan = CollectionsMarshal.AsSpan(candidates); // candidateSpan now tracks the reduced list.
candidateCount = candidateSpan.Length;
}
} }
finally
recordedSpan.Sort(); {
ArrayPool<ulong>.Shared.Return(recordedCandidates, clearArray: true);
}
}
else
{
int writeIndex = 0; int writeIndex = 0;
int skipIndex = 0;
for (int readIndex = 0; readIndex < candidateCount; readIndex++) for (int readIndex = 0; readIndex < candidateCount; readIndex++)
{ {
ulong candidate = candidateSpan[readIndex]; ulong candidate = candidateSpan[readIndex];
while (skipIndex < recordedCount && recordedSpan[skipIndex] < candidate) if (previousResults.ContainsKey(candidate))
{
skipIndex++;
}
if (skipIndex < recordedCount && recordedSpan[skipIndex] == candidate)
{ {
skippedByPreviousResults++; skippedByPreviousResults++;
skipIndex++;
continue; continue;
} }
@@ -75,14 +106,10 @@ public static class MersenneNumberDivisorByDivisorTester
if (writeIndex < candidateCount) if (writeIndex < candidateCount)
{ {
candidates.RemoveRange(writeIndex, candidateCount - writeIndex); candidates.RemoveRange(writeIndex, candidateCount - writeIndex);
candidateSpan = CollectionsMarshal.AsSpan(candidates); candidateSpan = CollectionsMarshal.AsSpan(candidates); // candidateSpan now tracks the reduced list.
candidateCount = candidateSpan.Length; candidateCount = candidateSpan.Length;
} }
} }
finally
{
ArrayPool<ulong>.Shared.Return(recordedCandidates, clearArray: true);
}
} }
if (skippedByPreviousResults > 0) if (skippedByPreviousResults > 0)