66 lines
3.1 KiB
C#
66 lines
3.1 KiB
C#
using System.Runtime.CompilerServices;
|
||
using PerfectNumbers.Core.Gpu;
|
||
using PerfectNumbers.Core.Gpu.Accelerators;
|
||
|
||
namespace PerfectNumbers.Core;
|
||
|
||
public static partial class ULongExtensions
|
||
{
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
[Obsolete("Use ULongExtensions.MulHighCpu or ULongExtensions.MulHighGpu.")]
|
||
public static ulong MulHighGpuCompatible(this ulong x, ulong y)
|
||
{
|
||
GpuUInt128 product = new(x);
|
||
GpuUInt128.Mul64(ref product, 0UL, y);
|
||
return product.High;
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||
public static ulong MulMod64Gpu(this ulong a, ulong b, ulong modulus)
|
||
{
|
||
// TODO: Remove this GPU-compatible shim from production once callers migrate to MulMod64,
|
||
// which the benchmarks show is roughly 6-7× faster on dense 64-bit inputs.
|
||
GpuUInt128 state = new(a % modulus);
|
||
return state.MulMod(b, modulus);
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
[Obsolete("Use ULongExtensions.MulModGpu for GPU-compatible host code or GpuUInt128.MulMod inside kernels.")]
|
||
public static ulong MulMod64GpuDeferred(this ulong a, ulong b, ulong modulus)
|
||
{
|
||
// TODO: Move this deferred helper to the benchmark suite; the baseline MulMod64 avoids the
|
||
// 5-40× slowdown seen across real-world operand distributions.
|
||
GpuUInt128 state = new(a);
|
||
return state.MulModWithNativeModulo(b, modulus);
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
public static ulong MulModGpu(this ulong left, ulong right, ulong modulus)
|
||
{
|
||
GpuUInt128 state = new(left);
|
||
return state.MulMod(right, modulus);
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
public static ulong Pow2MontgomeryModWindowedKeepGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
||
=> Pow2MontgomeryGpuCalculator.CalculateKeep(gpu, exponent, divisor);
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
public static ulong Pow2MontgomeryModWindowedConvertGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
||
=> Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, exponent, divisor);
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
public static ulong Pow2MontgomeryModWithCycleGpu(this ulong exponent, PrimeOrderCalculatorAccelerator gpu, ulong cycleLength, in MontgomeryDivisorData divisor)
|
||
{
|
||
ulong rotationCount = exponent % cycleLength;
|
||
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, rotationCount, divisor);
|
||
}
|
||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||
public static ulong Pow2MontgomeryModFromCycleRemainderGpu(this ulong reducedExponent, PrimeOrderCalculatorAccelerator gpu, in MontgomeryDivisorData divisor)
|
||
{
|
||
return Pow2MontgomeryGpuCalculator.CalculateConvert(gpu, reducedExponent, divisor);
|
||
}
|
||
}
|