Support for q > 2^64 added in --mersenne=bydivisor mode

This commit is contained in:
mlemanczyk committed 2025-12-05 23:33:21 +01:00
1 parent cf5bd6bc1a
commit 86f20ed083
11 files changed
+542 -222

No files matched your search

@@ -1,4 +1,7 @@
using System;
using System.Buffers.Text;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using PerfectNumbers.Core;
@@ -93,19 +96,46 @@ internal static class CalculationResultHandler
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void HandleResult(ulong currentP, BigInteger divisor, bool searchedMersenne, bool detailedCheck, bool passedAllTests, bool lastWasComposite)
{
Span<char> divisorBuffer = stackalloc char[256];
if (!divisor.TryFormat(divisorBuffer, out int divisorChars, provider: CultureInfo.InvariantCulture))
{
string divisorString = divisor.ToString(CultureInfo.InvariantCulture);
HandleResultInternal(currentP, divisorString.AsSpan(), searchedMersenne, detailedCheck, passedAllTests, lastWasComposite);
return;
}
HandleResultInternal(currentP, divisorBuffer[..divisorChars], searchedMersenne, detailedCheck, passedAllTests, lastWasComposite);
}
internal static void HandleResult(ulong currentP, ulong divisor, bool searchedMersenne, bool detailedCheck, bool passedAllTests, bool lastWasComposite)
{
Span<char> divisorBuffer = stackalloc char[32];
if (!divisor.TryFormat(divisorBuffer, out int divisorChars, provider: CultureInfo.InvariantCulture))
{
string divisorString = divisor.ToString(CultureInfo.InvariantCulture);
HandleResultInternal(currentP, divisorString.AsSpan(), searchedMersenne, detailedCheck, passedAllTests, lastWasComposite);
return;
}
HandleResultInternal(currentP, divisorBuffer[..divisorChars], searchedMersenne, detailedCheck, passedAllTests, lastWasComposite);
}
private static void HandleResultInternal(ulong currentP, ReadOnlySpan<char> divisorText, bool searchedMersenne, bool detailedCheck, bool passedAllTests, bool lastWasComposite)
{
// Program flow ensures Initialize(...) and InitializeOutputBuffer() ran before this call. Do not add initialization guards here.
Span<byte> stackBuffer = stackalloc byte[128];
Span<byte> stackBuffer = stackalloc byte[256];
byte[]? rentedBuffer = null;
Span<byte> utf8Span = stackBuffer;
int byteCount = TryFormatResultLine(utf8Span, currentP, divisor, searchedMersenne, detailedCheck, passedAllTests);
int byteCount = TryFormatResultLine(utf8Span, currentP, divisorText, searchedMersenne, detailedCheck, passedAllTests);
if (byteCount < 0)
{
rentedBuffer = ThreadStaticPools.BytePool.Rent(256);
int minimumSize = Math.Max((divisorText.Length + 5) * 4, 256);
rentedBuffer = ThreadStaticPools.BytePool.Rent(minimumSize);
utf8Span = rentedBuffer;
byteCount = TryFormatResultLine(utf8Span, currentP, divisor, searchedMersenne, detailedCheck, passedAllTests);
byteCount = TryFormatResultLine(utf8Span, currentP, divisorText, searchedMersenne, detailedCheck, passedAllTests);
if (byteCount < 0)
{
ThreadStaticPools.BytePool.Return(rentedBuffer);
@@ -114,7 +144,7 @@ internal static class CalculationResultHandler
}
ReadOnlySpan<byte> utf8Line = utf8Span[..byteCount];
Span<char> charBuffer = stackalloc char[128];
Span<char> charBuffer = stackalloc char[256];
int charCount = Utf8Encoding.GetChars(utf8Line, charBuffer);
ReadOnlySpan<char> recordSpan = charBuffer[..charCount];
@@ -229,7 +259,7 @@ internal static class CalculationResultHandler
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int TryFormatResultLine(Span<byte> destination, ulong currentP, ulong divisor, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
private static int TryFormatResultLine(Span<byte> destination, ulong currentP, ReadOnlySpan<char> divisorText, bool searchedMersenne, bool detailedCheck, bool passedAllTests)
{
int offset = 0;
@@ -246,16 +276,14 @@ internal static class CalculationResultHandler
destination[offset++] = (byte)',';
if (!Utf8Formatter.TryFormat(divisor, destination[offset..], out written))
int divisorByteCount = Utf8Encoding.GetByteCount(divisorText);
if (offset + divisorByteCount >= destination.Length)
{
return -1;
}
offset += written;
if (offset >= destination.Length)
{
return -1;
}
divisorByteCount = Utf8Encoding.GetBytes(divisorText, destination[offset..]);
offset += divisorByteCount;
destination[offset++] = (byte)',';
+24 -6
View File
@@ -1,4 +1,5 @@
using System.Globalization;
using System.Numerics;
using PerfectNumbers.Core;
using PerfectNumbers.Core.Gpu;
@@ -50,7 +51,7 @@ internal readonly struct CliArguments
internal readonly double ZeroFractionHard;
internal readonly double ZeroFractionConjecture;
internal readonly int MaxZeroConjecture;
internal readonly ulong MinK;
internal readonly BigInteger MinK;
internal readonly int GpuRatio;
private CliArguments(
@@ -96,7 +97,7 @@ internal readonly struct CliArguments
double zeroFractionHard,
double zeroFractionConjecture,
int maxZeroConjecture,
ulong minK,
BigInteger minK,
int gpuRatio)
{
StartPrime = startPrime;
@@ -191,7 +192,7 @@ internal readonly struct CliArguments
double zeroFractionHard = -1.0;
double zeroFractionConjecture = -1.0;
int maxZeroConjecture = -1;
ulong minK = 1UL;
BigInteger minK = BigInteger.One;
int gpuRatio = PerfectNumberConstants.GpuRatio;
foreach (string argument in args)
@@ -314,14 +315,31 @@ internal readonly struct CliArguments
if (argument.StartsWith("--min-k=", StringComparison.OrdinalIgnoreCase))
{
if (Utf8CliParser.TryParseUInt64(argument.AsSpan("--min-k=".Length), out ulong parsedMinK) && parsedMinK > 0UL)
ReadOnlySpan<char> minKSpan = argument.AsSpan("--min-k=".Length);
if (Utf8CliParser.TryParseUInt64(minKSpan, out ulong parsedMinK) && parsedMinK > 0UL)
{
minK = parsedMinK;
}
else
{
Console.WriteLine("Invalid value for --min-k.");
return default;
try
{
BigInteger parsedMinKBig = BigInteger.Parse(minKSpan, CultureInfo.InvariantCulture);
if (parsedMinKBig > BigInteger.Zero)
{
minK = parsedMinKBig;
}
else
{
Console.WriteLine("Invalid value for --min-k.");
return default;
}
}
catch
{
Console.WriteLine("Invalid value for --min-k.");
return default;
}
}
continue;
+6
View File
@@ -1,6 +1,7 @@
using System.Buffers;
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using EvenPerfectBitScanner.Candidates;
using EvenPerfectBitScanner.IO;
@@ -241,6 +242,11 @@ internal static class Program
: new MersenneNumberDivisorByDivisorCpuTester(orderDevice);
_byDivisorTester.MinK = _cliArguments.MinK;
_byDivisorTester.BatchSize = scanBatchSize;
if (_byDivisorTester is MersenneNumberDivisorByDivisorGpuTester && _cliArguments.MinK > ulong.MaxValue)
{
Console.WriteLine("--min-k values above UInt64 are only supported on the CPU path for --mersenne=bydivisor.");
return;
}
}
// Load RLE blacklist (optional)