Pow2MontgomeryModWindowedConvertToStandardCpu usages replaced with a comparison to MontgomeryOne avoiding unnecessary conversions. Results updated.
This commit is contained in:
1 parent
3f59cdc14b
commit
6b80e31e6c
7 files changed
+57
-34
No files matched your search
@@ -141,6 +141,12 @@ public static class Pow2MontgomeryKernels
|
||||
return Pow2MontgomeryModWindowedGpuMontgomeryResult(divisor, exponent);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong Pow2MontgomeryModWindowedGpuKeepMontgomery(this MontgomeryDivisorDataGpu divisor, ulong exponent)
|
||||
{
|
||||
return Pow2MontgomeryModWindowedGpuMontgomeryResult(divisor, exponent);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong Pow2MontgomeryModWindowedGpuConvertToStandard(this MontgomeryDivisorDataGpu divisor, ulong exponent)
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ internal static partial class PrimeOrderKernels
|
||||
}
|
||||
|
||||
// ulong candidate = order / primeFactor;
|
||||
if (divisorData.Pow2MontgomeryModWindowedGpuConvertToStandard(candidate) == 1UL)
|
||||
if (divisorData.Pow2MontgomeryModWindowedGpuKeepMontgomery(candidate) == divisorData.MontgomeryOne)
|
||||
{
|
||||
order = candidate;
|
||||
continue;
|
||||
@@ -395,7 +395,7 @@ internal static partial class PrimeOrderKernels
|
||||
}
|
||||
|
||||
ulong reduced = phi / factor;
|
||||
if (divisor.Pow2MontgomeryModWindowedGpuConvertToStandard(reduced) == 1UL)
|
||||
if (divisor.Pow2MontgomeryModWindowedGpuKeepMontgomery(reduced) == divisor.MontgomeryOne)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1179,7 +1179,7 @@ internal static partial class PrimeOrderKernels
|
||||
|
||||
private static bool Pow2EqualsOneKernel(ulong exponent, in MontgomeryDivisorDataGpu divisor)
|
||||
{
|
||||
return divisor.Pow2MontgomeryModWindowedGpuConvertToStandard(exponent) == 1UL;
|
||||
return divisor.Pow2MontgomeryModWindowedGpuKeepMontgomery(exponent) == divisor.MontgomeryOne;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
|
||||
|
||||
@@ -99,7 +99,7 @@ public struct MersenneDivisorCyclesTemplate
|
||||
return cycleLength == exponent;
|
||||
}
|
||||
|
||||
return exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
||||
return exponent.Pow2MontgomeryModWindowedKeepMontgomeryCpu(divisorData) == divisorData.MontgomeryOne;
|
||||
}
|
||||
|
||||
public static bool CycleEqualsExponentForMersenneCandidate(ulong divisor, in MontgomeryDivisorData divisorData, ulong exponent)
|
||||
@@ -125,7 +125,7 @@ public struct MersenneDivisorCyclesTemplate
|
||||
}
|
||||
}
|
||||
|
||||
return exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
||||
return exponent.Pow2MontgomeryModWindowedKeepMontgomeryCpu(divisorData) == divisorData.MontgomeryOne;
|
||||
}
|
||||
|
||||
private static bool IsValidMersenneDivisorCandidate(ulong divisor, ulong exponent)
|
||||
|
||||
@@ -938,7 +938,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
ulong candidate = order - primeFactor * remainder;
|
||||
// ulong candidate = order / primeFactor;
|
||||
|
||||
if (candidate.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL)
|
||||
if (candidate.Pow2MontgomeryModWindowedKeepMontgomeryCpu(divisorData) == divisorData.MontgomeryOne)
|
||||
{
|
||||
order = candidate;
|
||||
continue;
|
||||
@@ -1674,7 +1674,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static bool Pow2EqualsOne(ulong exponent, in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
return exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
||||
return exponent.Pow2MontgomeryModWindowedKeepMontgomeryCpu(divisorData) == divisorData.MontgomeryOne;
|
||||
}
|
||||
|
||||
#if DEVICE_HYBRID || DEVICE_GPU
|
||||
@@ -1685,7 +1685,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
// TODO: swap to GPU pow2 when available; fallback to CPU for now.
|
||||
return exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
||||
return exponent.Pow2MontgomeryModWindowedKeepMontgomeryCpu(divisorData) == divisorData.MontgomeryOne;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
@@ -1695,7 +1695,7 @@ public static partial class PrimeOrderCalculatorTemplate
|
||||
ulong prime,
|
||||
in MontgomeryDivisorData divisorData)
|
||||
{
|
||||
return exponent.Pow2MontgomeryModWindowedConvertToStandardCpu(divisorData) == 1UL;
|
||||
return exponent.Pow2MontgomeryModWindowedKeepMontgomeryCpu(divisorData) == divisorData.MontgomeryOne;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ public static partial class ULongExtensions
|
||||
// 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)
|
||||
if (exponent <= Pow2WindowFallbackThreshold || modulus <= PerfectNumberConstants.MaxQForDivisorCycles)
|
||||
{
|
||||
return Pow2MontgomeryModSingleBitKeepMontgomery(exponent, divisor);
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public static partial class ULongExtensions
|
||||
// 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)
|
||||
if (exponent <= Pow2WindowFallbackThreshold || modulus <= PerfectNumberConstants.MaxQForDivisorCycles)
|
||||
{
|
||||
return Pow2MontgomeryModSingleBitConvertToStandard(exponent, divisor);
|
||||
}
|
||||
@@ -274,7 +274,7 @@ public static partial class ULongExtensions
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static bool AdvanceMersenneDivisorCycleStepCpu(ref ulong pow, ulong divisor, ref ulong order)
|
||||
{
|
||||
pow += pow;
|
||||
|
||||
@@ -390,7 +390,7 @@ public static partial class ULongExtensions
|
||||
return value.BinaryGcd(exponentLog) > 1UL;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong BinaryGcd(this ulong a, ulong b)
|
||||
{
|
||||
if (a == 0UL)
|
||||
@@ -423,7 +423,7 @@ public static partial class ULongExtensions
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static ulong Select(ulong left, ulong right, bool useRight)
|
||||
{
|
||||
ulong mask = useRight ? ulong.MaxValue : 0UL;
|
||||
@@ -432,7 +432,7 @@ public static partial class ULongExtensions
|
||||
|
||||
// Benchmarks (Mod5ULongBenchmarks) show the direct `% 5` is still cheaper (~0.26 ns vs 0.43 ns), so keep the modulo until a faster lookup is proven.
|
||||
// (Mod8/Mod10 stay masked because they win; Mod5 currently does not.)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static byte Mod10(this ulong value) => (byte)(value % 5UL) switch
|
||||
{
|
||||
0 => 0,
|
||||
@@ -446,7 +446,7 @@ public static partial class ULongExtensions
|
||||
public static ulong Mod128(this ulong value) => value & 127UL;
|
||||
|
||||
// Benchmarks confirm `%` beats our current Mod5/Mod3 helpers for 64-bit inputs, so leave these modulo operations in place until a superior lookup is available.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Mod10_8_5_3(this ulong value, out ulong mod10, out ulong mod8, out ulong mod5, out ulong mod3)
|
||||
{
|
||||
mod8 = value & 7UL;
|
||||
@@ -474,7 +474,7 @@ public static partial class ULongExtensions
|
||||
}
|
||||
|
||||
// Mod5/Mod3 lookup tables are currently slower on 64-bit operands; keep the direct modulo until benchmarks flip.
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void Mod10_8_5_3Steps(this ulong value, out ulong step10, out ulong step8, out ulong step5, out ulong step3)
|
||||
{
|
||||
ulong mod8 = value & 7UL;
|
||||
@@ -520,16 +520,16 @@ public static partial class ULongExtensions
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static UInt128 Mul64(this ulong a, ulong b) => ((UInt128)a.MulHighCpu(b) << 64) | (UInt128)(a * b);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong MulHighCpu(this ulong x, ulong y)
|
||||
{
|
||||
return (ulong)(((UInt128)x * y) >> 64);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong MulHighGpu(this ulong x, ulong y)
|
||||
{
|
||||
// Retain this manual decomposition for GPU-style arithmetic so callers staging accelerator work
|
||||
@@ -553,7 +553,7 @@ public static partial class ULongExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong AddMod64(this ulong value, ulong addend, ulong modulus)
|
||||
{
|
||||
// Every CPU caller (Pollard Rho and the ModPow64 ladder) supplies moduli of at least three, so leave this guard
|
||||
@@ -580,7 +580,7 @@ public static partial class ULongExtensions
|
||||
return (ulong)sum;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static ulong FoldMontgomery(ulong value, ulong modulus)
|
||||
{
|
||||
// Pollard Rho and ModPow64 both feed moduli of at least three, so retain the documentation and skip the runtime guard.
|
||||
@@ -609,7 +609,7 @@ public static partial class ULongExtensions
|
||||
return folded;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong ModPow64(this ulong value, ulong exponent, ulong modulus)
|
||||
{
|
||||
// Pollard Rho and the Mersenne testers never pass moduli below two, so keep the guard commented for clarity.
|
||||
@@ -635,13 +635,10 @@ public static partial class ULongExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
// Reuse the direct UInt128 reduction path that dominated MulMod64Benchmarks to avoid
|
||||
// the redundant operand modulo operations in the older fallback.
|
||||
public static ulong MulMod64(this ulong a, ulong b, ulong modulus)
|
||||
{
|
||||
return (ulong)(((UInt128)a * b) % modulus);
|
||||
}
|
||||
public static ulong MulMod64(this ulong a, ulong b, ulong modulus) => (ulong)(((UInt128)a * b) % modulus);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static ulong MontgomeryMultiplyCpu(this ulong a, ulong b, ulong modulus, ulong nPrime)
|
||||
@@ -658,7 +655,7 @@ public static partial class ULongExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static ulong Pow2MontgomeryModSingleBitKeepMontgomery(ulong exponent, in MontgomeryDivisorData divisor)
|
||||
{
|
||||
ulong modulus = divisor.Modulus;
|
||||
@@ -686,7 +683,7 @@ public static partial class ULongExtensions
|
||||
return result;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private static ulong Pow2MontgomeryModSingleBitConvertToStandard(ulong exponent, in MontgomeryDivisorData divisor)
|
||||
{
|
||||
ulong modulus = divisor.Modulus;
|
||||
@@ -714,7 +711,7 @@ public static partial class ULongExtensions
|
||||
return result.MontgomeryMultiplyCpu(1UL, modulus, nPrime);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static UInt128 PowMod(this ulong exponent, UInt128 modulus)
|
||||
{
|
||||
// EvenPerfectBitScanner starts CPU scans at p >= 138,000,000 (Program.cs),
|
||||
@@ -1198,7 +1195,7 @@ public static partial class ULongExtensions
|
||||
return value % modulus;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static bool SharesFactorWithExponentMinusOneCpu(this ulong exponent)
|
||||
{
|
||||
ulong prime, value = exponent - 1UL;
|
||||
@@ -1235,7 +1232,7 @@ public static partial class ULongExtensions
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static bool SharesFactorWithExponentMinusOneGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu)
|
||||
{
|
||||
ulong prime, value = exponent - 1UL;
|
||||
@@ -1272,7 +1269,7 @@ public static partial class ULongExtensions
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static bool SharesFactorWithExponentMinusOneHybrid(this ulong exponent, PrimeOrderCalculatorAccelerator gpu)
|
||||
{
|
||||
ulong prime, value = exponent - 1UL;
|
||||
|
||||
@@ -34510,3 +34510,23 @@ p,divisor,searchedMersenne,detailedCheck,passedAllTests
|
||||
10639,427251792503,True,True,False
|
||||
20023,1235434157297,True,True,False
|
||||
12497,347432096281,True,True,False
|
||||
17539,1434748148857,True,True,False
|
||||
5669,122398868791,True,True,False
|
||||
12721,338895581441,True,True,False
|
||||
15773,344578472209,True,True,False
|
||||
16573,588828580471,True,True,False
|
||||
5581,129359320121,True,True,False
|
||||
17477,606383809609,True,True,False
|
||||
19571,2844272257303,True,True,False
|
||||
9433,444094320401,True,True,False
|
||||
9769,296887940119,True,True,False
|
||||
15629,284749721023,True,True,False
|
||||
16519,2418552373423,True,True,False
|
||||
7603,918910927273,True,True,False
|
||||
20399,167108609,True,True,False
|
||||
10729,290280712591,True,True,False
|
||||
20411,40823,True,True,False
|
||||
20441,406981291169,True,True,False
|
||||
9511,1366035502967,True,True,False
|
||||
2789,128664552119,True,True,False
|
||||
20479,2948977,True,True,False
|
||||
|
Can't render this file because it is too large.
|
Reference in new issue
Block a user