Files
even-perfect-numbers-scanner/PerfectNumbers.Core.Tests/MersenneNumberDivisorByDivisorTesterTests.cs

110 lines
3.4 KiB
C#

using System.Numerics;
using FluentAssertions;
using PerfectNumbers.Core.Gpu.Accelerators;
using Xunit;
namespace PerfectNumbers.Core.Tests;
public class MersenneNumberDivisorByDivisorTesterTests
{
[Fact]
[Trait("Category", "Fast")]
public void Run_marks_candidates_divisible_by_seven_or_eleven_as_composite()
{
var candidates = new List<ulong> { 5UL, 7UL, 11UL, 13UL };
var tester = new FakeTester();
var results = new List<(ulong Prime, bool Searched, bool Detailed, bool Passed, BigInteger Divisor)>();
int compositeMarks = 0;
int clearedMarks = 0;
MersenneNumberDivisorByDivisorTester.Run(
candidates,
tester,
previousResults: null,
startPrime: 0UL,
markComposite: () => compositeMarks++,
clearComposite: () => clearedMarks++,
printResult: (prime, searched, detailed, passed, divisor) => results.Add((prime, searched, detailed, passed, divisor)),
threadCount: 1,
primesPerTask: 2);
tester.ConfiguredMaxPrime.Should().Be(13UL);
compositeMarks.Should().Be(2);
clearedMarks.Should().Be(2);
results.Should().Equal(
new (ulong Prime, bool Searched, bool Detailed, bool Passed, BigInteger Divisor)[]
{
(5UL, true, true, true, BigInteger.Zero),
(7UL, true, true, false, new BigInteger(7)),
(11UL, true, true, false, new BigInteger(11)),
(13UL, true, true, true, BigInteger.Zero),
});
}
private sealed class FakeTester : IMersenneNumberDivisorByDivisorTester
{
public ulong ConfiguredMaxPrime { get; private set; }
public int BatchSize { get; set; }
public BigInteger MinK { get; set; }
public string? StateFilePath { get; set; }
public void ResetStateTracking()
{
}
public void ResumeFromState(in string stateFile, in BigInteger lastSavedK, in BigInteger minK)
{
}
public ulong DivisorLimit => ConfiguredMaxPrime + 100UL;
public bool IsPrime(ulong prime, out bool divisorsExhausted, out BigInteger divisor)
{
divisorsExhausted = true;
if (prime % 7UL == 0UL)
{
divisor = 7UL;
return false;
}
if (prime % 11UL == 0UL)
{
divisor = 11UL;
return false;
}
divisor = 0UL;
return true;
}
public IMersenneNumberDivisorByDivisorTester.IDivisorScanSession CreateDivisorSession(PrimeOrderCalculatorAccelerator gpu)
{
return new DummySession();
}
public void PrepareCandidates(ulong maxPrime, in ReadOnlySpan<ulong> primes, Span<ulong> allowedMaxValues)
{
ConfiguredMaxPrime = maxPrime;
for (int i = 0; i < primes.Length; i++)
{
allowedMaxValues[i] = 100UL;
}
}
private sealed class DummySession : IMersenneNumberDivisorByDivisorTester.IDivisorScanSession
{
public bool CheckDivisor(ulong divisor, in MontgomeryDivisorData divisorData, ulong divisorCycle, in ReadOnlySpan<ulong> primes)
{
throw new NotSupportedException();
}
public void Return()
{
}
}
}
}