Simplify Pow2Montgomery GPU executor branching

This commit is contained in:
Marek Lemańczyk committed 2025-10-22 01:17:35 +02:00
1 parent 865a88fac0
commit b08175dadf
1 file changed
+26 -23
+26 -23
View File
@@ -135,43 +135,46 @@ public static partial class ULongExtensions
{ {
ulong currentBit = (exponent >> index) & 1UL; ulong currentBit = (exponent >> index) & 1UL;
ulong squared = MontgomeryMultiply(result, result, modulus, nPrime); ulong squared = MontgomeryMultiply(result, result, modulus, nPrime);
result = currentBit == 0UL ? squared : result; bool processWindow = currentBit != 0UL;
index -= (int)(currentBit ^ 1UL);
if (currentBit == 0UL)
{
continue;
}
int windowStart = index - windowSize + 1; result = processWindow ? result : squared;
// if (windowStart < 0) index -= (int)(currentBit ^ 1UL);
int windowStartCandidate = index - windowSize + 1;
// if (windowStartCandidate < 0)
// { // {
// windowStart = 0; // windowStartCandidate = 0;
// } // }
// Clamp the negative offset without branching so the GPU loop stays divergence-free. // Clamp the negative offset without branching so the GPU loop stays divergence-free.
// This still handles windows that would otherwise extend past the most significant bit. // This still handles windows that would otherwise extend past the most significant bit.
int negativeMask = windowStart >> 31; int negativeMask = windowStartCandidate >> 31;
windowStart &= ~negativeMask; windowStartCandidate &= ~negativeMask;
windowStart = GetNextSetBitIndexGpu(exponent, windowStart); int windowStart = processWindow ? GetNextSetBitIndexGpu(exponent, windowStartCandidate) : windowStartCandidate;
int windowLength = processWindow ? index - windowStart + 1 : 0;
int windowLength = index - windowStart + 1;
for (int square = 0; square < windowLength; square++) for (int square = 0; square < windowLength; square++)
{ {
result = MontgomeryMultiply(result, result, modulus, nPrime); result = MontgomeryMultiply(result, result, modulus, nPrime);
} }
ulong mask = (1UL << windowLength) - 1UL; result = processWindow
ulong windowValue = (exponent >> windowStart) & mask; ? MontgomeryMultiply(
ulong multiplier = ComputeMontgomeryOddPowerGpu(windowValue, divisor, modulus, nPrime); result,
result = MontgomeryMultiply(result, multiplier, modulus, nPrime); ComputeMontgomeryOddPowerGpu(
(exponent >> windowStart) & ((1UL << windowLength) - 1UL),
divisor,
modulus,
nPrime),
modulus,
nPrime)
: result;
index = windowStart - 1; index = processWindow ? windowStart - 1 : index;
} }
if (!keepMontgomery) result = keepMontgomery
{ ? result
result = MontgomeryMultiply(result, 1UL, modulus, nPrime); : MontgomeryMultiply(result, 1UL, modulus, nPrime);
}
return result; return result;
} }