Use adaptive pow2 stepping in residue stepper
This commit is contained in:
1 parent
4831fc84d1
commit
7cbc27d6c3
1 file changed
+4
-19
@@ -34,28 +34,12 @@ public class MersenneResidueStepper
|
|||||||
return State();
|
return State();
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt128 g = UInt128.One;
|
|
||||||
ulong absDelta = (ulong)Math.Abs(delta);
|
ulong absDelta = (ulong)Math.Abs(delta);
|
||||||
|
UInt128 g = absDelta.PowMod(m);
|
||||||
for (ulong i = 0; i < absDelta; i++)
|
|
||||||
{
|
|
||||||
// TODO: Replace this repeated doubling with the shared ProcessEightBitWindows helper (or cycle-aware lookup)
|
|
||||||
// once the scalar pow2mod upgrade lands; benchmarking showed the windowed ladder slashes latency for large
|
|
||||||
// deltas compared to this linear loop.
|
|
||||||
// TODO: Once divisor cycles power the residue stepper, prefer stepping by cycle lengths instead of incrementing
|
|
||||||
// one bit at a time so large jumps stay on the mandatory cycle-accelerated path.
|
|
||||||
g <<= 1;
|
|
||||||
|
|
||||||
if (g >= m)
|
|
||||||
{
|
|
||||||
g -= m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta > 0)
|
if (delta > 0)
|
||||||
{
|
{
|
||||||
// TODO: Once the scalar windowed pow2 helper lands, reroute this `%` path through it to avoid the slower
|
// Reuse the cached 2^p residue and only multiply by the adaptive pow2 step computed above.
|
||||||
// multiply-and-mod sequence measured in the legacy benchmarks.
|
|
||||||
pow2_mod = (pow2_mod * g) % m;
|
pow2_mod = (pow2_mod * g) % m;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -63,7 +47,8 @@ public class MersenneResidueStepper
|
|||||||
// Modular inverse for negative delta
|
// Modular inverse for negative delta
|
||||||
// TODO: Switch to a cached divisor-cycle remainder instead of computing a fresh modular inverse for every
|
// TODO: Switch to a cached divisor-cycle remainder instead of computing a fresh modular inverse for every
|
||||||
// backward jump; the divisor cycle benchmarks demonstrated significant savings once shared cycle data was used.
|
// backward jump; the divisor cycle benchmarks demonstrated significant savings once shared cycle data was used.
|
||||||
pow2_mod = (pow2_mod * ModInverse(g, m)) % m;
|
UInt128 inverse = ModInverse(g, m);
|
||||||
|
pow2_mod = (pow2_mod * inverse) % m;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = (ulong)((long)p + delta);
|
p = (ulong)((long)p + delta);
|
||||||
|
|||||||
Reference in new issue
Block a user