#r "nuget: ILGPU, 1.5.3" #r "nuget: PeterO.Numbers, 1.8.1" using System; using System.Numerics; using ILGPU; using ILGPU.Runtime; using ILGPU.Runtime.CPU; using PeterO.Numbers; var context = Context.CreateDefault(); var accelerator = context.CreateCPUAccelerator(0); try { Console.WriteLine("ILGPU numeric type support probe (CPU accelerator)"); Console.WriteLine(); ProbeResult[] results = [ ProbeBigInteger(accelerator), ProbeEInteger(accelerator), ProbeERational(accelerator) ]; foreach (ProbeResult result in results) { Console.WriteLine($"{result.Type}: {(result.Supported ? "supported" : "unsupported")}"); Console.WriteLine($" Details: {result.Details}"); Console.WriteLine(); } } finally { accelerator.Dispose(); context.Dispose(); } record ProbeResult(string Type, bool Supported, string Details) { public static ProbeResult Success(string type, string details) => new(type, true, details); public static ProbeResult Failure(string type, Exception exception) => new(type, false, $"{exception.GetType().Name}: {exception.Message}"); public static ProbeResult Failure(string type, string details) => new(type, false, details); } static ProbeResult ProbeBigInteger(Accelerator accelerator) { try { var kernel = accelerator.LoadAutoGroupedStreamKernel>(BigIntegerKernel); using var buffer = accelerator.Allocate1D(1); var extent = new Index1D((int)buffer.Length); kernel(extent, buffer.View); accelerator.Synchronize(); return ProbeResult.Success( "System.Numerics.BigInteger", "Addition, subtraction, multiplication, division, and modulo compile on the CPU accelerator."); } catch (Exception ex) { return ProbeResult.Failure("System.Numerics.BigInteger", ex); } } static ProbeResult ProbeEInteger(Accelerator accelerator) { try { var kernel = accelerator.LoadAutoGroupedStreamKernel>(EIntegerKernel); using var buffer = accelerator.Allocate1D(1); kernel(new Index1D((int)buffer.Length), buffer.View); accelerator.Synchronize(); return ProbeResult.Success( "PeterO.Numbers.EInteger", "Addition, subtraction, multiplication, division, and remainder compile on the CPU accelerator."); } catch (Exception ex) { return ProbeResult.Failure("PeterO.Numbers.EInteger", ex); } } static ProbeResult ProbeERational(Accelerator accelerator) { bool hasRemainder = HasERationalRemainder(); try { var kernel = accelerator.LoadAutoGroupedStreamKernel>(ERationalKernel); using var buffer = accelerator.Allocate1D(1); kernel(new Index1D((int)buffer.Length), buffer.View); accelerator.Synchronize(); string details = "Addition, subtraction, multiplication, and division compile on the CPU accelerator."; details += hasRemainder ? " ERational exposes a remainder API that requires further investigation." : " ERational does not expose a remainder/modulo API."; return ProbeResult.Success("PeterO.Numbers.ERational", details); } catch (Exception ex) { string details = $"{ex.GetType().Name}: {ex.Message}"; if (!hasRemainder) { details += " ERational does not expose a remainder/modulo API."; } return ProbeResult.Failure("PeterO.Numbers.ERational", details); } } static void BigIntegerKernel(Index1D index, ArrayView1D data) { BigInteger value = new BigInteger(data[index]); value += BigInteger.One; value -= BigInteger.One; value *= new BigInteger(2); value /= new BigInteger(3); value %= new BigInteger(5); int comparison = value.CompareTo(BigInteger.Zero); data[index] = comparison; } static void EIntegerKernel(Index1D index, ArrayView1D data) { EInteger value = EInteger.FromInt32(data[index]); value = value + EInteger.One; value = value - EInteger.One; value = value * EInteger.FromInt32(2); value = value.Divide(EInteger.FromInt32(3)); value = value.Remainder(EInteger.FromInt32(5)); int comparison = value.CompareTo(EInteger.Zero); data[index] = comparison; } static void ERationalKernel(Index1D index, ArrayView1D data) { ERational value = ERational.FromInt32(data[index]); ERational adjusted = (value + ERational.FromInt32(1)) - ERational.FromInt32(1); ERational product = adjusted * ERational.FromInt32(2); ERational quotient = product / ERational.FromInt32(3); int comparison = quotient.CompareTo(ERational.FromInt32(0)); data[index] = comparison; } static bool HasERationalRemainder() { foreach (var method in typeof(ERational).GetMethods()) { if (string.Equals(method.Name, "Remainder", StringComparison.Ordinal)) { return true; } } return false; }