diff --git a/Src/ILGPU.Algorithms/Random/RandomExtensions.cs b/Src/ILGPU.Algorithms/Random/RandomExtensions.cs index 579ed86fb..7d6ade8d9 100644 --- a/Src/ILGPU.Algorithms/Random/RandomExtensions.cs +++ b/Src/ILGPU.Algorithms/Random/RandomExtensions.cs @@ -10,8 +10,10 @@ // --------------------------------------------------------------------------------------- using ILGPU.Runtime; +using ILGPU.Util; using System; using System.Diagnostics; +using System.Numerics; using System.Runtime.CompilerServices; namespace ILGPU.Algorithms.Random @@ -49,7 +51,7 @@ internal static uint MergeULong(ulong nextULong) => /// /// Separates the given unsigned int into an unsigned long. /// - internal static ulong SeperateUInt(uint nextUInt) => + internal static ulong SeparateUInt(uint nextUInt) => ((ulong)nextUInt << 32) | nextUInt; /// @@ -91,8 +93,8 @@ internal static ulong ShiftState(ulong state, int laneShift) /// Generates a random int in [minValue..maxValue). /// /// The random provider. - /// The minimum value (inclusive) - /// The maximum values (exclusive) + /// The minimum value (inclusive). + /// The maximum values (exclusive). /// A random int in [minValue..maxValue). [MethodImpl(MethodImplOptions.AggressiveInlining)] public static float Next( @@ -112,8 +114,8 @@ public static float Next( /// Generates a random int in [minValue..maxValue). /// /// The random provider. - /// The minimum value (inclusive) - /// The maximum values (exclusive) + /// The minimum value (inclusive). + /// The maximum values (exclusive). /// A random int in [minValue..maxValue). [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double Next( @@ -133,8 +135,8 @@ public static double Next( /// Generates a random int in [minValue..maxValue). /// /// The random provider. - /// The minimum value (inclusive) - /// The maximum values (exclusive) + /// The minimum value (inclusive). + /// The maximum values (exclusive). /// A random int in [minValue..maxValue). [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Next( @@ -154,8 +156,8 @@ public static int Next( /// Generates a random long in [minValue..maxValue). /// /// The random provider. - /// The minimum value (inclusive) - /// The maximum values (exclusive) + /// The minimum value (inclusive). + /// The maximum values (exclusive). /// A random long in [minValue..maxValue). [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long Next( @@ -174,6 +176,74 @@ public static long Next( return Math.Min(intermediate + minValue, maxValue - 1); } +#if NET7_0_OR_GREATER + /// + /// Generates a new random vector containing provided RNG-based values. + /// + /// The vector element type. + /// The RNG provider type. + /// The generic RNG value range. + /// The random provider instance to use. + /// The generic range instance to use. + /// The created random vector. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector NextVector( + ref TRandomProvider randomProvider, + TRange range) + where T : unmanaged + where TRandomProvider : struct, IRandomProvider + where TRange : struct, IRandomRange + { + int vectorLength = Vector.Count; + int length = Interop.SizeOf() * vectorLength; + + // Allocate temporary buffers + var source = stackalloc byte[length + vectorLength]; + var span = new Span( + (void*)Interop.Align((long)source, length, vectorLength), + vectorLength); + + // Generated random numbers + for (int i = 0; i < vectorLength; ++i) + span[i] = range.Next(ref randomProvider); + + // Load aligned vector + return span.LoadAlignedVectorUnsafe(); + } + + /// + /// Generates a new random vector containing provided RNG-based values. + /// + /// The vector element type. + /// The RNG range provider. + /// The range provider instance to use. + /// The created random vector. + [CLSCompliant(false)] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe Vector NextVector( + ref TRangeProvider rangeProvider) + where T : unmanaged + where TRangeProvider : struct, IRandomRangeProvider + { + int vectorLength = Vector.Count; + int length = Interop.SizeOf() * vectorLength; + + // Allocate temporary buffers + var source = stackalloc byte[length + vectorLength]; + var span = new Span( + (void*)Interop.Align((long)source, length, vectorLength), + vectorLength); + + // Generated random numbers + for (int i = 0; i < vectorLength; ++i) + span[i] = rangeProvider.Next(); + + // Load aligned vector + return span.LoadAlignedVectorUnsafe(); + } +#endif + /// /// Constructs an RNG using the given provider instance. /// @@ -220,7 +290,7 @@ internal static void InitializeRNGKernel( { randomProvider[i] = default(TRandomProvider).CreateProvider(ref provider); } - + // Update provider state for future iterations sourceProviders[index] = provider; } diff --git a/Src/ILGPU.Algorithms/Random/XorShift128.cs b/Src/ILGPU.Algorithms/Random/XorShift128.cs index 71e1a7c03..b867b556c 100644 --- a/Src/ILGPU.Algorithms/Random/XorShift128.cs +++ b/Src/ILGPU.Algorithms/Random/XorShift128.cs @@ -113,7 +113,7 @@ public uint NextUInt() /// Generates a random ulong in [0..ulong.MaxValue]. /// /// A random ulong in [0..ulong.MaxValue]. - public ulong NextULong() => SeperateUInt(NextUInt()); + public ulong NextULong() => SeparateUInt(NextUInt()); /// public int Next() => ToInt(NextUInt()); diff --git a/Src/ILGPU.Algorithms/Random/XorShift32.cs b/Src/ILGPU.Algorithms/Random/XorShift32.cs index 72730de71..addb035aa 100644 --- a/Src/ILGPU.Algorithms/Random/XorShift32.cs +++ b/Src/ILGPU.Algorithms/Random/XorShift32.cs @@ -84,7 +84,7 @@ public uint NextUInt() /// Generates a random ulong in [0..ulong.MaxValue]. /// /// A random ulong in [0..ulong.MaxValue]. - public ulong NextULong() => SeperateUInt(NextUInt()); + public ulong NextULong() => SeparateUInt(NextUInt()); /// public int Next() => ToInt(NextUInt());