Implement UInt128 exponentiation and apply in Mersenne scan
This commit is contained in:
1 parent
9eb50bee3b
commit
01277832e6
3 files changed
+63
-9
No files matched your search
@@ -112,6 +112,40 @@ public class UInt128ExtensionsTests
|
|||||||
mod3.Should().Be(expected3);
|
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]
|
[Theory]
|
||||||
[Trait("Category", "Fast")]
|
[Trait("Category", "Fast")]
|
||||||
[InlineData(2UL, 10UL, 17UL)]
|
[InlineData(2UL, 10UL, 17UL)]
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ public sealed class MersenneNumberTester(
|
|||||||
bool prePrime = true;
|
bool prePrime = true;
|
||||||
UInt128 twoP = (UInt128)exponent << 1; // 2 * p
|
UInt128 twoP = (UInt128)exponent << 1; // 2 * p
|
||||||
// UInt128 maxDivisor = new(ulong.MaxValue, ulong.MaxValue);
|
// 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;
|
bool lastIsSeven = (exponent & 3UL) == 3UL;
|
||||||
|
|
||||||
// This is how maxK was for residue test before changes UInt128 maxK = maxKOverride ?? ResidueMaxK;
|
// This is how maxK was for residue test before changes UInt128 maxK = maxKOverride ?? ResidueMaxK;
|
||||||
|
|||||||
@@ -150,15 +150,35 @@ public static class UInt128Extensions
|
|||||||
high >>= 64;
|
high >>= 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
mod10 = result % 10UL;
|
mod10 = result % 10UL;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static UInt128 ModPow(this UInt128 value, UInt128 exponent, UInt128 modulus)
|
public static UInt128 Pow(this UInt128 value, ulong exponent)
|
||||||
{
|
{
|
||||||
UInt128 result, one = result = UInt128.One,
|
UInt128 result = UInt128.One;
|
||||||
zero = UInt128.Zero,
|
UInt128 baseValue = value;
|
||||||
baseValue = value % modulus;
|
|
||||||
|
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)
|
while (exponent != zero)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user