Clarify invariants across GPU divisor helpers

This commit is contained in:
Marek Lemańczyk committed 2025-10-13 20:41:00 +02:00
1 parent bccb2f43c9
commit 6e89700f80
5 files changed
+44 -52

No files matched your search

@@ -64,28 +64,22 @@ public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDiv
public void ConfigureFromMaxPrime(ulong maxPrime)
{
lock (_sync)
{
_divisorLimit = ComputeDivisorLimitFromMaxPrime(maxPrime);
_isConfigured = true;
}
// Configuration happens once during startup, so no synchronization is required to cache the divisor limit.
_divisorLimit = ComputeDivisorLimitFromMaxPrime(maxPrime);
_isConfigured = true;
}
public bool IsPrime(ulong prime, out bool divisorsExhausted, TimeSpan? timeLimit = null)
{
ulong allowedMax;
int batchCapacity;
// The CLI always configures the tester during startup, so the historical guard is commented out to avoid branching.
// if (!_isConfigured)
// {
// throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
// }
lock (_sync)
{
if (!_isConfigured)
{
throw new InvalidOperationException("ConfigureFromMaxPrime must be called before using the tester.");
}
allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit);
batchCapacity = _gpuBatchSize;
}
// Configuration is immutable, so the cached values can be read without locking.
ulong allowedMax = ComputeAllowedMaxDivisor(prime, _divisorLimit);
int batchCapacity = _gpuBatchSize;
// The GPU path always receives an allowed maximum well above the minimal divisor, so the legacy
// guard stays commented out to document the invariant without branching.
@@ -75,7 +75,10 @@ internal sealed class MersenneNumberDivisorCandidateGpuEvaluator : IDisposable
// return;
// }
EnsureCapacity(count);
if (count > _capacity)
{
EnsureCapacity(count);
}
Span<ulong> hostCandidateSpan = _hostCandidates.AsSpan(0, count);
Span<byte> hostMaskSpan = _hostMask.AsSpan(0, count);
@@ -52,7 +52,7 @@ internal sealed class MersenneNumberDivisorRemainderGpuStepper : IDisposable
{
if (_disposed)
{
return;
throw new InvalidOperationException("MersenneNumberDivisorRemainderGpuStepper was disposed more than once.");
}
_disposed = true;
@@ -78,10 +78,11 @@ internal sealed class MersenneNumberDivisorRemainderGpuStepper : IDisposable
// return;
// }
if (remainders.Length != _length)
{
throw new ArgumentException("Remainder buffer length must match the configured length.");
}
// Production code always calls the stepper with a fixed-length table, so the historical length guard stays commented.
// if (remainders.Length != _length)
// {
// throw new ArgumentException("Remainder buffer length must match the configured length.");
// }
Span<byte> hostRemainderSpan = _hostRemainders.AsSpan(0, _length);
remainders.CopyTo(hostRemainderSpan);
@@ -33,7 +33,7 @@ internal sealed class MersenneNumberDivisorResidueGpuEvaluator : IDisposable
{
if (_disposed)
{
return;
throw new InvalidOperationException("MersenneNumberDivisorResidueGpuEvaluator was disposed more than once.");
}
_disposed = true;