MontgomeryDivisorData converted to a pooled class to limit GC pressure. MontgomeryDivisorDataGpu added for GPU operations. PrimeOrderCalculator kernels precompiled during warmup.

This commit is contained in:
mlemanczyk committed 2025-11-24 15:14:31 +01:00
1 parent 07efd5d2a1
commit 070e2a14fd
32 files changed
+310 -192

No files matched your search

+18 -41
View File
@@ -1,47 +1,24 @@
using System.Runtime.CompilerServices;
namespace PerfectNumbers.Core;
public readonly struct MontgomeryDivisorData(ulong modulus, ulong nPrime, ulong montgomeryOne, ulong montgomeryTwo, ulong montgomeryTwoSquared)
public sealed class MontgomeryDivisorData
{
public readonly ulong Modulus = modulus;
public static readonly MontgomeryDivisorData Empty = new();
public ulong Modulus;
public ulong NPrime;
public ulong MontgomeryOne;
public ulong MontgomeryTwo;
public ulong MontgomeryTwoSquared;
public readonly ulong NPrime = nPrime;
public readonly ulong MontgomeryOne = montgomeryOne;
public readonly ulong MontgomeryTwo = montgomeryTwo;
public readonly ulong MontgomeryTwoSquared = montgomeryTwoSquared;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ulong ComputeMontgomeryResidue(UInt128 value, ulong modulus) => (ulong)(value % modulus);
private static ulong ComputeMontgomeryNPrime(ulong modulus)
{
ulong inv = modulus;
inv *= unchecked(2UL - modulus * inv);
inv *= unchecked(2UL - modulus * inv);
inv *= unchecked(2UL - modulus * inv);
inv *= unchecked(2UL - modulus * inv);
inv *= unchecked(2UL - modulus * inv);
inv *= unchecked(2UL - modulus * inv);
inv *= unchecked(2UL - modulus * inv);
return unchecked(0UL - inv);
}
public static MontgomeryDivisorData FromModulus(ulong modulus)
{
ulong nPrime = ComputeMontgomeryNPrime(modulus);
ulong montgomeryOne = ComputeMontgomeryResidue(UInt128Numbers.OneShiftedLeft64, modulus);
ulong montgomeryTwo = ComputeMontgomeryResidue(UInt128Numbers.OneShiftedLeft64x2, modulus);
ulong montgomeryTwoSquared = ULongExtensions.MontgomeryMultiplyCpu(montgomeryTwo, montgomeryTwo, modulus, nPrime);
return new MontgomeryDivisorData(
modulus,
nPrime,
montgomeryOne,
montgomeryTwo,
montgomeryTwoSquared);
}
public MontgomeryDivisorData()
{
}
public MontgomeryDivisorData(ulong modulus, ulong nPrime, ulong montgomeryOne, ulong montgomeryTwo, ulong montgomeryTwoSquared)
{
Modulus = modulus;
NPrime = nPrime;
MontgomeryOne = montgomeryOne;
MontgomeryTwo = montgomeryTwo;
MontgomeryTwoSquared = montgomeryTwoSquared;
}
}