Files
even-perfect-numbers-scanner/PerfectNumbers.Core/Gpu/Kernels/KernelMathHelpers.cs
T

70 lines
1.6 KiB
C#

using System.Runtime.CompilerServices;
namespace PerfectNumbers.Core.Gpu;
internal static class KernelMathHelpers
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong FastDiv64Gpu(ulong value, ulong divisor, ulong mul)
{
ulong quotient = GpuUInt128.MulHigh(value, mul);
GpuUInt128 remainder = new(0UL, value);
GpuUInt128 product = new(GpuUInt128.MulHigh(quotient, divisor), quotient * divisor);
remainder.Sub(product);
if (remainder.High != 0UL || remainder.Low >= divisor)
{
quotient++;
}
return quotient;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong Mod128By64(GpuUInt128 value, ulong modulus)
{
ulong rem = 0UL;
ulong part = value.High;
for (int i = 0; i < 64; i++)
{
rem = (rem << 1) | (part >> 63);
if (rem >= modulus)
{
rem -= modulus;
}
part <<= 1;
}
part = value.Low;
for (int i = 0; i < 64; i++)
{
rem = (rem << 1) | (part >> 63);
if (rem >= modulus)
{
rem -= modulus;
}
part <<= 1;
}
return rem;
}
public static ulong CalculateCycleLengthSmall(ulong divisor)
{
if ((divisor & (divisor - 1UL)) == 0UL)
return 1UL;
ulong order = 1UL, pow = 2UL;
while (pow != 1UL)
{
pow <<= 1;
if (pow > divisor)
pow -= divisor;
order++;
}
return order;
}
}