Files
2025-11-18 04:22:39 +01:00

47 lines
1.4 KiB
C#

using ILGPU;
using ILGPU.Algorithms;
namespace PerfectNumbers.Core.Gpu;
internal static class DivisorKernels
{
public static void Kernel(Index1D _, ulong exponent, ReadOnlyGpuUInt128 divisor, ArrayView<byte> result)
{
if (divisor.High == 0UL && divisor.Low <= 1UL)
{
result[0] = 0;
return;
}
GpuUInt128 baseVal;
int x = divisor.High == 0UL
? 63 - XMath.LeadingZeroCount(divisor.Low)
: 127 - XMath.LeadingZeroCount(divisor.High);
ReadOnlyGpuUInt128 readOnlyMod = divisor;
if (x == 0)
{
baseVal = GpuUInt128.Pow2Mod(exponent, in readOnlyMod);
result[0] = baseVal.High == 0UL && baseVal.Low == 1UL ? (byte)1 : (byte)0;
return;
}
ulong ux = (ulong)x;
if (x >= 64)
{
baseVal = new GpuUInt128(1UL << (x - 64), 0UL);
}
else
{
baseVal = new GpuUInt128(0UL, 1UL << x);
}
GpuUInt128 pow = baseVal;
pow.ModPow(exponent / ux, in readOnlyMod);
var part2 = GpuUInt128.Pow2Mod(exponent % ux, in readOnlyMod);
GpuUInt128 product = pow;
ReadOnlyGpuUInt128 part2ReadOnly = part2.AsReadOnly();
product.MulMod(in part2ReadOnly, in readOnlyMod);
result[0] = product.High == 0UL && product.Low == 1UL ? (byte)1 : (byte)0;
}
}