Merge pull request #4 from mlemanczyk/codex/analyze-inconsistent-results-for-evenperfectbitscanner

Implement UInt128 exponentiation and apply in Mersenne scan
This commit is contained in:
Marek Lemańczyk authored and GitHub committed 2025-09-10 01:51:48 +02:00
commit 6e678152f5
3 files changed
+63 -9

No files matched your search

@@ -112,6 +112,40 @@ public class UInt128ExtensionsTests
mod3.Should().Be(expected3);
}
[Theory]
[Trait("Category", "Fast")]
[InlineData(2UL, 0UL)]
[InlineData(2UL, 1UL)]
[InlineData(2UL, 63UL)]
[InlineData(2UL, 127UL)]
[InlineData(3UL, 5UL)]
public void Pow_matches_BigInteger(ulong value, ulong exponent)
{
UInt128 v = value;
UInt128 expected = (UInt128)BigPow(value, exponent);
v.Pow(exponent).Should().Be(expected);
}
private static BigInteger BigPow(ulong value, ulong exponent)
{
BigInteger result = BigInteger.One;
BigInteger baseValue = value;
while (exponent != 0UL)
{
if ((exponent & 1UL) != 0UL)
{
result *= baseValue;
}
baseValue *= baseValue;
exponent >>= 1;
}
return result;
}
[Theory]
[Trait("Category", "Fast")]
[InlineData(2UL, 10UL, 17UL)]
+1 -1
View File
@@ -214,7 +214,7 @@ public sealed class MersenneNumberTester(
bool prePrime = true;
UInt128 twoP = (UInt128)exponent << 1; // 2 * p
// UInt128 maxDivisor = new(ulong.MaxValue, ulong.MaxValue);
UInt128 maxK = (UInt128Numbers.Two ^ exponent) / 2 + 1;
UInt128 maxK = UInt128Numbers.Two.Pow(exponent) / 2 + 1;
bool lastIsSeven = (exponent & 3UL) == 3UL;
// This is how maxK was for residue test before changes UInt128 maxK = maxKOverride ?? ResidueMaxK;
+28 -8
View File
@@ -150,15 +150,35 @@ public static class UInt128Extensions
high >>= 64;
}
mod10 = result % 10UL;
}
mod10 = result % 10UL;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static UInt128 ModPow(this UInt128 value, UInt128 exponent, UInt128 modulus)
{
UInt128 result, one = result = UInt128.One,
zero = UInt128.Zero,
baseValue = value % modulus;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static UInt128 Pow(this UInt128 value, ulong exponent)
{
UInt128 result = UInt128.One;
UInt128 baseValue = value;
while (exponent != 0UL)
{
if ((exponent & 1UL) != 0UL)
{
result *= baseValue;
}
baseValue *= baseValue;
exponent >>= 1;
}
return result;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static UInt128 ModPow(this UInt128 value, UInt128 exponent, UInt128 modulus)
{
UInt128 result, one = result = UInt128.One,
zero = UInt128.Zero,
baseValue = value % modulus;
while (exponent != zero)
{