From 798ae455b13320298d3b84ab953e9d1f0731500f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Lema=C5=84czyk?= Date: Mon, 20 Oct 2025 17:03:36 +0200 Subject: [PATCH] Adjust CPU Pow2 Montgomery helper for small divisors --- PerfectNumbers.Core/ULongExtensions.Cpu.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/PerfectNumbers.Core/ULongExtensions.Cpu.cs b/PerfectNumbers.Core/ULongExtensions.Cpu.cs index 3de0b55..24e415c 100644 --- a/PerfectNumbers.Core/ULongExtensions.Cpu.cs +++ b/PerfectNumbers.Core/ULongExtensions.Cpu.cs @@ -16,12 +16,13 @@ public static partial class ULongExtensions // return keepMontgomery ? divisor.MontgomeryOne : 1UL % modulus; // } - // There is no point in having extra branch, because in real use-cases it'll barely ever hit. - // Out of all 3_358_944_545 Pow2MontgomeryModWindowedCpu calls, we hit Pow2MontgomeryModSingleBit only 772 times. - // if (exponent <= Pow2WindowFallbackThreshold) - // { - // return Pow2MontgomeryModSingleBit(exponent, divisor, keepMontgomery); - // } + // Small divisors come from the precomputed <= 4,000,000 snapshot and tiny rotation counts + // appear when cycle reductions trigger. Route both cases through the single-bit ladder so the + // CPU path avoids renting the window tables when a cheaper method is available. + if (exponent <= Pow2WindowFallbackThreshold || modulus <= (ulong)PerfectNumberConstants.MaxQForDivisorCycles) + { + return Pow2MontgomeryModSingleBit(exponent, divisor, keepMontgomery); + } int bitLength = GetPortableBitLengthCpu(exponent); int windowSize = GetWindowSizeCpu(bitLength);