78 lines
2.1 KiB
C#
78 lines
2.1 KiB
C#
using System;
|
|
using System.Threading;
|
|
using EvenPerfectBitScanner;
|
|
using PerfectNumbers.Core;
|
|
using Xunit;
|
|
|
|
namespace EvenPerfectBitScanner.Tests;
|
|
|
|
public class ResidueCandidateEnumerationTests
|
|
{
|
|
[Fact]
|
|
public void ModResidueTracker_does_not_flag_small_primes_as_composite()
|
|
{
|
|
var tracker = new ModResidueTracker(ResidueModel.Identity, initialNumber: 13UL, initialized: true);
|
|
var primes = PrimesGenerator.SmallPrimes;
|
|
var primesPow2 = PrimesGenerator.SmallPrimesPow2;
|
|
|
|
ulong p = 13UL;
|
|
ulong remainder = p % 6UL;
|
|
|
|
for (int i = 0; i < 2000; i++)
|
|
{
|
|
tracker.BeginMerge(p);
|
|
bool composite = false;
|
|
for (int j = 0; j < primes.Length; j++)
|
|
{
|
|
if (primesPow2[j] > p)
|
|
{
|
|
break;
|
|
}
|
|
|
|
tracker.MergeOrAppend(p, primes[j], out bool divisible);
|
|
if (divisible)
|
|
{
|
|
composite = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool isPrime = PrimeTester.IsPrimeInternal(p, CancellationToken.None);
|
|
if (isPrime && composite)
|
|
{
|
|
throw new InvalidOperationException($"Prime {p} marked as composite.");
|
|
}
|
|
|
|
p = Program.TransformPAdd(p, ref remainder);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void TransformPAdd_visits_both_prime_residue_classes()
|
|
{
|
|
ulong p = 13UL;
|
|
ulong remainder = p % 6UL;
|
|
bool sawOneModSix = false;
|
|
bool sawFiveModSix = false;
|
|
|
|
for (int i = 0; i < 256; i++)
|
|
{
|
|
ulong residue = p % 6UL;
|
|
if (residue == 1UL)
|
|
{
|
|
sawOneModSix = true;
|
|
}
|
|
else if (residue == 5UL)
|
|
{
|
|
sawFiveModSix = true;
|
|
}
|
|
|
|
p = Program.TransformPAdd(p, ref remainder);
|
|
}
|
|
|
|
Assert.True(sawOneModSix, "Sequence never produced numbers congruent to 1 mod 6.");
|
|
Assert.True(sawFiveModSix, "Sequence never produced numbers congruent to 5 mod 6.");
|
|
}
|
|
|
|
}
|