Clarify modular helper invariants
This commit is contained in:
1 parent
0f51454496
commit
ea2476c749
2 files changed
+14
-9
No files matched your search
@@ -634,17 +634,19 @@ public static class UInt128Extensions
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static UInt128 AddMod(this UInt128 value, UInt128 addend, UInt128 modulus)
|
public static UInt128 AddMod(this UInt128 value, UInt128 addend, UInt128 modulus)
|
||||||
{
|
{
|
||||||
// The by-divisor CPU path never supplies moduli below 2, so this guard stays disabled.
|
// All current CPU callers (Pollard Rho and the Mersenne residue tracker) only supply moduli
|
||||||
|
// of at least three, so leave this guard documented but disabled.
|
||||||
// if (modulus <= UInt128.One)
|
// if (modulus <= UInt128.One)
|
||||||
// {
|
// {
|
||||||
// return UInt128.Zero;
|
// return UInt128.Zero;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// value and addend already lie below the modulus throughout the divisor-by-divisor CPU flow,
|
// Both operands arrive pre-reduced on these paths, letting us skip the redundant folds the old
|
||||||
// so skip the redundant reductions the old helper performed.
|
// helper performed.
|
||||||
// value %= modulus;
|
// value %= modulus;
|
||||||
// addend %= modulus;
|
// addend %= modulus;
|
||||||
// Odd moduli keep 2^delta from landing on zero, leaving this branch inactive in the scan.
|
// Pollard Rho keeps its polynomial constant inside [1, modulus - 1], and the Mersenne pow-delta
|
||||||
|
// term never hits zero for odd moduli, leaving this branch inactive outside targeted tests.
|
||||||
// if (addend == UInt128.Zero)
|
// if (addend == UInt128.Zero)
|
||||||
// {
|
// {
|
||||||
// return value;
|
// return value;
|
||||||
@@ -664,7 +666,8 @@ public static class UInt128Extensions
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static UInt128 SubtractOneMod(this UInt128 value, UInt128 modulus)
|
public static UInt128 SubtractOneMod(this UInt128 value, UInt128 modulus)
|
||||||
{
|
{
|
||||||
// The divisor scan never observes moduli below 2, so leave this guard documented but inactive.
|
// Only the Mersenne residue tracker calls this helper, and it never observes moduli below three,
|
||||||
|
// so leave this guard documented but inactive.
|
||||||
// if (modulus <= UInt128.One)
|
// if (modulus <= UInt128.One)
|
||||||
// {
|
// {
|
||||||
// return UInt128.Zero;
|
// return UInt128.Zero;
|
||||||
@@ -672,6 +675,7 @@ public static class UInt128Extensions
|
|||||||
|
|
||||||
if (value == UInt128.Zero)
|
if (value == UInt128.Zero)
|
||||||
{
|
{
|
||||||
|
// Wrapping occurs when the prior AddMod call produced one, so step back to modulus - 1.
|
||||||
return modulus - UInt128.One;
|
return modulus - UInt128.One;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -458,13 +458,14 @@ public static partial class ULongExtensions
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ulong AddMod64(this ulong value, ulong addend, ulong modulus)
|
public static ulong AddMod64(this ulong value, ulong addend, ulong modulus)
|
||||||
{
|
{
|
||||||
// The CPU factoring path never presents moduli below 2, so leave this guard documented but disabled.
|
// Every CPU caller (Pollard Rho and the ModPow64 ladder) supplies moduli of at least three, so leave this guard
|
||||||
|
// documented but disabled.
|
||||||
// if (modulus <= 1UL)
|
// if (modulus <= 1UL)
|
||||||
// {
|
// {
|
||||||
// return 0UL;
|
// return 0UL;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// The Pollard Rho walks keep both operands below the modulus, so skip re-folding them here.
|
// Both flows keep their operands below the modulus ahead of time, letting us skip the re-fold the old helper performed.
|
||||||
UInt128 sum = (UInt128)value + addend;
|
UInt128 sum = (UInt128)value + addend;
|
||||||
if (sum < modulus)
|
if (sum < modulus)
|
||||||
{
|
{
|
||||||
@@ -484,7 +485,7 @@ public static partial class ULongExtensions
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private static ulong FoldMontgomery(ulong value, ulong modulus)
|
private static ulong FoldMontgomery(ulong value, ulong modulus)
|
||||||
{
|
{
|
||||||
// Moduli in the divisor scan always exceed 1, so retain the documentation and skip the runtime guard.
|
// Pollard Rho and ModPow64 both feed moduli of at least three, so retain the documentation and skip the runtime guard.
|
||||||
// if (modulus <= 1UL)
|
// if (modulus <= 1UL)
|
||||||
// {
|
// {
|
||||||
// return 0UL;
|
// return 0UL;
|
||||||
@@ -513,7 +514,7 @@ public static partial class ULongExtensions
|
|||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static ulong ModPow64(this ulong value, ulong exponent, ulong modulus)
|
public static ulong ModPow64(this ulong value, ulong exponent, ulong modulus)
|
||||||
{
|
{
|
||||||
// Moduli below 2 do not occur in the even-perfect divisor scans, so keep the guard commented for clarity.
|
// Pollard Rho and the Mersenne testers never pass moduli below two, so keep the guard commented for clarity.
|
||||||
// if (modulus <= 1UL)
|
// if (modulus <= 1UL)
|
||||||
// {
|
// {
|
||||||
// return 0UL;
|
// return 0UL;
|
||||||
|
|||||||
Reference in new issue
Block a user