DivisorSet.BitContradiction mode added to --mersenne=bydivisor.
This commit is contained in:
1 parent
6a924f4041
commit
45e3455ff3
11 files changed
+1133
-28
No files matched your search
@@ -0,0 +1,78 @@
|
||||
using System.Numerics;
|
||||
using FluentAssertions;
|
||||
using PerfectNumbers.Core.ByDivisor;
|
||||
using Xunit;
|
||||
|
||||
namespace PerfectNumbers.Core.Tests;
|
||||
|
||||
public class BitContradictionIntegrationTests
|
||||
{
|
||||
// 2^11 - 1 = 2047 = 23 * 89
|
||||
[Fact]
|
||||
public void BitContradictionAcceptsKnownDivisorWithDecision()
|
||||
{
|
||||
BigInteger divisor = 23;
|
||||
ulong p = 11;
|
||||
bool decided = Invoke(divisor, p, out bool divides);
|
||||
decided.Should().BeTrue("small p should be decided exactly");
|
||||
divides.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BitContradictionRejectsEvenDivisorQuickly()
|
||||
{
|
||||
BigInteger divisor = 24;
|
||||
ulong p = 11;
|
||||
bool decided = Invoke(divisor, p, out bool divides);
|
||||
decided.Should().BeTrue();
|
||||
divides.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BitContradictionRejectsTooLongDivisor()
|
||||
{
|
||||
// q bit length >= p => impossible
|
||||
BigInteger divisor = (BigInteger.One << 15) + 1;
|
||||
ulong p = 11;
|
||||
bool decided = Invoke(divisor, p, out bool divides);
|
||||
decided.Should().BeTrue();
|
||||
divides.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BitContradictionRejectsNonDivisorWithDecision()
|
||||
{
|
||||
// 2^11 - 1 is not divisible by 25
|
||||
BigInteger divisor = 25;
|
||||
ulong p = 11;
|
||||
bool decided = Invoke(divisor, p, out bool divides);
|
||||
decided.Should().BeTrue("small p should be decided exactly");
|
||||
divides.Should().BeFalse();
|
||||
}
|
||||
|
||||
private static bool Invoke(BigInteger divisor, ulong p, out bool divides)
|
||||
{
|
||||
int bitLen = GetBitLength(divisor);
|
||||
Span<int> offsets = stackalloc int[bitLen];
|
||||
int count = 0;
|
||||
for (int i = 0; i < bitLen; i++)
|
||||
{
|
||||
if (((divisor >> i) & BigInteger.One) == BigInteger.One)
|
||||
{
|
||||
offsets[count++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
return BitContradictionSolver.TryCheckDivisibilityFromOneOffsets(offsets[..count], p, out divides);
|
||||
}
|
||||
|
||||
private static int GetBitLength(BigInteger value)
|
||||
{
|
||||
if (value.IsZero)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int)Math.Floor(BigInteger.Log(value, 2.0)) + 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using FluentAssertions;
|
||||
using PerfectNumbers.Core.ByDivisor;
|
||||
using Xunit;
|
||||
using static PerfectNumbers.Core.ByDivisor.BitContradictionSolver;
|
||||
|
||||
namespace PerfectNumbers.Core.Tests;
|
||||
|
||||
public class BitContradictionSolverTests
|
||||
{
|
||||
[Fact]
|
||||
public void ComputeColumnBounds_TracksForcedAndPossibleOnes()
|
||||
{
|
||||
BitState[] a = [BitState.One, BitState.Unknown];
|
||||
BitState[] q = [BitState.One, BitState.One];
|
||||
|
||||
ColumnBounds bounds = ComputeColumnBounds(a, q, 1);
|
||||
|
||||
bounds.ForcedOnes.Should().Be(1);
|
||||
bounds.PossibleOnes.Should().Be(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryPropagateCarry_FailsWhenParityUnreachable()
|
||||
{
|
||||
CarryRange carry = CarryRange.Single(0);
|
||||
|
||||
bool success = TryPropagateCarry(
|
||||
carry,
|
||||
forcedOnes: 0,
|
||||
possibleOnes: 0,
|
||||
requiredResultBit: 1,
|
||||
out CarryRange next,
|
||||
out ContradictionReason reason);
|
||||
|
||||
success.Should().BeFalse();
|
||||
reason.Should().Be(ContradictionReason.ParityUnreachable);
|
||||
next.Min.Should().Be(0);
|
||||
next.Max.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryPropagateCarry_ComputesNextCarryRange()
|
||||
{
|
||||
CarryRange carry = new(0, 1);
|
||||
|
||||
bool success = TryPropagateCarry(
|
||||
carry,
|
||||
forcedOnes: 1,
|
||||
possibleOnes: 3,
|
||||
requiredResultBit: 1,
|
||||
out CarryRange next,
|
||||
out ContradictionReason reason);
|
||||
|
||||
success.Should().BeTrue();
|
||||
reason.Should().Be(ContradictionReason.None);
|
||||
next.Min.Should().Be(0);
|
||||
next.Max.Should().Be(1);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user