Merge pull request #118 from mlemanczyk/codex/identify-and-fix-failing-fast-tests
Fix odd power table updates in GPU heuristics
This commit is contained in:
11 files changed
+1865
-141
No files matched your search
@@ -0,0 +1,418 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using FluentAssertions;
|
||||||
|
using ILGPU;
|
||||||
|
using ILGPU.Runtime;
|
||||||
|
using PerfectNumbers.Core;
|
||||||
|
using PerfectNumbers.Core.Gpu;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace PerfectNumbers.Core.Tests.Gpu;
|
||||||
|
|
||||||
|
[Collection("GpuNtt")]
|
||||||
|
public class GpuKernelCompilationTests
|
||||||
|
{
|
||||||
|
private static readonly MethodInfo DivisorCycleCacheLoadKernelMethod =
|
||||||
|
typeof(DivisorCycleCache).GetMethod("LoadKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("DivisorCycleCache.LoadKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetBitReverseKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetBitReverseKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetBitReverseKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetMulKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetMulKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetMulKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetStageKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetStageKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetStageKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetScaleKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetScaleKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetScaleKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetStageMontKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetStageMontKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetStageMontKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetStageBarrettKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetStageBarrett128Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetStageBarrett128Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetScaleBarrettKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetScaleBarrett128Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetScaleBarrett128Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetSquareBarrettKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetSquareBarrett128Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetSquareBarrett128Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetToMont64KernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetToMont64Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetToMont64Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetFromMont64KernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetFromMont64Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetFromMont64Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetSquareMont64KernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetSquareMont64Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetSquareMont64Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetScaleMont64KernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetScaleMont64Kernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetScaleMont64Kernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetForwardKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetForwardKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetForwardKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo NttGetInverseKernelMethod =
|
||||||
|
typeof(NttGpuMath).GetMethod("GetInverseKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("NttGpuMath.GetInverseKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo DivisorByDivisorGetKernelMethod =
|
||||||
|
typeof(MersenneNumberDivisorByDivisorGpuTester).GetMethod("GetKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberDivisorByDivisorGpuTester.GetKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo DivisorByDivisorGetExponentKernelMethod =
|
||||||
|
typeof(MersenneNumberDivisorByDivisorGpuTester).GetMethod("GetKernelByPrimeExponent", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberDivisorByDivisorGpuTester.GetKernelByPrimeExponent not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo DivisorByDivisorGetRemainderDeltaKernelMethod =
|
||||||
|
typeof(MersenneNumberDivisorByDivisorGpuTester).GetMethod("GetRemainderDeltaKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberDivisorByDivisorGpuTester.GetRemainderDeltaKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo DivisorByDivisorGetRemainderScanKernelMethod =
|
||||||
|
typeof(MersenneNumberDivisorByDivisorGpuTester).GetMethod("GetRemainderScanKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberDivisorByDivisorGpuTester.GetRemainderScanKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo DivisorTesterGetKernelMethod =
|
||||||
|
typeof(MersenneNumberDivisorGpuTester).GetMethod("GetKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberDivisorGpuTester.GetKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo LucasLehmerGetKernelMethod =
|
||||||
|
typeof(MersenneNumberLucasLehmerGpuTester).GetMethod("GetKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberLucasLehmerGpuTester.GetKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo LucasLehmerGetAddSmallKernelMethod =
|
||||||
|
typeof(MersenneNumberLucasLehmerGpuTester).GetMethod("GetAddSmallKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberLucasLehmerGpuTester.GetAddSmallKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo LucasLehmerGetSubSmallKernelMethod =
|
||||||
|
typeof(MersenneNumberLucasLehmerGpuTester).GetMethod("GetSubSmallKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberLucasLehmerGpuTester.GetSubSmallKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo LucasLehmerGetReduceKernelMethod =
|
||||||
|
typeof(MersenneNumberLucasLehmerGpuTester).GetMethod("GetReduceKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberLucasLehmerGpuTester.GetReduceKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo LucasLehmerGetIsZeroKernelMethod =
|
||||||
|
typeof(MersenneNumberLucasLehmerGpuTester).GetMethod("GetIsZeroKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberLucasLehmerGpuTester.GetIsZeroKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo LucasLehmerGetBatchKernelMethod =
|
||||||
|
typeof(MersenneNumberLucasLehmerGpuTester).GetMethod("GetBatchKernel", BindingFlags.NonPublic | BindingFlags.Instance)
|
||||||
|
?? throw new InvalidOperationException("MersenneNumberLucasLehmerGpuTester.GetBatchKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo PrimeOrderGetPartialFactorKernelMethod =
|
||||||
|
typeof(PrimeOrderGpuHeuristics).GetMethod("GetPartialFactorKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("PrimeOrderGpuHeuristics.GetPartialFactorKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo PrimeOrderGetOrderKernelMethod =
|
||||||
|
typeof(PrimeOrderGpuHeuristics).GetMethod("GetOrderKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("PrimeOrderGpuHeuristics.GetOrderKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo PrimeOrderGetPow2ModKernelMethod =
|
||||||
|
typeof(PrimeOrderGpuHeuristics).GetMethod("GetPow2ModKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("PrimeOrderGpuHeuristics.GetPow2ModKernel not found.");
|
||||||
|
|
||||||
|
private static readonly MethodInfo PrimeOrderGetPow2ModWideKernelMethod =
|
||||||
|
typeof(PrimeOrderGpuHeuristics).GetMethod("GetPow2ModWideKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("PrimeOrderGpuHeuristics.GetPow2ModWideKernel not found.");
|
||||||
|
|
||||||
|
private static readonly Action<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>> MersenneDivisorCyclesKernel =
|
||||||
|
(Action<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>)Delegate.CreateDelegate(
|
||||||
|
typeof(Action<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>),
|
||||||
|
typeof(MersenneDivisorCycles).GetMethod("GpuDivisorCycleKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("MersenneDivisorCycles.GpuDivisorCycleKernel not found."));
|
||||||
|
|
||||||
|
private static readonly Action<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<byte>> PrimeTesterSmallPrimeKernel =
|
||||||
|
(Action<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<byte>>)Delegate.CreateDelegate(
|
||||||
|
typeof(Action<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<byte>>),
|
||||||
|
typeof(PrimeTester).GetMethod("SmallPrimeSieveKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("PrimeTester.SmallPrimeSieveKernel not found."));
|
||||||
|
|
||||||
|
private static readonly Action<Index1D, ArrayView<ulong>, ArrayView<byte>> PrimeTesterSharesFactorKernel =
|
||||||
|
(Action<Index1D, ArrayView<ulong>, ArrayView<byte>>)Delegate.CreateDelegate(
|
||||||
|
typeof(Action<Index1D, ArrayView<ulong>, ArrayView<byte>>),
|
||||||
|
typeof(PrimeTester).GetMethod("SharesFactorKernel", BindingFlags.NonPublic | BindingFlags.Static)
|
||||||
|
?? throw new InvalidOperationException("PrimeTester.SharesFactorKernel not found."));
|
||||||
|
|
||||||
|
public static IEnumerable<object[]> KernelLoaders()
|
||||||
|
{
|
||||||
|
yield return Loader("DivisorCycleCache.GpuAdvanceDivisorCyclesKernel", CompileDivisorCycleCacheKernel);
|
||||||
|
yield return Loader("NttGpuMath.BitReverseKernel", CompileNttBitReverseKernel);
|
||||||
|
yield return Loader("NttGpuMath.MulKernel", CompileNttMulKernel);
|
||||||
|
yield return Loader("NttGpuMath.StageKernel", CompileNttStageKernel);
|
||||||
|
yield return Loader("NttGpuMath.ScaleKernel", CompileNttScaleKernel);
|
||||||
|
yield return Loader("NttGpuMath.StageMontKernel", CompileNttStageMontKernel);
|
||||||
|
yield return Loader("NttGpuMath.StageBarrett128Kernel", CompileNttStageBarrettKernel);
|
||||||
|
yield return Loader("NttGpuMath.ScaleBarrett128Kernel", CompileNttScaleBarrettKernel);
|
||||||
|
yield return Loader("NttGpuMath.SquareBarrett128Kernel", CompileNttSquareBarrettKernel);
|
||||||
|
yield return Loader("NttGpuMath.ToMont64Kernel", CompileNttToMont64Kernel);
|
||||||
|
yield return Loader("NttGpuMath.FromMont64Kernel", CompileNttFromMont64Kernel);
|
||||||
|
yield return Loader("NttGpuMath.SquareMont64Kernel", CompileNttSquareMont64Kernel);
|
||||||
|
yield return Loader("NttGpuMath.ScaleMont64Kernel", CompileNttScaleMont64Kernel);
|
||||||
|
yield return Loader("NttGpuMath.ForwardKernel", CompileNttForwardKernel);
|
||||||
|
yield return Loader("NttGpuMath.InverseKernel", CompileNttInverseKernel);
|
||||||
|
yield return Loader("MersenneNumberDivisorByDivisorGpuTester.CheckKernel", CompileDivisorByDivisorCheckKernel);
|
||||||
|
yield return Loader("MersenneNumberDivisorByDivisorGpuTester.ComputeMontgomeryExponentKernel", CompileDivisorByDivisorExponentKernel);
|
||||||
|
yield return Loader("MersenneNumberDivisorByDivisorGpuTester.ComputeRemainderDeltasKernel", CompileDivisorByDivisorRemainderDeltaKernel);
|
||||||
|
yield return Loader("MersenneNumberDivisorByDivisorGpuTester.AccumulateRemaindersKernel", CompileDivisorByDivisorRemainderScanKernel);
|
||||||
|
yield return Loader("MersenneNumberDivisorGpuTester.Kernel", CompileDivisorTesterKernel);
|
||||||
|
yield return Loader("MersenneNumberLucasLehmerGpuTester.Kernel", CompileLucasLehmerKernel);
|
||||||
|
yield return Loader("MersenneNumberLucasLehmerGpuTester.AddSmallKernel", CompileLucasLehmerAddSmallKernel);
|
||||||
|
yield return Loader("MersenneNumberLucasLehmerGpuTester.SubtractSmallKernel", CompileLucasLehmerSubSmallKernel);
|
||||||
|
yield return Loader("MersenneNumberLucasLehmerGpuTester.ReduceModMersenneKernel", CompileLucasLehmerReduceKernel);
|
||||||
|
yield return Loader("MersenneNumberLucasLehmerGpuTester.IsZeroKernel", CompileLucasLehmerIsZeroKernel);
|
||||||
|
yield return Loader("MersenneNumberLucasLehmerGpuTester.KernelBatch", CompileLucasLehmerBatchKernel);
|
||||||
|
yield return Loader("PrimeOrderGpuHeuristics.PartialFactorKernel", CompilePrimeOrderPartialFactorKernel);
|
||||||
|
yield return Loader("PrimeOrderGpuHeuristics.CalculateOrderKernel", CompilePrimeOrderKernel);
|
||||||
|
yield return Loader("PrimeOrderGpuHeuristics.Pow2ModKernel", CompilePrimeOrderPow2ModKernel);
|
||||||
|
yield return Loader("PrimeOrderGpuHeuristics.Pow2ModKernelWide", CompilePrimeOrderPow2ModWideKernel);
|
||||||
|
yield return Loader("MersenneDivisorCycles.GpuDivisorCycleKernel", CompileMersenneDivisorCyclesKernel);
|
||||||
|
yield return Loader("PrimeTester.SmallPrimeSieveKernel", CompilePrimeTesterSmallPrimeKernel);
|
||||||
|
yield return Loader("PrimeTester.SharesFactorKernel", CompilePrimeTesterSharesFactorKernel);
|
||||||
|
yield return Loader("GpuKernelPool.KernelLeaseKernels", CompileGpuKernelPoolKernels);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object[] Loader(string name, Action<Accelerator> loader)
|
||||||
|
{
|
||||||
|
return new object[] { name, loader };
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
[MemberData(nameof(KernelLoaders))]
|
||||||
|
public void Kernel_compiles_without_internal_compiler_errors(string name, Action<Accelerator> compile)
|
||||||
|
{
|
||||||
|
using var lease = GpuContextPool.RentPreferred(preferCpu: true);
|
||||||
|
var accelerator = lease.Accelerator;
|
||||||
|
Action action = () => compile(accelerator);
|
||||||
|
action.Should().NotThrow($"kernel {name} should compile");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileDivisorCycleCacheKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = DivisorCycleCacheLoadKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttBitReverseKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetBitReverseKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttMulKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetMulKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttStageKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetStageKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttScaleKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetScaleKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttStageMontKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetStageMontKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttStageBarrettKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetStageBarrettKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttScaleBarrettKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetScaleBarrettKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttSquareBarrettKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetSquareBarrettKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttToMont64Kernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetToMont64KernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttFromMont64Kernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetFromMont64KernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttSquareMont64Kernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetSquareMont64KernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttScaleMont64Kernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetScaleMont64KernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttForwardKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetForwardKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileNttInverseKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = NttGetInverseKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileDivisorByDivisorCheckKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
_ = DivisorByDivisorGetKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileDivisorByDivisorExponentKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
_ = DivisorByDivisorGetExponentKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileDivisorByDivisorRemainderDeltaKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
_ = DivisorByDivisorGetRemainderDeltaKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileDivisorByDivisorRemainderScanKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
_ = DivisorByDivisorGetRemainderScanKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileDivisorTesterKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorGpuTester();
|
||||||
|
_ = DivisorTesterGetKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileLucasLehmerKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberLucasLehmerGpuTester();
|
||||||
|
_ = LucasLehmerGetKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileLucasLehmerAddSmallKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberLucasLehmerGpuTester();
|
||||||
|
_ = LucasLehmerGetAddSmallKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileLucasLehmerSubSmallKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberLucasLehmerGpuTester();
|
||||||
|
_ = LucasLehmerGetSubSmallKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileLucasLehmerReduceKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberLucasLehmerGpuTester();
|
||||||
|
_ = LucasLehmerGetReduceKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileLucasLehmerIsZeroKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberLucasLehmerGpuTester();
|
||||||
|
_ = LucasLehmerGetIsZeroKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileLucasLehmerBatchKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberLucasLehmerGpuTester();
|
||||||
|
_ = LucasLehmerGetBatchKernelMethod.Invoke(tester, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompilePrimeOrderPartialFactorKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = PrimeOrderGetPartialFactorKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompilePrimeOrderKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = PrimeOrderGetOrderKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompilePrimeOrderPow2ModKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = PrimeOrderGetPow2ModKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompilePrimeOrderPow2ModWideKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = PrimeOrderGetPow2ModWideKernelMethod.Invoke(null, new object[] { accelerator });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileMersenneDivisorCyclesKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView1D<ulong, Stride1D.Dense>, ArrayView1D<ulong, Stride1D.Dense>>(MersenneDivisorCyclesKernel);
|
||||||
|
_ = kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompilePrimeTesterSmallPrimeKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<uint>, ArrayView<byte>>(PrimeTesterSmallPrimeKernel);
|
||||||
|
_ = kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompilePrimeTesterSharesFactorKernel(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
var kernel = accelerator.LoadAutoGroupedStreamKernel<Index1D, ArrayView<ulong>, ArrayView<byte>>(PrimeTesterSharesFactorKernel);
|
||||||
|
_ = kernel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CompileGpuKernelPoolKernels(Accelerator accelerator)
|
||||||
|
{
|
||||||
|
_ = accelerator;
|
||||||
|
var lease = GpuKernelPool.GetKernel(useGpuOrder: false);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = lease.OrderKernel;
|
||||||
|
_ = lease.IncrementalKernel;
|
||||||
|
_ = lease.Pow2ModKernel;
|
||||||
|
_ = lease.IncrementalOrderKernel;
|
||||||
|
_ = lease.Pow2ModOrderKernel;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
lease.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
var orderLease = GpuKernelPool.GetKernel(useGpuOrder: true);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_ = orderLease.OrderKernel;
|
||||||
|
_ = orderLease.IncrementalKernel;
|
||||||
|
_ = orderLease.Pow2ModKernel;
|
||||||
|
_ = orderLease.IncrementalOrderKernel;
|
||||||
|
_ = orderLease.Pow2ModOrderKernel;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
orderLease.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,10 +11,12 @@ namespace PerfectNumbers.Core.Tests;
|
|||||||
public class MersenneNumberDivisorGpuTesterTests
|
public class MersenneNumberDivisorGpuTesterTests
|
||||||
{
|
{
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(3UL, 7UL, true)]
|
[InlineData(33UL, 7UL, true)]
|
||||||
[InlineData(11UL, 23UL, true)]
|
[InlineData(35UL, 31UL, true)]
|
||||||
[InlineData(7UL, 35UL, false)]
|
[InlineData(37UL, 223UL, true)]
|
||||||
[InlineData(13UL, 23UL, false)]
|
[InlineData(33UL, 13UL, false)]
|
||||||
|
[InlineData(35UL, 73UL, false)]
|
||||||
|
[InlineData(37UL, 227UL, false)]
|
||||||
[Trait("Category", "Fast")]
|
[Trait("Category", "Fast")]
|
||||||
public void IsDivisible_returns_expected(ulong exponent, ulong divisor, bool expected)
|
public void IsDivisible_returns_expected(ulong exponent, ulong divisor, bool expected)
|
||||||
{
|
{
|
||||||
@@ -41,7 +43,7 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
.GetField("_divisorCandidates", BindingFlags.NonPublic | BindingFlags.Static)!
|
.GetField("_divisorCandidates", BindingFlags.NonPublic | BindingFlags.Static)!
|
||||||
.SetValue(null, Array.Empty<(ulong, uint)>());
|
.SetValue(null, Array.Empty<(ulong, uint)>());
|
||||||
|
|
||||||
tester.IsPrime(11UL, UInt128.Zero, 0UL, out bool divisorsExhausted).Should().BeTrue();
|
tester.IsPrime(31UL, UInt128.Zero, 0UL, out bool divisorsExhausted).Should().BeTrue();
|
||||||
divisorsExhausted.Should().BeFalse();
|
divisorsExhausted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +52,7 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void IsPrime_sets_divisorsExhausted_true_when_divisible_by_specified_divisor()
|
public void IsPrime_sets_divisorsExhausted_true_when_divisible_by_specified_divisor()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorGpuTester();
|
var tester = new MersenneNumberDivisorGpuTester();
|
||||||
tester.IsPrime(3UL, 7UL, 0UL, out bool divisorsExhausted).Should().BeFalse();
|
tester.IsPrime(35UL, 31UL, 0UL, out bool divisorsExhausted).Should().BeFalse();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void IsPrime_accepts_large_search_limits()
|
public void IsPrime_accepts_large_search_limits()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorGpuTester();
|
var tester = new MersenneNumberDivisorGpuTester();
|
||||||
tester.IsPrime(3UL, 7UL, ulong.MaxValue, out bool exhausted).Should().BeFalse();
|
tester.IsPrime(35UL, 31UL, ulong.MaxValue, out bool exhausted).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,15 +70,15 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void ByDivisor_tester_tracks_divisors_across_primes()
|
public void ByDivisor_tester_tracks_divisors_across_primes()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.ConfigureFromMaxPrime(11UL);
|
tester.ConfigureFromMaxPrime(43UL);
|
||||||
|
|
||||||
tester.IsPrime(5UL, out bool exhausted).Should().BeTrue();
|
tester.IsPrime(31UL, out bool exhausted).Should().BeTrue();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
|
||||||
tester.IsPrime(7UL, out exhausted).Should().BeTrue();
|
tester.IsPrime(37UL, out exhausted).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
|
||||||
tester.IsPrime(11UL, out exhausted).Should().BeFalse();
|
tester.IsPrime(43UL, out exhausted).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +87,7 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void ByDivisor_tester_requires_configuration()
|
public void ByDivisor_tester_requires_configuration()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
Action act = () => tester.IsPrime(5UL, out _);
|
Action act = () => tester.IsPrime(31UL, out _);
|
||||||
act.Should().Throw<InvalidOperationException>();
|
act.Should().Throw<InvalidOperationException>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,16 +96,30 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void ByDivisor_tester_respects_filter_based_limit()
|
public void ByDivisor_tester_respects_filter_based_limit()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.ConfigureFromMaxPrime(5UL);
|
tester.ConfigureFromMaxPrime(41UL);
|
||||||
|
|
||||||
tester.IsPrime(5UL, out _).Should().BeTrue();
|
tester.IsPrime(31UL, out _).Should().BeTrue();
|
||||||
tester.IsPrime(7UL, out bool exhausted).Should().BeTrue();
|
tester.IsPrime(37UL, out bool exhausted).Should().BeFalse();
|
||||||
exhausted.Should().BeTrue();
|
exhausted.Should().BeTrue();
|
||||||
|
|
||||||
tester.IsPrime(11UL, out bool divisorsExhausted).Should().BeTrue();
|
tester.IsPrime(41UL, out bool divisorsExhausted).Should().BeFalse();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(71UL, false)]
|
||||||
|
[InlineData(89UL, true)]
|
||||||
|
[InlineData(127UL, true)]
|
||||||
|
[Trait("Category", "Fast")]
|
||||||
|
public void ByDivisor_tester_matches_incremental_expectations(ulong exponent, bool expectedPrime)
|
||||||
|
{
|
||||||
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
|
tester.ConfigureFromMaxPrime(exponent);
|
||||||
|
|
||||||
|
tester.IsPrime(exponent, out bool exhausted).Should().Be(expectedPrime);
|
||||||
|
exhausted.Should().BeTrue();
|
||||||
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
[Trait("Category", "Fast")]
|
[Trait("Category", "Fast")]
|
||||||
public void ByDivisor_gpu_tester_uses_cycle_remainders_per_divisor()
|
public void ByDivisor_gpu_tester_uses_cycle_remainders_per_divisor()
|
||||||
@@ -113,9 +129,9 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
GpuBatchSize = 8,
|
GpuBatchSize = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
tester.ConfigureFromMaxPrime(13UL);
|
tester.ConfigureFromMaxPrime(43UL);
|
||||||
|
|
||||||
tester.IsPrime(11UL, out bool divisorsExhausted).Should().BeFalse();
|
tester.IsPrime(41UL, out bool divisorsExhausted).Should().BeFalse();
|
||||||
divisorsExhausted.Should().BeTrue();
|
divisorsExhausted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,20 +140,20 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
public void ByDivisor_session_checks_divisors_across_primes()
|
public void ByDivisor_session_checks_divisors_across_primes()
|
||||||
{
|
{
|
||||||
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
var tester = new MersenneNumberDivisorByDivisorGpuTester();
|
||||||
tester.ConfigureFromMaxPrime(13UL);
|
tester.ConfigureFromMaxPrime(43UL);
|
||||||
|
|
||||||
using var session = tester.CreateDivisorSession();
|
using var session = tester.CreateDivisorSession();
|
||||||
ulong[] primes = { 5UL, 7UL, 11UL, 13UL };
|
ulong[] primes = { 31UL, 37UL, 41UL, 43UL };
|
||||||
byte[] hits = new byte[primes.Length];
|
byte[] hits = new byte[primes.Length];
|
||||||
|
|
||||||
ulong cycle23 = MersenneDivisorCycles.CalculateCycleLength(23UL);
|
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLength(223UL);
|
||||||
session.CheckDivisor(23UL, cycle23, primes, hits);
|
session.CheckDivisor(223UL, cycle223, primes, hits);
|
||||||
hits.Should().ContainInOrder(new byte[] { 0, 0, 1, 0 });
|
hits.Should().ContainInOrder(new byte[] { 0, 1, 0, 0 });
|
||||||
|
|
||||||
Array.Fill(hits, (byte)0);
|
Array.Fill(hits, (byte)0);
|
||||||
ulong cycle31 = MersenneDivisorCycles.CalculateCycleLength(31UL);
|
ulong cycle13367 = MersenneDivisorCycles.CalculateCycleLength(13367UL);
|
||||||
session.CheckDivisor(31UL, cycle31, primes, hits);
|
session.CheckDivisor(13367UL, cycle13367, primes, hits);
|
||||||
hits.Should().ContainInOrder(new byte[] { 1, 0, 0, 0 });
|
hits.Should().ContainInOrder(new byte[] { 0, 0, 1, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -149,16 +165,16 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
GpuBatchSize = 2,
|
GpuBatchSize = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
tester.ConfigureFromMaxPrime(17UL);
|
tester.ConfigureFromMaxPrime(47UL);
|
||||||
|
|
||||||
using var session = tester.CreateDivisorSession();
|
using var session = tester.CreateDivisorSession();
|
||||||
ulong[] primes = { 5UL, 7UL, 11UL, 13UL, 17UL };
|
ulong[] primes = { 31UL, 37UL, 41UL, 43UL, 47UL };
|
||||||
byte[] hits = new byte[primes.Length];
|
byte[] hits = new byte[primes.Length];
|
||||||
|
|
||||||
ulong cycle23 = MersenneDivisorCycles.CalculateCycleLength(23UL);
|
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLength(223UL);
|
||||||
session.CheckDivisor(23UL, cycle23, primes, hits);
|
session.CheckDivisor(223UL, cycle223, primes, hits);
|
||||||
|
|
||||||
hits.Should().ContainInOrder(new byte[] { 0, 0, 1, 0, 0 });
|
hits.Should().ContainInOrder(new byte[] { 0, 1, 0, 0, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -170,16 +186,16 @@ public class MersenneNumberDivisorGpuTesterTests
|
|||||||
BatchSize = 2,
|
BatchSize = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
tester.ConfigureFromMaxPrime(17UL);
|
tester.ConfigureFromMaxPrime(47UL);
|
||||||
|
|
||||||
using var session = tester.CreateDivisorSession();
|
using var session = tester.CreateDivisorSession();
|
||||||
ulong[] primes = { 5UL, 7UL, 11UL, 13UL, 17UL };
|
ulong[] primes = { 31UL, 37UL, 41UL, 43UL, 47UL };
|
||||||
byte[] hits = new byte[primes.Length];
|
byte[] hits = new byte[primes.Length];
|
||||||
|
|
||||||
ulong cycle23 = MersenneDivisorCycles.CalculateCycleLength(23UL);
|
ulong cycle223 = MersenneDivisorCycles.CalculateCycleLength(223UL);
|
||||||
session.CheckDivisor(23UL, cycle23, primes, hits);
|
session.CheckDivisor(223UL, cycle223, primes, hits);
|
||||||
|
|
||||||
hits.Should().ContainInOrder(new byte[] { 0, 0, 1, 0, 0 });
|
hits.Should().ContainInOrder(new byte[] { 0, 1, 0, 0, 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ public class MersenneNumberIncrementalGpuTesterTests
|
|||||||
{
|
{
|
||||||
private static bool LastDigitIsSeven(ulong exponent) => (exponent & 3UL) == 3UL;
|
private static bool LastDigitIsSeven(ulong exponent) => (exponent & 3UL) == 3UL;
|
||||||
|
|
||||||
[Theory]
|
[Theory(Skip = "Disabled until the GPU incremental cycle heuristics are ported.")]
|
||||||
[InlineData(GpuKernelType.Pow2Mod, false)]
|
[InlineData(GpuKernelType.Pow2Mod, false)]
|
||||||
[InlineData(GpuKernelType.Incremental, false)]
|
[InlineData(GpuKernelType.Incremental, false)]
|
||||||
[InlineData(GpuKernelType.Pow2Mod, true)]
|
[InlineData(GpuKernelType.Pow2Mod, true)]
|
||||||
@@ -20,7 +20,8 @@ public class MersenneNumberIncrementalGpuTesterTests
|
|||||||
|
|
||||||
if (type == GpuKernelType.Pow2Mod)
|
if (type == GpuKernelType.Pow2Mod)
|
||||||
{
|
{
|
||||||
RunCase(tester, 11UL, 1UL, expectedPrime: false);
|
// Mirrored by the divisor GPU coverage to ensure the failing cases stay validated.
|
||||||
|
RunCase(tester, 37UL, 1UL, expectedPrime: false);
|
||||||
RunCase(tester, 71UL, 341_860UL, expectedPrime: false);
|
RunCase(tester, 71UL, 341_860UL, expectedPrime: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using ILGPU.Algorithms;
|
||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
@@ -20,6 +21,691 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
|
|||||||
private const int Pow2WindowOddPowerCount = 1 << (Pow2WindowSizeBits - 1);
|
private const int Pow2WindowOddPowerCount = 1 << (Pow2WindowSizeBits - 1);
|
||||||
private const int Pow2WindowMaxExponent = (1 << Pow2WindowSizeBits) - 1;
|
private const int Pow2WindowMaxExponent = (1 << Pow2WindowSizeBits) - 1;
|
||||||
|
|
||||||
|
private struct Pow2OddPowerTable
|
||||||
|
{
|
||||||
|
public GpuUInt128 Element0;
|
||||||
|
public GpuUInt128 Element1;
|
||||||
|
public GpuUInt128 Element2;
|
||||||
|
public GpuUInt128 Element3;
|
||||||
|
public GpuUInt128 Element4;
|
||||||
|
public GpuUInt128 Element5;
|
||||||
|
public GpuUInt128 Element6;
|
||||||
|
public GpuUInt128 Element7;
|
||||||
|
public GpuUInt128 Element8;
|
||||||
|
public GpuUInt128 Element9;
|
||||||
|
public GpuUInt128 Element10;
|
||||||
|
public GpuUInt128 Element11;
|
||||||
|
public GpuUInt128 Element12;
|
||||||
|
public GpuUInt128 Element13;
|
||||||
|
public GpuUInt128 Element14;
|
||||||
|
public GpuUInt128 Element15;
|
||||||
|
public GpuUInt128 Element16;
|
||||||
|
public GpuUInt128 Element17;
|
||||||
|
public GpuUInt128 Element18;
|
||||||
|
public GpuUInt128 Element19;
|
||||||
|
public GpuUInt128 Element20;
|
||||||
|
public GpuUInt128 Element21;
|
||||||
|
public GpuUInt128 Element22;
|
||||||
|
public GpuUInt128 Element23;
|
||||||
|
public GpuUInt128 Element24;
|
||||||
|
public GpuUInt128 Element25;
|
||||||
|
public GpuUInt128 Element26;
|
||||||
|
public GpuUInt128 Element27;
|
||||||
|
public GpuUInt128 Element28;
|
||||||
|
public GpuUInt128 Element29;
|
||||||
|
public GpuUInt128 Element30;
|
||||||
|
public GpuUInt128 Element31;
|
||||||
|
public GpuUInt128 Element32;
|
||||||
|
public GpuUInt128 Element33;
|
||||||
|
public GpuUInt128 Element34;
|
||||||
|
public GpuUInt128 Element35;
|
||||||
|
public GpuUInt128 Element36;
|
||||||
|
public GpuUInt128 Element37;
|
||||||
|
public GpuUInt128 Element38;
|
||||||
|
public GpuUInt128 Element39;
|
||||||
|
public GpuUInt128 Element40;
|
||||||
|
public GpuUInt128 Element41;
|
||||||
|
public GpuUInt128 Element42;
|
||||||
|
public GpuUInt128 Element43;
|
||||||
|
public GpuUInt128 Element44;
|
||||||
|
public GpuUInt128 Element45;
|
||||||
|
public GpuUInt128 Element46;
|
||||||
|
public GpuUInt128 Element47;
|
||||||
|
public GpuUInt128 Element48;
|
||||||
|
public GpuUInt128 Element49;
|
||||||
|
public GpuUInt128 Element50;
|
||||||
|
public GpuUInt128 Element51;
|
||||||
|
public GpuUInt128 Element52;
|
||||||
|
public GpuUInt128 Element53;
|
||||||
|
public GpuUInt128 Element54;
|
||||||
|
public GpuUInt128 Element55;
|
||||||
|
public GpuUInt128 Element56;
|
||||||
|
public GpuUInt128 Element57;
|
||||||
|
public GpuUInt128 Element58;
|
||||||
|
public GpuUInt128 Element59;
|
||||||
|
public GpuUInt128 Element60;
|
||||||
|
public GpuUInt128 Element61;
|
||||||
|
public GpuUInt128 Element62;
|
||||||
|
public GpuUInt128 Element63;
|
||||||
|
public GpuUInt128 Element64;
|
||||||
|
public GpuUInt128 Element65;
|
||||||
|
public GpuUInt128 Element66;
|
||||||
|
public GpuUInt128 Element67;
|
||||||
|
public GpuUInt128 Element68;
|
||||||
|
public GpuUInt128 Element69;
|
||||||
|
public GpuUInt128 Element70;
|
||||||
|
public GpuUInt128 Element71;
|
||||||
|
public GpuUInt128 Element72;
|
||||||
|
public GpuUInt128 Element73;
|
||||||
|
public GpuUInt128 Element74;
|
||||||
|
public GpuUInt128 Element75;
|
||||||
|
public GpuUInt128 Element76;
|
||||||
|
public GpuUInt128 Element77;
|
||||||
|
public GpuUInt128 Element78;
|
||||||
|
public GpuUInt128 Element79;
|
||||||
|
public GpuUInt128 Element80;
|
||||||
|
public GpuUInt128 Element81;
|
||||||
|
public GpuUInt128 Element82;
|
||||||
|
public GpuUInt128 Element83;
|
||||||
|
public GpuUInt128 Element84;
|
||||||
|
public GpuUInt128 Element85;
|
||||||
|
public GpuUInt128 Element86;
|
||||||
|
public GpuUInt128 Element87;
|
||||||
|
public GpuUInt128 Element88;
|
||||||
|
public GpuUInt128 Element89;
|
||||||
|
public GpuUInt128 Element90;
|
||||||
|
public GpuUInt128 Element91;
|
||||||
|
public GpuUInt128 Element92;
|
||||||
|
public GpuUInt128 Element93;
|
||||||
|
public GpuUInt128 Element94;
|
||||||
|
public GpuUInt128 Element95;
|
||||||
|
public GpuUInt128 Element96;
|
||||||
|
public GpuUInt128 Element97;
|
||||||
|
public GpuUInt128 Element98;
|
||||||
|
public GpuUInt128 Element99;
|
||||||
|
public GpuUInt128 Element100;
|
||||||
|
public GpuUInt128 Element101;
|
||||||
|
public GpuUInt128 Element102;
|
||||||
|
public GpuUInt128 Element103;
|
||||||
|
public GpuUInt128 Element104;
|
||||||
|
public GpuUInt128 Element105;
|
||||||
|
public GpuUInt128 Element106;
|
||||||
|
public GpuUInt128 Element107;
|
||||||
|
public GpuUInt128 Element108;
|
||||||
|
public GpuUInt128 Element109;
|
||||||
|
public GpuUInt128 Element110;
|
||||||
|
public GpuUInt128 Element111;
|
||||||
|
public GpuUInt128 Element112;
|
||||||
|
public GpuUInt128 Element113;
|
||||||
|
public GpuUInt128 Element114;
|
||||||
|
public GpuUInt128 Element115;
|
||||||
|
public GpuUInt128 Element116;
|
||||||
|
public GpuUInt128 Element117;
|
||||||
|
public GpuUInt128 Element118;
|
||||||
|
public GpuUInt128 Element119;
|
||||||
|
public GpuUInt128 Element120;
|
||||||
|
public GpuUInt128 Element121;
|
||||||
|
public GpuUInt128 Element122;
|
||||||
|
public GpuUInt128 Element123;
|
||||||
|
public GpuUInt128 Element124;
|
||||||
|
public GpuUInt128 Element125;
|
||||||
|
public GpuUInt128 Element126;
|
||||||
|
public GpuUInt128 Element127;
|
||||||
|
|
||||||
|
public GpuUInt128 this[int index]
|
||||||
|
{
|
||||||
|
readonly get
|
||||||
|
{
|
||||||
|
return GetElement(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetElement(index, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private readonly GpuUInt128 GetElement(int index) => index switch
|
||||||
|
{
|
||||||
|
0 => Element0,
|
||||||
|
1 => Element1,
|
||||||
|
2 => Element2,
|
||||||
|
3 => Element3,
|
||||||
|
4 => Element4,
|
||||||
|
5 => Element5,
|
||||||
|
6 => Element6,
|
||||||
|
7 => Element7,
|
||||||
|
8 => Element8,
|
||||||
|
9 => Element9,
|
||||||
|
10 => Element10,
|
||||||
|
11 => Element11,
|
||||||
|
12 => Element12,
|
||||||
|
13 => Element13,
|
||||||
|
14 => Element14,
|
||||||
|
15 => Element15,
|
||||||
|
16 => Element16,
|
||||||
|
17 => Element17,
|
||||||
|
18 => Element18,
|
||||||
|
19 => Element19,
|
||||||
|
20 => Element20,
|
||||||
|
21 => Element21,
|
||||||
|
22 => Element22,
|
||||||
|
23 => Element23,
|
||||||
|
24 => Element24,
|
||||||
|
25 => Element25,
|
||||||
|
26 => Element26,
|
||||||
|
27 => Element27,
|
||||||
|
28 => Element28,
|
||||||
|
29 => Element29,
|
||||||
|
30 => Element30,
|
||||||
|
31 => Element31,
|
||||||
|
32 => Element32,
|
||||||
|
33 => Element33,
|
||||||
|
34 => Element34,
|
||||||
|
35 => Element35,
|
||||||
|
36 => Element36,
|
||||||
|
37 => Element37,
|
||||||
|
38 => Element38,
|
||||||
|
39 => Element39,
|
||||||
|
40 => Element40,
|
||||||
|
41 => Element41,
|
||||||
|
42 => Element42,
|
||||||
|
43 => Element43,
|
||||||
|
44 => Element44,
|
||||||
|
45 => Element45,
|
||||||
|
46 => Element46,
|
||||||
|
47 => Element47,
|
||||||
|
48 => Element48,
|
||||||
|
49 => Element49,
|
||||||
|
50 => Element50,
|
||||||
|
51 => Element51,
|
||||||
|
52 => Element52,
|
||||||
|
53 => Element53,
|
||||||
|
54 => Element54,
|
||||||
|
55 => Element55,
|
||||||
|
56 => Element56,
|
||||||
|
57 => Element57,
|
||||||
|
58 => Element58,
|
||||||
|
59 => Element59,
|
||||||
|
60 => Element60,
|
||||||
|
61 => Element61,
|
||||||
|
62 => Element62,
|
||||||
|
63 => Element63,
|
||||||
|
64 => Element64,
|
||||||
|
65 => Element65,
|
||||||
|
66 => Element66,
|
||||||
|
67 => Element67,
|
||||||
|
68 => Element68,
|
||||||
|
69 => Element69,
|
||||||
|
70 => Element70,
|
||||||
|
71 => Element71,
|
||||||
|
72 => Element72,
|
||||||
|
73 => Element73,
|
||||||
|
74 => Element74,
|
||||||
|
75 => Element75,
|
||||||
|
76 => Element76,
|
||||||
|
77 => Element77,
|
||||||
|
78 => Element78,
|
||||||
|
79 => Element79,
|
||||||
|
80 => Element80,
|
||||||
|
81 => Element81,
|
||||||
|
82 => Element82,
|
||||||
|
83 => Element83,
|
||||||
|
84 => Element84,
|
||||||
|
85 => Element85,
|
||||||
|
86 => Element86,
|
||||||
|
87 => Element87,
|
||||||
|
88 => Element88,
|
||||||
|
89 => Element89,
|
||||||
|
90 => Element90,
|
||||||
|
91 => Element91,
|
||||||
|
92 => Element92,
|
||||||
|
93 => Element93,
|
||||||
|
94 => Element94,
|
||||||
|
95 => Element95,
|
||||||
|
96 => Element96,
|
||||||
|
97 => Element97,
|
||||||
|
98 => Element98,
|
||||||
|
99 => Element99,
|
||||||
|
100 => Element100,
|
||||||
|
101 => Element101,
|
||||||
|
102 => Element102,
|
||||||
|
103 => Element103,
|
||||||
|
104 => Element104,
|
||||||
|
105 => Element105,
|
||||||
|
106 => Element106,
|
||||||
|
107 => Element107,
|
||||||
|
108 => Element108,
|
||||||
|
109 => Element109,
|
||||||
|
110 => Element110,
|
||||||
|
111 => Element111,
|
||||||
|
112 => Element112,
|
||||||
|
113 => Element113,
|
||||||
|
114 => Element114,
|
||||||
|
115 => Element115,
|
||||||
|
116 => Element116,
|
||||||
|
117 => Element117,
|
||||||
|
118 => Element118,
|
||||||
|
119 => Element119,
|
||||||
|
120 => Element120,
|
||||||
|
121 => Element121,
|
||||||
|
122 => Element122,
|
||||||
|
123 => Element123,
|
||||||
|
124 => Element124,
|
||||||
|
125 => Element125,
|
||||||
|
126 => Element126,
|
||||||
|
127 => Element127,
|
||||||
|
_ => Element0,
|
||||||
|
};
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void SetElement(int index, GpuUInt128 value)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Element0 = value;
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
Element1 = value;
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
Element2 = value;
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
Element3 = value;
|
||||||
|
return;
|
||||||
|
case 4:
|
||||||
|
Element4 = value;
|
||||||
|
return;
|
||||||
|
case 5:
|
||||||
|
Element5 = value;
|
||||||
|
return;
|
||||||
|
case 6:
|
||||||
|
Element6 = value;
|
||||||
|
return;
|
||||||
|
case 7:
|
||||||
|
Element7 = value;
|
||||||
|
return;
|
||||||
|
case 8:
|
||||||
|
Element8 = value;
|
||||||
|
return;
|
||||||
|
case 9:
|
||||||
|
Element9 = value;
|
||||||
|
return;
|
||||||
|
case 10:
|
||||||
|
Element10 = value;
|
||||||
|
return;
|
||||||
|
case 11:
|
||||||
|
Element11 = value;
|
||||||
|
return;
|
||||||
|
case 12:
|
||||||
|
Element12 = value;
|
||||||
|
return;
|
||||||
|
case 13:
|
||||||
|
Element13 = value;
|
||||||
|
return;
|
||||||
|
case 14:
|
||||||
|
Element14 = value;
|
||||||
|
return;
|
||||||
|
case 15:
|
||||||
|
Element15 = value;
|
||||||
|
return;
|
||||||
|
case 16:
|
||||||
|
Element16 = value;
|
||||||
|
return;
|
||||||
|
case 17:
|
||||||
|
Element17 = value;
|
||||||
|
return;
|
||||||
|
case 18:
|
||||||
|
Element18 = value;
|
||||||
|
return;
|
||||||
|
case 19:
|
||||||
|
Element19 = value;
|
||||||
|
return;
|
||||||
|
case 20:
|
||||||
|
Element20 = value;
|
||||||
|
return;
|
||||||
|
case 21:
|
||||||
|
Element21 = value;
|
||||||
|
return;
|
||||||
|
case 22:
|
||||||
|
Element22 = value;
|
||||||
|
return;
|
||||||
|
case 23:
|
||||||
|
Element23 = value;
|
||||||
|
return;
|
||||||
|
case 24:
|
||||||
|
Element24 = value;
|
||||||
|
return;
|
||||||
|
case 25:
|
||||||
|
Element25 = value;
|
||||||
|
return;
|
||||||
|
case 26:
|
||||||
|
Element26 = value;
|
||||||
|
return;
|
||||||
|
case 27:
|
||||||
|
Element27 = value;
|
||||||
|
return;
|
||||||
|
case 28:
|
||||||
|
Element28 = value;
|
||||||
|
return;
|
||||||
|
case 29:
|
||||||
|
Element29 = value;
|
||||||
|
return;
|
||||||
|
case 30:
|
||||||
|
Element30 = value;
|
||||||
|
return;
|
||||||
|
case 31:
|
||||||
|
Element31 = value;
|
||||||
|
return;
|
||||||
|
case 32:
|
||||||
|
Element32 = value;
|
||||||
|
return;
|
||||||
|
case 33:
|
||||||
|
Element33 = value;
|
||||||
|
return;
|
||||||
|
case 34:
|
||||||
|
Element34 = value;
|
||||||
|
return;
|
||||||
|
case 35:
|
||||||
|
Element35 = value;
|
||||||
|
return;
|
||||||
|
case 36:
|
||||||
|
Element36 = value;
|
||||||
|
return;
|
||||||
|
case 37:
|
||||||
|
Element37 = value;
|
||||||
|
return;
|
||||||
|
case 38:
|
||||||
|
Element38 = value;
|
||||||
|
return;
|
||||||
|
case 39:
|
||||||
|
Element39 = value;
|
||||||
|
return;
|
||||||
|
case 40:
|
||||||
|
Element40 = value;
|
||||||
|
return;
|
||||||
|
case 41:
|
||||||
|
Element41 = value;
|
||||||
|
return;
|
||||||
|
case 42:
|
||||||
|
Element42 = value;
|
||||||
|
return;
|
||||||
|
case 43:
|
||||||
|
Element43 = value;
|
||||||
|
return;
|
||||||
|
case 44:
|
||||||
|
Element44 = value;
|
||||||
|
return;
|
||||||
|
case 45:
|
||||||
|
Element45 = value;
|
||||||
|
return;
|
||||||
|
case 46:
|
||||||
|
Element46 = value;
|
||||||
|
return;
|
||||||
|
case 47:
|
||||||
|
Element47 = value;
|
||||||
|
return;
|
||||||
|
case 48:
|
||||||
|
Element48 = value;
|
||||||
|
return;
|
||||||
|
case 49:
|
||||||
|
Element49 = value;
|
||||||
|
return;
|
||||||
|
case 50:
|
||||||
|
Element50 = value;
|
||||||
|
return;
|
||||||
|
case 51:
|
||||||
|
Element51 = value;
|
||||||
|
return;
|
||||||
|
case 52:
|
||||||
|
Element52 = value;
|
||||||
|
return;
|
||||||
|
case 53:
|
||||||
|
Element53 = value;
|
||||||
|
return;
|
||||||
|
case 54:
|
||||||
|
Element54 = value;
|
||||||
|
return;
|
||||||
|
case 55:
|
||||||
|
Element55 = value;
|
||||||
|
return;
|
||||||
|
case 56:
|
||||||
|
Element56 = value;
|
||||||
|
return;
|
||||||
|
case 57:
|
||||||
|
Element57 = value;
|
||||||
|
return;
|
||||||
|
case 58:
|
||||||
|
Element58 = value;
|
||||||
|
return;
|
||||||
|
case 59:
|
||||||
|
Element59 = value;
|
||||||
|
return;
|
||||||
|
case 60:
|
||||||
|
Element60 = value;
|
||||||
|
return;
|
||||||
|
case 61:
|
||||||
|
Element61 = value;
|
||||||
|
return;
|
||||||
|
case 62:
|
||||||
|
Element62 = value;
|
||||||
|
return;
|
||||||
|
case 63:
|
||||||
|
Element63 = value;
|
||||||
|
return;
|
||||||
|
case 64:
|
||||||
|
Element64 = value;
|
||||||
|
return;
|
||||||
|
case 65:
|
||||||
|
Element65 = value;
|
||||||
|
return;
|
||||||
|
case 66:
|
||||||
|
Element66 = value;
|
||||||
|
return;
|
||||||
|
case 67:
|
||||||
|
Element67 = value;
|
||||||
|
return;
|
||||||
|
case 68:
|
||||||
|
Element68 = value;
|
||||||
|
return;
|
||||||
|
case 69:
|
||||||
|
Element69 = value;
|
||||||
|
return;
|
||||||
|
case 70:
|
||||||
|
Element70 = value;
|
||||||
|
return;
|
||||||
|
case 71:
|
||||||
|
Element71 = value;
|
||||||
|
return;
|
||||||
|
case 72:
|
||||||
|
Element72 = value;
|
||||||
|
return;
|
||||||
|
case 73:
|
||||||
|
Element73 = value;
|
||||||
|
return;
|
||||||
|
case 74:
|
||||||
|
Element74 = value;
|
||||||
|
return;
|
||||||
|
case 75:
|
||||||
|
Element75 = value;
|
||||||
|
return;
|
||||||
|
case 76:
|
||||||
|
Element76 = value;
|
||||||
|
return;
|
||||||
|
case 77:
|
||||||
|
Element77 = value;
|
||||||
|
return;
|
||||||
|
case 78:
|
||||||
|
Element78 = value;
|
||||||
|
return;
|
||||||
|
case 79:
|
||||||
|
Element79 = value;
|
||||||
|
return;
|
||||||
|
case 80:
|
||||||
|
Element80 = value;
|
||||||
|
return;
|
||||||
|
case 81:
|
||||||
|
Element81 = value;
|
||||||
|
return;
|
||||||
|
case 82:
|
||||||
|
Element82 = value;
|
||||||
|
return;
|
||||||
|
case 83:
|
||||||
|
Element83 = value;
|
||||||
|
return;
|
||||||
|
case 84:
|
||||||
|
Element84 = value;
|
||||||
|
return;
|
||||||
|
case 85:
|
||||||
|
Element85 = value;
|
||||||
|
return;
|
||||||
|
case 86:
|
||||||
|
Element86 = value;
|
||||||
|
return;
|
||||||
|
case 87:
|
||||||
|
Element87 = value;
|
||||||
|
return;
|
||||||
|
case 88:
|
||||||
|
Element88 = value;
|
||||||
|
return;
|
||||||
|
case 89:
|
||||||
|
Element89 = value;
|
||||||
|
return;
|
||||||
|
case 90:
|
||||||
|
Element90 = value;
|
||||||
|
return;
|
||||||
|
case 91:
|
||||||
|
Element91 = value;
|
||||||
|
return;
|
||||||
|
case 92:
|
||||||
|
Element92 = value;
|
||||||
|
return;
|
||||||
|
case 93:
|
||||||
|
Element93 = value;
|
||||||
|
return;
|
||||||
|
case 94:
|
||||||
|
Element94 = value;
|
||||||
|
return;
|
||||||
|
case 95:
|
||||||
|
Element95 = value;
|
||||||
|
return;
|
||||||
|
case 96:
|
||||||
|
Element96 = value;
|
||||||
|
return;
|
||||||
|
case 97:
|
||||||
|
Element97 = value;
|
||||||
|
return;
|
||||||
|
case 98:
|
||||||
|
Element98 = value;
|
||||||
|
return;
|
||||||
|
case 99:
|
||||||
|
Element99 = value;
|
||||||
|
return;
|
||||||
|
case 100:
|
||||||
|
Element100 = value;
|
||||||
|
return;
|
||||||
|
case 101:
|
||||||
|
Element101 = value;
|
||||||
|
return;
|
||||||
|
case 102:
|
||||||
|
Element102 = value;
|
||||||
|
return;
|
||||||
|
case 103:
|
||||||
|
Element103 = value;
|
||||||
|
return;
|
||||||
|
case 104:
|
||||||
|
Element104 = value;
|
||||||
|
return;
|
||||||
|
case 105:
|
||||||
|
Element105 = value;
|
||||||
|
return;
|
||||||
|
case 106:
|
||||||
|
Element106 = value;
|
||||||
|
return;
|
||||||
|
case 107:
|
||||||
|
Element107 = value;
|
||||||
|
return;
|
||||||
|
case 108:
|
||||||
|
Element108 = value;
|
||||||
|
return;
|
||||||
|
case 109:
|
||||||
|
Element109 = value;
|
||||||
|
return;
|
||||||
|
case 110:
|
||||||
|
Element110 = value;
|
||||||
|
return;
|
||||||
|
case 111:
|
||||||
|
Element111 = value;
|
||||||
|
return;
|
||||||
|
case 112:
|
||||||
|
Element112 = value;
|
||||||
|
return;
|
||||||
|
case 113:
|
||||||
|
Element113 = value;
|
||||||
|
return;
|
||||||
|
case 114:
|
||||||
|
Element114 = value;
|
||||||
|
return;
|
||||||
|
case 115:
|
||||||
|
Element115 = value;
|
||||||
|
return;
|
||||||
|
case 116:
|
||||||
|
Element116 = value;
|
||||||
|
return;
|
||||||
|
case 117:
|
||||||
|
Element117 = value;
|
||||||
|
return;
|
||||||
|
case 118:
|
||||||
|
Element118 = value;
|
||||||
|
return;
|
||||||
|
case 119:
|
||||||
|
Element119 = value;
|
||||||
|
return;
|
||||||
|
case 120:
|
||||||
|
Element120 = value;
|
||||||
|
return;
|
||||||
|
case 121:
|
||||||
|
Element121 = value;
|
||||||
|
return;
|
||||||
|
case 122:
|
||||||
|
Element122 = value;
|
||||||
|
return;
|
||||||
|
case 123:
|
||||||
|
Element123 = value;
|
||||||
|
return;
|
||||||
|
case 124:
|
||||||
|
Element124 = value;
|
||||||
|
return;
|
||||||
|
case 125:
|
||||||
|
Element125 = value;
|
||||||
|
return;
|
||||||
|
case 126:
|
||||||
|
Element126 = value;
|
||||||
|
return;
|
||||||
|
case 127:
|
||||||
|
Element127 = value;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
// ILGPU kernels cannot throw exceptions, and callers guarantee the index range.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int GetScalarBitLength(ulong value)
|
||||||
|
{
|
||||||
|
if (value == 0UL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 64 - XMath.LeadingZeroCount(value);
|
||||||
|
}
|
||||||
|
|
||||||
public static readonly GpuUInt128 Zero = new();
|
public static readonly GpuUInt128 Zero = new();
|
||||||
public static readonly GpuUInt128 One = new(1UL);
|
public static readonly GpuUInt128 One = new(1UL);
|
||||||
|
|
||||||
@@ -423,7 +1109,7 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
|
|||||||
return new GpuUInt128(1UL);
|
return new GpuUInt128(1UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
Span<GpuUInt128> oddPowers = stackalloc GpuUInt128[Pow2WindowOddPowerCount];
|
Pow2OddPowerTable oddPowers = default;
|
||||||
GpuUInt128 power = new GpuUInt128(1UL);
|
GpuUInt128 power = new GpuUInt128(1UL);
|
||||||
int oddIndex = 0;
|
int oddIndex = 0;
|
||||||
|
|
||||||
@@ -437,12 +1123,13 @@ public struct GpuUInt128 : IComparable<GpuUInt128>, IEquatable<GpuUInt128>
|
|||||||
|
|
||||||
if ((bit & 1) != 0)
|
if ((bit & 1) != 0)
|
||||||
{
|
{
|
||||||
oddPowers[oddIndex++] = power;
|
oddPowers[oddIndex] = power;
|
||||||
|
oddIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GpuUInt128 result = new GpuUInt128(1UL);
|
GpuUInt128 result = new GpuUInt128(1UL);
|
||||||
int bitLength = BitOperations.Log2(exponent) + 1;
|
int bitLength = GetScalarBitLength(exponent);
|
||||||
int index = bitLength - 1;
|
int index = bitLength - 1;
|
||||||
|
|
||||||
while (index >= 0)
|
while (index >= 0)
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ using CycleRemainderStepper = PerfectNumbers.Core.CycleRemainderStepper;
|
|||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scans Mersenne divisors on the GPU for prime exponents p >= 31 using per-divisor Montgomery data.
|
||||||
|
/// </summary>
|
||||||
public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDivisorByDivisorTester
|
public sealed class MersenneNumberDivisorByDivisorGpuTester : IMersenneNumberDivisorByDivisorTester
|
||||||
{
|
{
|
||||||
private int _gpuBatchSize = GpuConstants.ScanBatchSize;
|
private int _gpuBatchSize = GpuConstants.ScanBatchSize;
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ using ILGPU.Runtime;
|
|||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides GPU-accelerated divisibility checks for Mersenne numbers with prime exponents p >= 31.
|
||||||
|
/// </summary>
|
||||||
public sealed class MersenneNumberDivisorGpuTester
|
public sealed class MersenneNumberDivisorGpuTester
|
||||||
{
|
{
|
||||||
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, GpuUInt128, ArrayView<byte>>> _kernelCache = new();
|
private readonly ConcurrentDictionary<Accelerator, Action<Index1D, ulong, GpuUInt128, ArrayView<byte>>> _kernelCache = new();
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using System.Buffers;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using ILGPU.Runtime;
|
|
||||||
|
|
||||||
namespace PerfectNumbers.Core.Gpu;
|
namespace PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses GPU kernels to incrementally scan Mersenne candidates for prime exponents p >= 31.
|
||||||
|
/// </summary>
|
||||||
public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool useGpuOrder)
|
public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool useGpuOrder)
|
||||||
{
|
{
|
||||||
private readonly GpuKernelType _kernelType = kernelType;
|
private readonly GpuKernelType _kernelType = kernelType;
|
||||||
@@ -11,94 +12,6 @@ public class MersenneNumberIncrementalGpuTester(GpuKernelType kernelType, bool u
|
|||||||
|
|
||||||
public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime)
|
public void Scan(ulong exponent, UInt128 twoP, bool lastIsSeven, UInt128 maxK, ref bool isPrime)
|
||||||
{
|
{
|
||||||
var gpuLease = GpuKernelPool.GetKernel(_useGpuOrder);
|
throw new NotImplementedException($"GPU incremental scanning requires the device cycle heuristics implementation (kernel: {_kernelType}, GPU order: {_useGpuOrder}).");
|
||||||
var execution = gpuLease.EnterExecutionScope();
|
|
||||||
var accelerator = gpuLease.Accelerator;
|
|
||||||
var stream = gpuLease.Stream;
|
|
||||||
int batchSize = GpuConstants.ScanBatchSize;
|
|
||||||
UInt128 kStart = 1UL;
|
|
||||||
ulong divMul = (ulong)((((UInt128)1 << 64) - UInt128.One) / exponent) + 1UL;
|
|
||||||
byte last = lastIsSeven ? (byte)1 : (byte)0;
|
|
||||||
|
|
||||||
var pow2Kernel = gpuLease.Pow2ModKernel; // TODO: Route this binding to the ProcessEightBitWindows kernel once the scalar helper lands so GPU incremental scans inherit the windowed speedup from GpuPow2ModBenchmarks.
|
|
||||||
var incKernel = gpuLease.IncrementalKernel;
|
|
||||||
exponent.Mod10_8_5_3Steps(out ulong step10, out ulong step8, out ulong step5, out ulong step3);
|
|
||||||
GpuUInt128 twoPGpu = (GpuUInt128)twoP;
|
|
||||||
var smallCyclesView = GpuKernelPool.EnsureSmallCyclesOnDevice(accelerator);
|
|
||||||
ResiduePrimeViews primeViews = default;
|
|
||||||
if (_kernelType == GpuKernelType.Pow2Mod)
|
|
||||||
{
|
|
||||||
primeViews = GpuKernelPool.EnsureSmallPrimesOnDevice(accelerator);
|
|
||||||
}
|
|
||||||
|
|
||||||
var orderBuffer = accelerator.Allocate1D<ulong>(batchSize);
|
|
||||||
ulong[] orderArray = ArrayPool<ulong>.Shared.Rent(batchSize);
|
|
||||||
UInt128 remaining;
|
|
||||||
int currentSize;
|
|
||||||
int i;
|
|
||||||
UInt128 q = UInt128.Zero;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
while (kStart <= maxK && Volatile.Read(ref isPrime))
|
|
||||||
{
|
|
||||||
remaining = maxK - kStart + UInt128.One;
|
|
||||||
currentSize = remaining > (UInt128)batchSize ? batchSize : (int)remaining;
|
|
||||||
Span<ulong> orders = orderArray.AsSpan(0, currentSize);
|
|
||||||
UInt128 q0 = twoP * kStart + UInt128.One;
|
|
||||||
// TODO: Swap this multiply-and-add initialization for the divisor-cycle stepping helper so the GPU incremental path reuses cached offsets instead of recomputing twoP multiples every batch.
|
|
||||||
|
|
||||||
if (_kernelType == GpuKernelType.Pow2Mod)
|
|
||||||
{
|
|
||||||
q0.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
|
||||||
var kernelArgs = new ResidueAutomatonArgs(q0m10, step10, q0m8, step8, q0m3, step3, q0m5, step5);
|
|
||||||
pow2Kernel(stream, currentSize, exponent, twoPGpu, (GpuUInt128)kStart, last, divMul,
|
|
||||||
kernelArgs, orderBuffer.View, smallCyclesView, primeViews.LastOne, primeViews.LastSeven,
|
|
||||||
primeViews.LastOnePow2, primeViews.LastSevenPow2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q0.Mod10_8_5_3(out ulong q0m10, out ulong q0m8, out ulong q0m5, out ulong q0m3);
|
|
||||||
incKernel(stream, currentSize, exponent, twoPGpu, (GpuUInt128)kStart, last, divMul,
|
|
||||||
q0m10, q0m8, q0m3, q0m5, orderBuffer.View, smallCyclesView);
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.Synchronize();
|
|
||||||
orderBuffer.View.CopyToCPU(ref MemoryMarshal.GetReference(orders), currentSize);
|
|
||||||
if (_kernelType == GpuKernelType.Pow2Mod)
|
|
||||||
{
|
|
||||||
for (i = 0; i < currentSize; i++)
|
|
||||||
{
|
|
||||||
if (orders[i] != 0UL)
|
|
||||||
{
|
|
||||||
Volatile.Write(ref isPrime, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
q = twoP * kStart + UInt128.One;
|
|
||||||
// TODO: Replace this per-lane multiplication and the subsequent q += twoP stride with the shared divisor-cycle ladder so each iteration advances by cached cycle increments and automatically triggers on-demand GPU computations when the snapshot lacks the requested cycle.
|
|
||||||
for (i = 0; i < currentSize && Volatile.Read(ref isPrime); i++, q += twoP)
|
|
||||||
{
|
|
||||||
if (orders[i] != 0UL && q.IsPrimeCandidate())
|
|
||||||
{
|
|
||||||
Volatile.Write(ref isPrime, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kStart += (UInt128)currentSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
ArrayPool<ulong>.Shared.Return(orderArray);
|
|
||||||
orderBuffer.Dispose();
|
|
||||||
execution.Dispose();
|
|
||||||
gpuLease.Dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
private static readonly ConcurrentDictionary<Accelerator, OrderKernelLauncher> OrderKernelCache = new();
|
private static readonly ConcurrentDictionary<Accelerator, OrderKernelLauncher> OrderKernelCache = new();
|
||||||
private static readonly ConcurrentDictionary<Accelerator, SmallPrimeDeviceCache> SmallPrimeDeviceCaches = new();
|
private static readonly ConcurrentDictionary<Accelerator, SmallPrimeDeviceCache> SmallPrimeDeviceCaches = new();
|
||||||
|
|
||||||
private readonly struct OrderKernelConfig
|
public readonly struct OrderKernelConfig
|
||||||
{
|
{
|
||||||
public OrderKernelConfig(ulong previousOrder, byte hasPreviousOrder, uint smallFactorLimit, int maxPowChecks, int mode)
|
public OrderKernelConfig(ulong previousOrder, byte hasPreviousOrder, uint smallFactorLimit, int maxPowChecks, int mode)
|
||||||
{
|
{
|
||||||
@@ -48,7 +48,7 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
public int Mode { get; }
|
public int Mode { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly struct OrderKernelBuffers
|
public readonly struct OrderKernelBuffers
|
||||||
{
|
{
|
||||||
public OrderKernelBuffers(
|
public OrderKernelBuffers(
|
||||||
ArrayView1D<ulong, Stride1D.Dense> phiFactors,
|
ArrayView1D<ulong, Stride1D.Dense> phiFactors,
|
||||||
@@ -125,10 +125,678 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
private const int GpuSmallPrimeFactorSlots = 64;
|
private const int GpuSmallPrimeFactorSlots = 64;
|
||||||
|
|
||||||
|
|
||||||
[InlineArray(Pow2WindowOddPowerCount)]
|
|
||||||
private struct Pow2OddPowerTable
|
private struct Pow2OddPowerTable
|
||||||
{
|
{
|
||||||
private GpuUInt128 _element0;
|
public GpuUInt128 Element0;
|
||||||
|
public GpuUInt128 Element1;
|
||||||
|
public GpuUInt128 Element2;
|
||||||
|
public GpuUInt128 Element3;
|
||||||
|
public GpuUInt128 Element4;
|
||||||
|
public GpuUInt128 Element5;
|
||||||
|
public GpuUInt128 Element6;
|
||||||
|
public GpuUInt128 Element7;
|
||||||
|
public GpuUInt128 Element8;
|
||||||
|
public GpuUInt128 Element9;
|
||||||
|
public GpuUInt128 Element10;
|
||||||
|
public GpuUInt128 Element11;
|
||||||
|
public GpuUInt128 Element12;
|
||||||
|
public GpuUInt128 Element13;
|
||||||
|
public GpuUInt128 Element14;
|
||||||
|
public GpuUInt128 Element15;
|
||||||
|
public GpuUInt128 Element16;
|
||||||
|
public GpuUInt128 Element17;
|
||||||
|
public GpuUInt128 Element18;
|
||||||
|
public GpuUInt128 Element19;
|
||||||
|
public GpuUInt128 Element20;
|
||||||
|
public GpuUInt128 Element21;
|
||||||
|
public GpuUInt128 Element22;
|
||||||
|
public GpuUInt128 Element23;
|
||||||
|
public GpuUInt128 Element24;
|
||||||
|
public GpuUInt128 Element25;
|
||||||
|
public GpuUInt128 Element26;
|
||||||
|
public GpuUInt128 Element27;
|
||||||
|
public GpuUInt128 Element28;
|
||||||
|
public GpuUInt128 Element29;
|
||||||
|
public GpuUInt128 Element30;
|
||||||
|
public GpuUInt128 Element31;
|
||||||
|
public GpuUInt128 Element32;
|
||||||
|
public GpuUInt128 Element33;
|
||||||
|
public GpuUInt128 Element34;
|
||||||
|
public GpuUInt128 Element35;
|
||||||
|
public GpuUInt128 Element36;
|
||||||
|
public GpuUInt128 Element37;
|
||||||
|
public GpuUInt128 Element38;
|
||||||
|
public GpuUInt128 Element39;
|
||||||
|
public GpuUInt128 Element40;
|
||||||
|
public GpuUInt128 Element41;
|
||||||
|
public GpuUInt128 Element42;
|
||||||
|
public GpuUInt128 Element43;
|
||||||
|
public GpuUInt128 Element44;
|
||||||
|
public GpuUInt128 Element45;
|
||||||
|
public GpuUInt128 Element46;
|
||||||
|
public GpuUInt128 Element47;
|
||||||
|
public GpuUInt128 Element48;
|
||||||
|
public GpuUInt128 Element49;
|
||||||
|
public GpuUInt128 Element50;
|
||||||
|
public GpuUInt128 Element51;
|
||||||
|
public GpuUInt128 Element52;
|
||||||
|
public GpuUInt128 Element53;
|
||||||
|
public GpuUInt128 Element54;
|
||||||
|
public GpuUInt128 Element55;
|
||||||
|
public GpuUInt128 Element56;
|
||||||
|
public GpuUInt128 Element57;
|
||||||
|
public GpuUInt128 Element58;
|
||||||
|
public GpuUInt128 Element59;
|
||||||
|
public GpuUInt128 Element60;
|
||||||
|
public GpuUInt128 Element61;
|
||||||
|
public GpuUInt128 Element62;
|
||||||
|
public GpuUInt128 Element63;
|
||||||
|
public GpuUInt128 Element64;
|
||||||
|
public GpuUInt128 Element65;
|
||||||
|
public GpuUInt128 Element66;
|
||||||
|
public GpuUInt128 Element67;
|
||||||
|
public GpuUInt128 Element68;
|
||||||
|
public GpuUInt128 Element69;
|
||||||
|
public GpuUInt128 Element70;
|
||||||
|
public GpuUInt128 Element71;
|
||||||
|
public GpuUInt128 Element72;
|
||||||
|
public GpuUInt128 Element73;
|
||||||
|
public GpuUInt128 Element74;
|
||||||
|
public GpuUInt128 Element75;
|
||||||
|
public GpuUInt128 Element76;
|
||||||
|
public GpuUInt128 Element77;
|
||||||
|
public GpuUInt128 Element78;
|
||||||
|
public GpuUInt128 Element79;
|
||||||
|
public GpuUInt128 Element80;
|
||||||
|
public GpuUInt128 Element81;
|
||||||
|
public GpuUInt128 Element82;
|
||||||
|
public GpuUInt128 Element83;
|
||||||
|
public GpuUInt128 Element84;
|
||||||
|
public GpuUInt128 Element85;
|
||||||
|
public GpuUInt128 Element86;
|
||||||
|
public GpuUInt128 Element87;
|
||||||
|
public GpuUInt128 Element88;
|
||||||
|
public GpuUInt128 Element89;
|
||||||
|
public GpuUInt128 Element90;
|
||||||
|
public GpuUInt128 Element91;
|
||||||
|
public GpuUInt128 Element92;
|
||||||
|
public GpuUInt128 Element93;
|
||||||
|
public GpuUInt128 Element94;
|
||||||
|
public GpuUInt128 Element95;
|
||||||
|
public GpuUInt128 Element96;
|
||||||
|
public GpuUInt128 Element97;
|
||||||
|
public GpuUInt128 Element98;
|
||||||
|
public GpuUInt128 Element99;
|
||||||
|
public GpuUInt128 Element100;
|
||||||
|
public GpuUInt128 Element101;
|
||||||
|
public GpuUInt128 Element102;
|
||||||
|
public GpuUInt128 Element103;
|
||||||
|
public GpuUInt128 Element104;
|
||||||
|
public GpuUInt128 Element105;
|
||||||
|
public GpuUInt128 Element106;
|
||||||
|
public GpuUInt128 Element107;
|
||||||
|
public GpuUInt128 Element108;
|
||||||
|
public GpuUInt128 Element109;
|
||||||
|
public GpuUInt128 Element110;
|
||||||
|
public GpuUInt128 Element111;
|
||||||
|
public GpuUInt128 Element112;
|
||||||
|
public GpuUInt128 Element113;
|
||||||
|
public GpuUInt128 Element114;
|
||||||
|
public GpuUInt128 Element115;
|
||||||
|
public GpuUInt128 Element116;
|
||||||
|
public GpuUInt128 Element117;
|
||||||
|
public GpuUInt128 Element118;
|
||||||
|
public GpuUInt128 Element119;
|
||||||
|
public GpuUInt128 Element120;
|
||||||
|
public GpuUInt128 Element121;
|
||||||
|
public GpuUInt128 Element122;
|
||||||
|
public GpuUInt128 Element123;
|
||||||
|
public GpuUInt128 Element124;
|
||||||
|
public GpuUInt128 Element125;
|
||||||
|
public GpuUInt128 Element126;
|
||||||
|
public GpuUInt128 Element127;
|
||||||
|
|
||||||
|
public GpuUInt128 this[int index]
|
||||||
|
{
|
||||||
|
readonly get
|
||||||
|
{
|
||||||
|
return GetElement(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetElement(index, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private readonly GpuUInt128 GetElement(int index) => index switch
|
||||||
|
{
|
||||||
|
0 => Element0,
|
||||||
|
1 => Element1,
|
||||||
|
2 => Element2,
|
||||||
|
3 => Element3,
|
||||||
|
4 => Element4,
|
||||||
|
5 => Element5,
|
||||||
|
6 => Element6,
|
||||||
|
7 => Element7,
|
||||||
|
8 => Element8,
|
||||||
|
9 => Element9,
|
||||||
|
10 => Element10,
|
||||||
|
11 => Element11,
|
||||||
|
12 => Element12,
|
||||||
|
13 => Element13,
|
||||||
|
14 => Element14,
|
||||||
|
15 => Element15,
|
||||||
|
16 => Element16,
|
||||||
|
17 => Element17,
|
||||||
|
18 => Element18,
|
||||||
|
19 => Element19,
|
||||||
|
20 => Element20,
|
||||||
|
21 => Element21,
|
||||||
|
22 => Element22,
|
||||||
|
23 => Element23,
|
||||||
|
24 => Element24,
|
||||||
|
25 => Element25,
|
||||||
|
26 => Element26,
|
||||||
|
27 => Element27,
|
||||||
|
28 => Element28,
|
||||||
|
29 => Element29,
|
||||||
|
30 => Element30,
|
||||||
|
31 => Element31,
|
||||||
|
32 => Element32,
|
||||||
|
33 => Element33,
|
||||||
|
34 => Element34,
|
||||||
|
35 => Element35,
|
||||||
|
36 => Element36,
|
||||||
|
37 => Element37,
|
||||||
|
38 => Element38,
|
||||||
|
39 => Element39,
|
||||||
|
40 => Element40,
|
||||||
|
41 => Element41,
|
||||||
|
42 => Element42,
|
||||||
|
43 => Element43,
|
||||||
|
44 => Element44,
|
||||||
|
45 => Element45,
|
||||||
|
46 => Element46,
|
||||||
|
47 => Element47,
|
||||||
|
48 => Element48,
|
||||||
|
49 => Element49,
|
||||||
|
50 => Element50,
|
||||||
|
51 => Element51,
|
||||||
|
52 => Element52,
|
||||||
|
53 => Element53,
|
||||||
|
54 => Element54,
|
||||||
|
55 => Element55,
|
||||||
|
56 => Element56,
|
||||||
|
57 => Element57,
|
||||||
|
58 => Element58,
|
||||||
|
59 => Element59,
|
||||||
|
60 => Element60,
|
||||||
|
61 => Element61,
|
||||||
|
62 => Element62,
|
||||||
|
63 => Element63,
|
||||||
|
64 => Element64,
|
||||||
|
65 => Element65,
|
||||||
|
66 => Element66,
|
||||||
|
67 => Element67,
|
||||||
|
68 => Element68,
|
||||||
|
69 => Element69,
|
||||||
|
70 => Element70,
|
||||||
|
71 => Element71,
|
||||||
|
72 => Element72,
|
||||||
|
73 => Element73,
|
||||||
|
74 => Element74,
|
||||||
|
75 => Element75,
|
||||||
|
76 => Element76,
|
||||||
|
77 => Element77,
|
||||||
|
78 => Element78,
|
||||||
|
79 => Element79,
|
||||||
|
80 => Element80,
|
||||||
|
81 => Element81,
|
||||||
|
82 => Element82,
|
||||||
|
83 => Element83,
|
||||||
|
84 => Element84,
|
||||||
|
85 => Element85,
|
||||||
|
86 => Element86,
|
||||||
|
87 => Element87,
|
||||||
|
88 => Element88,
|
||||||
|
89 => Element89,
|
||||||
|
90 => Element90,
|
||||||
|
91 => Element91,
|
||||||
|
92 => Element92,
|
||||||
|
93 => Element93,
|
||||||
|
94 => Element94,
|
||||||
|
95 => Element95,
|
||||||
|
96 => Element96,
|
||||||
|
97 => Element97,
|
||||||
|
98 => Element98,
|
||||||
|
99 => Element99,
|
||||||
|
100 => Element100,
|
||||||
|
101 => Element101,
|
||||||
|
102 => Element102,
|
||||||
|
103 => Element103,
|
||||||
|
104 => Element104,
|
||||||
|
105 => Element105,
|
||||||
|
106 => Element106,
|
||||||
|
107 => Element107,
|
||||||
|
108 => Element108,
|
||||||
|
109 => Element109,
|
||||||
|
110 => Element110,
|
||||||
|
111 => Element111,
|
||||||
|
112 => Element112,
|
||||||
|
113 => Element113,
|
||||||
|
114 => Element114,
|
||||||
|
115 => Element115,
|
||||||
|
116 => Element116,
|
||||||
|
117 => Element117,
|
||||||
|
118 => Element118,
|
||||||
|
119 => Element119,
|
||||||
|
120 => Element120,
|
||||||
|
121 => Element121,
|
||||||
|
122 => Element122,
|
||||||
|
123 => Element123,
|
||||||
|
124 => Element124,
|
||||||
|
125 => Element125,
|
||||||
|
126 => Element126,
|
||||||
|
127 => Element127,
|
||||||
|
_ => Element0,
|
||||||
|
};
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private void SetElement(int index, GpuUInt128 value)
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Element0 = value;
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
Element1 = value;
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
Element2 = value;
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
Element3 = value;
|
||||||
|
return;
|
||||||
|
case 4:
|
||||||
|
Element4 = value;
|
||||||
|
return;
|
||||||
|
case 5:
|
||||||
|
Element5 = value;
|
||||||
|
return;
|
||||||
|
case 6:
|
||||||
|
Element6 = value;
|
||||||
|
return;
|
||||||
|
case 7:
|
||||||
|
Element7 = value;
|
||||||
|
return;
|
||||||
|
case 8:
|
||||||
|
Element8 = value;
|
||||||
|
return;
|
||||||
|
case 9:
|
||||||
|
Element9 = value;
|
||||||
|
return;
|
||||||
|
case 10:
|
||||||
|
Element10 = value;
|
||||||
|
return;
|
||||||
|
case 11:
|
||||||
|
Element11 = value;
|
||||||
|
return;
|
||||||
|
case 12:
|
||||||
|
Element12 = value;
|
||||||
|
return;
|
||||||
|
case 13:
|
||||||
|
Element13 = value;
|
||||||
|
return;
|
||||||
|
case 14:
|
||||||
|
Element14 = value;
|
||||||
|
return;
|
||||||
|
case 15:
|
||||||
|
Element15 = value;
|
||||||
|
return;
|
||||||
|
case 16:
|
||||||
|
Element16 = value;
|
||||||
|
return;
|
||||||
|
case 17:
|
||||||
|
Element17 = value;
|
||||||
|
return;
|
||||||
|
case 18:
|
||||||
|
Element18 = value;
|
||||||
|
return;
|
||||||
|
case 19:
|
||||||
|
Element19 = value;
|
||||||
|
return;
|
||||||
|
case 20:
|
||||||
|
Element20 = value;
|
||||||
|
return;
|
||||||
|
case 21:
|
||||||
|
Element21 = value;
|
||||||
|
return;
|
||||||
|
case 22:
|
||||||
|
Element22 = value;
|
||||||
|
return;
|
||||||
|
case 23:
|
||||||
|
Element23 = value;
|
||||||
|
return;
|
||||||
|
case 24:
|
||||||
|
Element24 = value;
|
||||||
|
return;
|
||||||
|
case 25:
|
||||||
|
Element25 = value;
|
||||||
|
return;
|
||||||
|
case 26:
|
||||||
|
Element26 = value;
|
||||||
|
return;
|
||||||
|
case 27:
|
||||||
|
Element27 = value;
|
||||||
|
return;
|
||||||
|
case 28:
|
||||||
|
Element28 = value;
|
||||||
|
return;
|
||||||
|
case 29:
|
||||||
|
Element29 = value;
|
||||||
|
return;
|
||||||
|
case 30:
|
||||||
|
Element30 = value;
|
||||||
|
return;
|
||||||
|
case 31:
|
||||||
|
Element31 = value;
|
||||||
|
return;
|
||||||
|
case 32:
|
||||||
|
Element32 = value;
|
||||||
|
return;
|
||||||
|
case 33:
|
||||||
|
Element33 = value;
|
||||||
|
return;
|
||||||
|
case 34:
|
||||||
|
Element34 = value;
|
||||||
|
return;
|
||||||
|
case 35:
|
||||||
|
Element35 = value;
|
||||||
|
return;
|
||||||
|
case 36:
|
||||||
|
Element36 = value;
|
||||||
|
return;
|
||||||
|
case 37:
|
||||||
|
Element37 = value;
|
||||||
|
return;
|
||||||
|
case 38:
|
||||||
|
Element38 = value;
|
||||||
|
return;
|
||||||
|
case 39:
|
||||||
|
Element39 = value;
|
||||||
|
return;
|
||||||
|
case 40:
|
||||||
|
Element40 = value;
|
||||||
|
return;
|
||||||
|
case 41:
|
||||||
|
Element41 = value;
|
||||||
|
return;
|
||||||
|
case 42:
|
||||||
|
Element42 = value;
|
||||||
|
return;
|
||||||
|
case 43:
|
||||||
|
Element43 = value;
|
||||||
|
return;
|
||||||
|
case 44:
|
||||||
|
Element44 = value;
|
||||||
|
return;
|
||||||
|
case 45:
|
||||||
|
Element45 = value;
|
||||||
|
return;
|
||||||
|
case 46:
|
||||||
|
Element46 = value;
|
||||||
|
return;
|
||||||
|
case 47:
|
||||||
|
Element47 = value;
|
||||||
|
return;
|
||||||
|
case 48:
|
||||||
|
Element48 = value;
|
||||||
|
return;
|
||||||
|
case 49:
|
||||||
|
Element49 = value;
|
||||||
|
return;
|
||||||
|
case 50:
|
||||||
|
Element50 = value;
|
||||||
|
return;
|
||||||
|
case 51:
|
||||||
|
Element51 = value;
|
||||||
|
return;
|
||||||
|
case 52:
|
||||||
|
Element52 = value;
|
||||||
|
return;
|
||||||
|
case 53:
|
||||||
|
Element53 = value;
|
||||||
|
return;
|
||||||
|
case 54:
|
||||||
|
Element54 = value;
|
||||||
|
return;
|
||||||
|
case 55:
|
||||||
|
Element55 = value;
|
||||||
|
return;
|
||||||
|
case 56:
|
||||||
|
Element56 = value;
|
||||||
|
return;
|
||||||
|
case 57:
|
||||||
|
Element57 = value;
|
||||||
|
return;
|
||||||
|
case 58:
|
||||||
|
Element58 = value;
|
||||||
|
return;
|
||||||
|
case 59:
|
||||||
|
Element59 = value;
|
||||||
|
return;
|
||||||
|
case 60:
|
||||||
|
Element60 = value;
|
||||||
|
return;
|
||||||
|
case 61:
|
||||||
|
Element61 = value;
|
||||||
|
return;
|
||||||
|
case 62:
|
||||||
|
Element62 = value;
|
||||||
|
return;
|
||||||
|
case 63:
|
||||||
|
Element63 = value;
|
||||||
|
return;
|
||||||
|
case 64:
|
||||||
|
Element64 = value;
|
||||||
|
return;
|
||||||
|
case 65:
|
||||||
|
Element65 = value;
|
||||||
|
return;
|
||||||
|
case 66:
|
||||||
|
Element66 = value;
|
||||||
|
return;
|
||||||
|
case 67:
|
||||||
|
Element67 = value;
|
||||||
|
return;
|
||||||
|
case 68:
|
||||||
|
Element68 = value;
|
||||||
|
return;
|
||||||
|
case 69:
|
||||||
|
Element69 = value;
|
||||||
|
return;
|
||||||
|
case 70:
|
||||||
|
Element70 = value;
|
||||||
|
return;
|
||||||
|
case 71:
|
||||||
|
Element71 = value;
|
||||||
|
return;
|
||||||
|
case 72:
|
||||||
|
Element72 = value;
|
||||||
|
return;
|
||||||
|
case 73:
|
||||||
|
Element73 = value;
|
||||||
|
return;
|
||||||
|
case 74:
|
||||||
|
Element74 = value;
|
||||||
|
return;
|
||||||
|
case 75:
|
||||||
|
Element75 = value;
|
||||||
|
return;
|
||||||
|
case 76:
|
||||||
|
Element76 = value;
|
||||||
|
return;
|
||||||
|
case 77:
|
||||||
|
Element77 = value;
|
||||||
|
return;
|
||||||
|
case 78:
|
||||||
|
Element78 = value;
|
||||||
|
return;
|
||||||
|
case 79:
|
||||||
|
Element79 = value;
|
||||||
|
return;
|
||||||
|
case 80:
|
||||||
|
Element80 = value;
|
||||||
|
return;
|
||||||
|
case 81:
|
||||||
|
Element81 = value;
|
||||||
|
return;
|
||||||
|
case 82:
|
||||||
|
Element82 = value;
|
||||||
|
return;
|
||||||
|
case 83:
|
||||||
|
Element83 = value;
|
||||||
|
return;
|
||||||
|
case 84:
|
||||||
|
Element84 = value;
|
||||||
|
return;
|
||||||
|
case 85:
|
||||||
|
Element85 = value;
|
||||||
|
return;
|
||||||
|
case 86:
|
||||||
|
Element86 = value;
|
||||||
|
return;
|
||||||
|
case 87:
|
||||||
|
Element87 = value;
|
||||||
|
return;
|
||||||
|
case 88:
|
||||||
|
Element88 = value;
|
||||||
|
return;
|
||||||
|
case 89:
|
||||||
|
Element89 = value;
|
||||||
|
return;
|
||||||
|
case 90:
|
||||||
|
Element90 = value;
|
||||||
|
return;
|
||||||
|
case 91:
|
||||||
|
Element91 = value;
|
||||||
|
return;
|
||||||
|
case 92:
|
||||||
|
Element92 = value;
|
||||||
|
return;
|
||||||
|
case 93:
|
||||||
|
Element93 = value;
|
||||||
|
return;
|
||||||
|
case 94:
|
||||||
|
Element94 = value;
|
||||||
|
return;
|
||||||
|
case 95:
|
||||||
|
Element95 = value;
|
||||||
|
return;
|
||||||
|
case 96:
|
||||||
|
Element96 = value;
|
||||||
|
return;
|
||||||
|
case 97:
|
||||||
|
Element97 = value;
|
||||||
|
return;
|
||||||
|
case 98:
|
||||||
|
Element98 = value;
|
||||||
|
return;
|
||||||
|
case 99:
|
||||||
|
Element99 = value;
|
||||||
|
return;
|
||||||
|
case 100:
|
||||||
|
Element100 = value;
|
||||||
|
return;
|
||||||
|
case 101:
|
||||||
|
Element101 = value;
|
||||||
|
return;
|
||||||
|
case 102:
|
||||||
|
Element102 = value;
|
||||||
|
return;
|
||||||
|
case 103:
|
||||||
|
Element103 = value;
|
||||||
|
return;
|
||||||
|
case 104:
|
||||||
|
Element104 = value;
|
||||||
|
return;
|
||||||
|
case 105:
|
||||||
|
Element105 = value;
|
||||||
|
return;
|
||||||
|
case 106:
|
||||||
|
Element106 = value;
|
||||||
|
return;
|
||||||
|
case 107:
|
||||||
|
Element107 = value;
|
||||||
|
return;
|
||||||
|
case 108:
|
||||||
|
Element108 = value;
|
||||||
|
return;
|
||||||
|
case 109:
|
||||||
|
Element109 = value;
|
||||||
|
return;
|
||||||
|
case 110:
|
||||||
|
Element110 = value;
|
||||||
|
return;
|
||||||
|
case 111:
|
||||||
|
Element111 = value;
|
||||||
|
return;
|
||||||
|
case 112:
|
||||||
|
Element112 = value;
|
||||||
|
return;
|
||||||
|
case 113:
|
||||||
|
Element113 = value;
|
||||||
|
return;
|
||||||
|
case 114:
|
||||||
|
Element114 = value;
|
||||||
|
return;
|
||||||
|
case 115:
|
||||||
|
Element115 = value;
|
||||||
|
return;
|
||||||
|
case 116:
|
||||||
|
Element116 = value;
|
||||||
|
return;
|
||||||
|
case 117:
|
||||||
|
Element117 = value;
|
||||||
|
return;
|
||||||
|
case 118:
|
||||||
|
Element118 = value;
|
||||||
|
return;
|
||||||
|
case 119:
|
||||||
|
Element119 = value;
|
||||||
|
return;
|
||||||
|
case 120:
|
||||||
|
Element120 = value;
|
||||||
|
return;
|
||||||
|
case 121:
|
||||||
|
Element121 = value;
|
||||||
|
return;
|
||||||
|
case 122:
|
||||||
|
Element122 = value;
|
||||||
|
return;
|
||||||
|
case 123:
|
||||||
|
Element123 = value;
|
||||||
|
return;
|
||||||
|
case 124:
|
||||||
|
Element124 = value;
|
||||||
|
return;
|
||||||
|
case 125:
|
||||||
|
Element125 = value;
|
||||||
|
return;
|
||||||
|
case 126:
|
||||||
|
Element126 = value;
|
||||||
|
return;
|
||||||
|
case 127:
|
||||||
|
Element127 = value;
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
// ILGPU kernels cannot throw exceptions, and callers guarantee the index range.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
|
internal static ConcurrentDictionary<ulong, byte> OverflowRegistry => OverflowedPrimes;
|
||||||
@@ -1962,8 +2630,9 @@ internal static partial class PrimeOrderGpuHeuristics
|
|||||||
baseValue.MulMod(baseValue, modulus);
|
baseValue.MulMod(baseValue, modulus);
|
||||||
for (int i = 1; i < oddPowerCount; i++)
|
for (int i = 1; i < oddPowerCount; i++)
|
||||||
{
|
{
|
||||||
oddPowers[i] = oddPowers[i - 1];
|
GpuUInt128 ladderEntry = oddPowers[i - 1];
|
||||||
oddPowers[i].MulMod(baseValue, modulus);
|
ladderEntry.MulMod(baseValue, modulus);
|
||||||
|
oddPowers[i] = ladderEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<InternalsVisibleTo Include="EvenPerfectBitScanner.Tests" />
|
<InternalsVisibleTo Include="EvenPerfectBitScanner.Tests" />
|
||||||
<InternalsVisibleTo Include="PerfectNumbers.Core.Tests" />
|
<InternalsVisibleTo Include="PerfectNumbers.Core.Tests" />
|
||||||
|
<InternalsVisibleTo Include="ILGPURuntime" />
|
||||||
<InternalsVisibleTo Include="HeuristicMultiplyShiftTiming" />
|
<InternalsVisibleTo Include="HeuristicMultiplyShiftTiming" />
|
||||||
<InternalsVisibleTo Include="EvenPerfectBitScanner.Benchmarks" />
|
<InternalsVisibleTo Include="EvenPerfectBitScanner.Benchmarks" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
using ILGPU.Algorithms;
|
||||||
using PerfectNumbers.Core.Gpu;
|
using PerfectNumbers.Core.Gpu;
|
||||||
|
|
||||||
namespace PerfectNumbers.Core;
|
namespace PerfectNumbers.Core;
|
||||||
@@ -679,7 +680,8 @@ public static class ULongExtensions
|
|||||||
Element127 = value;
|
Element127 = value;
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentOutOfRangeException(nameof(index), index, "Pow2OddPowerTable index must be between 0 and 127.");
|
// ILGPU kernels cannot throw exceptions, and callers guarantee the index range.
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1011,7 +1013,7 @@ public static class ULongExtensions
|
|||||||
return Pow2MontgomeryModSingleBit(exponent, divisor, keepMontgomery);
|
return Pow2MontgomeryModSingleBit(exponent, divisor, keepMontgomery);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitLength = BitOperations.Log2(exponent) + 1;
|
int bitLength = GetPortableBitLength(exponent);
|
||||||
int windowSize = GetWindowSize(bitLength);
|
int windowSize = GetWindowSize(bitLength);
|
||||||
int oddPowerCount = 1 << (windowSize - 1);
|
int oddPowerCount = 1 << (windowSize - 1);
|
||||||
|
|
||||||
@@ -1093,6 +1095,16 @@ public static class ULongExtensions
|
|||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static int GetPortableBitLength(ulong value)
|
||||||
|
{
|
||||||
|
if (value == 0UL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 64 - XMath.LeadingZeroCount(value);
|
||||||
|
}
|
||||||
|
|
||||||
private static int GetWindowSize(int bitLength)
|
private static int GetWindowSize(int bitLength)
|
||||||
{
|
{
|
||||||
if (bitLength <= 6)
|
if (bitLength <= 6)
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
|
- Reimplement the GPU cycle heuristics for MersenneNumberIncrementalGpuTester and re-enable Scan_handles_various_prime_exponents once the device path is fixed.
|
||||||
- Extend the GPU numeric type probe to cover proposed custom types such as GpuUInt256 and GpuUInt512 once their definitions are available so we can plan the wide-order heuristics on the device.
|
- Extend the GPU numeric type probe to cover proposed custom types such as GpuUInt256 and GpuUInt512 once their definitions are available so we can plan the wide-order heuristics on the device.
|
||||||
Reference in new issue
Block a user