Skip to content

Commit

Permalink
Added vector-specific random extensions.
Browse files Browse the repository at this point in the history
  • Loading branch information
m4rs-mt committed Aug 9, 2023
1 parent a91587b commit 0e9206b
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 12 deletions.
90 changes: 80 additions & 10 deletions Src/ILGPU.Algorithms/Random/RandomExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -49,7 +51,7 @@ internal static uint MergeULong(ulong nextULong) =>
/// <summary>
/// Separates the given unsigned int into an unsigned long.
/// </summary>
internal static ulong SeperateUInt(uint nextUInt) =>
internal static ulong SeparateUInt(uint nextUInt) =>
((ulong)nextUInt << 32) | nextUInt;

/// <summary>
Expand Down Expand Up @@ -91,8 +93,8 @@ internal static ulong ShiftState(ulong state, int laneShift)
/// Generates a random int in [minValue..maxValue).
/// </summary>
/// <param name="randomProvider">The random provider.</param>
/// <param name="minValue">The minimum value (inclusive)</param>
/// <param name="maxValue">The maximum values (exclusive)</param>
/// <param name="minValue">The minimum value (inclusive).</param>
/// <param name="maxValue">The maximum values (exclusive).</param>
/// <returns>A random int in [minValue..maxValue).</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Next<TRandomProvider>(
Expand All @@ -112,8 +114,8 @@ public static float Next<TRandomProvider>(
/// Generates a random int in [minValue..maxValue).
/// </summary>
/// <param name="randomProvider">The random provider.</param>
/// <param name="minValue">The minimum value (inclusive)</param>
/// <param name="maxValue">The maximum values (exclusive)</param>
/// <param name="minValue">The minimum value (inclusive).</param>
/// <param name="maxValue">The maximum values (exclusive).</param>
/// <returns>A random int in [minValue..maxValue).</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double Next<TRandomProvider>(
Expand All @@ -133,8 +135,8 @@ public static double Next<TRandomProvider>(
/// Generates a random int in [minValue..maxValue).
/// </summary>
/// <param name="randomProvider">The random provider.</param>
/// <param name="minValue">The minimum value (inclusive)</param>
/// <param name="maxValue">The maximum values (exclusive)</param>
/// <param name="minValue">The minimum value (inclusive).</param>
/// <param name="maxValue">The maximum values (exclusive).</param>
/// <returns>A random int in [minValue..maxValue).</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Next<TRandomProvider>(
Expand All @@ -154,8 +156,8 @@ public static int Next<TRandomProvider>(
/// Generates a random long in [minValue..maxValue).
/// </summary>
/// <param name="randomProvider">The random provider.</param>
/// <param name="minValue">The minimum value (inclusive)</param>
/// <param name="maxValue">The maximum values (exclusive)</param>
/// <param name="minValue">The minimum value (inclusive).</param>
/// <param name="maxValue">The maximum values (exclusive).</param>
/// <returns>A random long in [minValue..maxValue).</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long Next<TRandomProvider>(
Expand All @@ -174,6 +176,74 @@ public static long Next<TRandomProvider>(
return Math.Min(intermediate + minValue, maxValue - 1);
}

#if NET7_0_OR_GREATER
/// <summary>
/// Generates a new random vector containing provided RNG-based values.
/// </summary>
/// <typeparam name="T">The vector element type.</typeparam>
/// <typeparam name="TRandomProvider">The RNG provider type.</typeparam>
/// <typeparam name="TRange">The generic RNG value range.</typeparam>
/// <param name="randomProvider">The random provider instance to use.</param>
/// <param name="range">The generic range instance to use.</param>
/// <returns>The created random vector.</returns>
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Vector<T> NextVector<T, TRandomProvider, TRange>(
ref TRandomProvider randomProvider,
TRange range)
where T : unmanaged
where TRandomProvider : struct, IRandomProvider
where TRange : struct, IRandomRange<T>
{
int vectorLength = Vector<T>.Count;
int length = Interop.SizeOf<T>() * vectorLength;

// Allocate temporary buffers
var source = stackalloc byte[length + vectorLength];
var span = new Span<T>(
(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();
}

/// <summary>
/// Generates a new random vector containing provided RNG-based values.
/// </summary>
/// <typeparam name="T">The vector element type.</typeparam>
/// <typeparam name="TRangeProvider">The RNG range provider.</typeparam>
/// <param name="rangeProvider">The range provider instance to use.</param>
/// <returns>The created random vector.</returns>
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Vector<T> NextVector<T, TRangeProvider>(
ref TRangeProvider rangeProvider)
where T : unmanaged
where TRangeProvider : struct, IRandomRangeProvider<TRangeProvider, T>
{
int vectorLength = Vector<T>.Count;
int length = Interop.SizeOf<T>() * vectorLength;

// Allocate temporary buffers
var source = stackalloc byte[length + vectorLength];
var span = new Span<T>(
(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

/// <summary>
/// Constructs an RNG using the given provider instance.
/// </summary>
Expand Down Expand Up @@ -220,7 +290,7 @@ internal static void InitializeRNGKernel<TRandomProvider>(
{
randomProvider[i] = default(TRandomProvider).CreateProvider(ref provider);
}

// Update provider state for future iterations
sourceProviders[index] = provider;
}
Expand Down
2 changes: 1 addition & 1 deletion Src/ILGPU.Algorithms/Random/XorShift128.cs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public uint NextUInt()
/// Generates a random ulong in [0..ulong.MaxValue].
/// </summary>
/// <returns>A random ulong in [0..ulong.MaxValue].</returns>
public ulong NextULong() => SeperateUInt(NextUInt());
public ulong NextULong() => SeparateUInt(NextUInt());

/// <inheritdoc cref="IRandomProvider.Next"/>
public int Next() => ToInt(NextUInt());
Expand Down
2 changes: 1 addition & 1 deletion Src/ILGPU.Algorithms/Random/XorShift32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public uint NextUInt()
/// Generates a random ulong in [0..ulong.MaxValue].
/// </summary>
/// <returns>A random ulong in [0..ulong.MaxValue].</returns>
public ulong NextULong() => SeperateUInt(NextUInt());
public ulong NextULong() => SeparateUInt(NextUInt());

/// <inheritdoc cref="IRandomProvider.Next"/>
public int Next() => ToInt(NextUInt());
Expand Down

0 comments on commit 0e9206b

Please sign in to comment.