diff --git a/.gitignore b/.gitignore
index 8967e0621..c5680028b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -291,6 +291,7 @@ Src/ILGPU.Algorithms/IL/ILContext.Generated.cs
Src/ILGPU.Algorithms/PTX/PTXContext.Generated.cs
Src/ILGPU.Algorithms/RadixSortOperations.cs
Src/ILGPU.Algorithms/Vectors/VectorTypes.cs
+Src/ILGPU.Algorithms/Random/RandomRanges.cs
Src/ILGPU.Algorithms/Runtime/Cuda/API/CuBlasNativeMethods.cs
Src/ILGPU.Algorithms/Runtime/Cuda/API/CuFFTAPI.Generated.cs
Src/ILGPU.Algorithms/Runtime/Cuda/API/CuFFTNativeMethods.cs
diff --git a/Src/ILGPU.Algorithms/ILGPU.Algorithms.csproj b/Src/ILGPU.Algorithms/ILGPU.Algorithms.csproj
index 8fece5da9..b89300f85 100644
--- a/Src/ILGPU.Algorithms/ILGPU.Algorithms.csproj
+++ b/Src/ILGPU.Algorithms/ILGPU.Algorithms.csproj
@@ -114,6 +114,10 @@
TextTemplatingFileGenerator
RadixSortOperations.cs
+
+ TextTemplatingFileGenerator
+ RandomRanges.cs
+
TextTemplatingFileGenerator
CuFFTAPI.Generated.cs
@@ -252,6 +256,11 @@
True
RadixSortOperations.tt
+
+ True
+ True
+ RandomRanges.tt
+
True
True
diff --git a/Src/ILGPU.Algorithms/Random/RandomExtensions.cs b/Src/ILGPU.Algorithms/Random/RandomExtensions.cs
index 282f73647..9c60c05f4 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,72 @@ 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.
+ [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.
+ [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.
///
diff --git a/Src/ILGPU.Algorithms/Random/RandomRanges.tt b/Src/ILGPU.Algorithms/Random/RandomRanges.tt
new file mode 100644
index 000000000..1282190e4
--- /dev/null
+++ b/Src/ILGPU.Algorithms/Random/RandomRanges.tt
@@ -0,0 +1,393 @@
+// ---------------------------------------------------------------------------------------
+// ILGPU Algorithms
+// Copyright (c) 2023 ILGPU Project
+// www.ilgpu.net
+//
+// File: RandomRanges.tt/RandomRanges.cs
+//
+// This file is part of ILGPU and is distributed under the University of Illinois Open
+// Source License. See LICENSE.txt for details.
+// ---------------------------------------------------------------------------------------
+
+<#@ template debug="false" hostspecific="false" language="C#" #>
+<#@ include file="../TypeInformation.ttinclude"#>
+<#@ assembly name="System.Core" #>
+<#@ import namespace="System.Text" #>
+<#@ import namespace="System.Collections.Generic" #>
+<#@ output extension=".cs" #>
+<#
+var rngTypes = SignedIntTypes.Concat(FloatTypes);
+var functionMapping = new Dictionary()
+ {
+ { "Int8", "(byte)randomProvider.Next(0, byte.MaxValue)" },
+ { "Int16", "(short)randomProvider.Next(0, short.MaxValue)" },
+ { "Int32", "randomProvider.Next()" },
+ { "Int64", "randomProvider.NextLong()" },
+
+ { "Half", "(Half)randomProvider.NextFloat()" },
+ { "Float", "randomProvider.NextFloat()" },
+ { "Double", "randomProvider.NextDouble()" },
+ };
+#>
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+#pragma warning disable CA1000 // No static members on generic types
+#pragma warning disable IDE0004 // Cast is redundant
+
+#if NET7_0_OR_GREATER
+
+namespace ILGPU.Algorithms.Random
+{
+ ///
+ /// A generic random number range operating on a generic type
+ /// .
+ ///
+ /// The element type to operate on.
+ public interface IBasicRandomRange
+ where T : struct
+ {
+ ///
+ /// Returns the min value of this range (inclusive).
+ ///
+ T MinValue { get; }
+
+ ///
+ /// Returns the max value of this range (exclusive).
+ ///
+ T MaxValue { get; }
+ }
+
+ ///
+ /// A generic random number range operating on a generic type
+ /// .
+ ///
+ /// The element type to operate on.
+ public interface IRandomRange : IBasicRandomRange
+ where T : struct
+ {
+ ///
+ /// Generates a new random value by taking min and max value ranges into account.
+ ///
+ /// The random provider type.
+ /// The random provider instance.
+ /// The retrieved random value.
+ ///
+ /// CAUTION: This function implementation is meant to be thread safe in general to
+ /// support massively parallel evaluations on CPU and GPU.
+ ///
+ [SuppressMessage(
+ "Naming",
+ "CA1716:Identifiers should not match keywords",
+ Justification = "Like the method System.Random.Next()")]
+ T Next(ref TRandomProvider randomProvider)
+ where TRandomProvider : struct, IRandomProvider;
+ }
+
+ ///
+ /// A generic random number range provider operating on a generic type
+ /// .
+ ///
+ /// The element type to operate on.
+ ///
+ /// CAUTION: A type implementing this interface is meant to be thread safe in general
+ /// to support massively parallel evaluations on CPU and GPU.
+ ///
+ public interface IRandomRangeProvider
+ where T : struct
+ {
+ ///
+ /// Generates a new random value by taking min and max value ranges into account.
+ ///
+ /// The retrieved random value.
+ [SuppressMessage(
+ "Naming",
+ "CA1716:Identifiers should not match keywords",
+ Justification = "Like the method System.Random.Next()")]
+ T Next();
+ }
+
+ ///
+ /// A generic random number range provider operating on a generic type
+ /// .
+ ///
+ /// The type implementing this interface.
+ /// The element type to operate on.
+ ///
+ /// CAUTION: A type implementing this interface is meant to be thread safe in general
+ /// to support massively parallel evaluations on CPU and GPU.
+ ///
+ public interface IRandomRangeProvider :
+ IRandomRangeProvider, IBasicRandomRange
+ where TSelf : struct, IRandomRangeProvider
+ where T : unmanaged
+ {
+ ///
+ /// Instantiates a new random range using the given random provider.
+ ///
+ /// The parent RNG instance.
+ /// The minimum value (inclusive).
+ /// The maximum value (exclusive).
+ static abstract TSelf Create(System.Random random, T minValue, T maxValue);
+
+ ///
+ /// Instantiates a new random range using the given random provider.
+ ///
+ /// The parent RNG instance.
+ /// The minimum value (inclusive).
+ /// The maximum value (exclusive).
+ static abstract TSelf Create(
+ ref TOtherProvider random,
+ T minValue,
+ T maxValue)
+ where TOtherProvider : struct, IRandomProvider;
+
+ ///
+ /// Creates a new random range vector provider compatible with this provider.
+ ///
+ RandomRangeVectorProvider CreateVectorProvider();
+ }
+
+ ///
+ /// Represents a default RNG range for vectors types returning specified value
+ /// intervals for type Vector.
+ ///
+ /// The vector element type.
+ /// The underlying range provider.
+ public struct RandomRangeVectorProvider :
+ IRandomRangeProvider>,
+ IRandomRangeProvider,
+ IBasicRandomRange
+ where T : unmanaged
+ where TRangeProvider : struct, IRandomRangeProvider
+ {
+ private TRangeProvider rangeProvider;
+
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The RNG provider to use.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public RandomRangeVectorProvider(TRangeProvider provider)
+ {
+ rangeProvider = provider;
+ }
+
+ ///
+ /// Returns the min value of this range (inclusive).
+ ///
+ public readonly T MinValue => rangeProvider.MinValue;
+
+ ///
+ /// Returns the max value of this range (exclusive).
+ ///
+ public readonly T MaxValue => rangeProvider.MaxValue;
+
+ ///
+ /// Generates a new random value using the given min and max values.
+ ///
+ [SuppressMessage(
+ "Naming",
+ "CA1716:Identifiers should not match keywords",
+ Justification = "Like the method System.Random.Next()")]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public Vector Next() =>
+ RandomExtensions.NextVector(ref rangeProvider);
+
+ ///
+ /// Generates a new random value using the given min and max values.
+ ///
+ [SuppressMessage(
+ "Naming",
+ "CA1716:Identifiers should not match keywords",
+ Justification = "Like the method System.Random.Next()")]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ T IRandomRangeProvider.Next() => rangeProvider.Next();
+ }
+
+ ///
+ /// A container class holding specialized random range instances while providing
+ /// specialized extension methods for different RNG providers.
+ ///
+ public static class RandomRanges
+ {
+<# foreach (var type in rngTypes) { #>
+<# var providerName = $"RandomRange{type.Name}Provider"; #>
+ ///
+ /// Represents a default RNG range for type <#= type.Name #> returning
+ /// specified value intervals for type <#= type.Name #> (in analogy to calling
+ /// the appropriate NextXYZ method on the random provider given using min and
+ /// max values).
+ ///
+ /// The minimum value (inclusive).
+ /// The maximum values (exclusive).
+ public readonly record struct RandomRange<#= type.Name #>(
+ <#= type.Type #> MinValue,
+ <#= type.Type #> MaxValue) :
+ IRandomRange<<#= type.Type #>>
+ {
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The parent RNG instance.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public <#= providerName #>
+ CreateProvider(System.Random random)
+ where TRandomProvider : struct, IRandomProvider =>
+ <#= providerName #>.Create(
+ random,
+ MinValue,
+ MaxValue);
+
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The parent RNG instance.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public <#= providerName #>
+ CreateProvider(ref TRandomProvider random)
+ where TRandomProvider : struct, IRandomProvider =>
+ <#= providerName #>.Create(
+ ref random,
+ MinValue,
+ MaxValue);
+
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The parent RNG instance.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public <#= providerName #>
+ CreateProvider(
+ ref TOtherRandomProvider random)
+ where TRandomProvider : struct, IRandomProvider
+ where TOtherRandomProvider :
+ struct, IRandomProvider =>
+ <#= providerName #>.Create(
+ ref random,
+ MinValue,
+ MaxValue);
+
+ ///
+ /// Generates a new random value using the given min and max values.
+ ///
+ [SuppressMessage(
+ "Naming",
+ "CA1716:Identifiers should not match keywords",
+ Justification = "Like the method System.Random.Next()")]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public <#= type.Type #> Next(
+ ref TRandomProvider randomProvider)
+ where TRandomProvider : struct, IRandomProvider =>
+ (<#= type.Type #>)RandomExtensions.Next(
+ ref randomProvider,
+ MinValue,
+ MaxValue);
+ }
+
+ ///
+ /// Represents a default RNG range for type <#= type.Name #> returning
+ /// specified value intervals for type <#= type.Name #> (in analogy to calling
+ /// the appropriate NextXYZ method on the random provider given using min and
+ /// max values).
+ ///
+ /// The underlying random provider.
+ public struct <#= providerName #> :
+ IRandomRangeProvider<
+ <#= providerName #>,
+ <#= type.Type #>>
+ where TRandomProvider : struct, IRandomProvider
+ {
+ private TRandomProvider randomProvider;
+
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The RNG instance to use.
+ /// The minimum value (inclusive).
+ /// The maximum value (exclusive).
+ public <#= providerName #>(
+ TRandomProvider random,
+ <#= type.Type #> minValue,
+ <#= type.Type #> maxValue)
+ {
+ randomProvider = random;
+ MinValue = minValue;
+ MaxValue = maxValue;
+ }
+
+ ///
+ /// Returns the min value of this range (inclusive).
+ ///
+ public <#= type.Type #> MinValue { get; }
+
+ ///
+ /// Returns the max value of this range (exclusive).
+ ///
+ public <#= type.Type #> MaxValue { get; }
+
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The parent RNG instance.
+ /// The minimum value (inclusive).
+ /// The maximum value (exclusive).
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static <#= providerName #>
+ Create(
+ System.Random random,
+ <#= type.Type #> minValue,
+ <#= type.Type #> maxValue) =>
+ new(default(TRandomProvider).CreateProvider(random), minValue, maxValue);
+
+ ///
+ /// Instantiates a new random range provider using the given random provider.
+ ///
+ /// The parent RNG instance.
+ /// The minimum value (inclusive).
+ /// The maximum value (exclusive).
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static <#= providerName #>
+ Create(
+ ref TOtherProvider random,
+ <#= type.Type #> minValue,
+ <#= type.Type #> maxValue)
+ where TOtherProvider : struct, IRandomProvider =>
+ new(
+ default(TRandomProvider).CreateProvider(ref random),
+ minValue,
+ maxValue);
+
+ ///
+ /// Creates a new random range vector provider compatible with this provider.
+ ///
+ public readonly RandomRangeVectorProvider<
+ <#= type.Type #>,
+ <#= providerName #>> CreateVectorProvider() =>
+ new(this);
+
+ ///
+ /// Generates a new random value using the given min and max values.
+ ///
+ [SuppressMessage(
+ "Naming",
+ "CA1716:Identifiers should not match keywords",
+ Justification = "Like the method System.Random.Next()")]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public <#= type.Type #> Next() =>
+ (<#= type.Type #>)RandomExtensions.Next(
+ ref randomProvider,
+ MinValue,
+ MaxValue);
+ }
+
+<# } #>
+ }
+}
+
+#endif
+
+#pragma warning restore IDE0004
+#pragma warning restore CA1000
\ No newline at end of file
diff --git a/Src/ILGPU.Algorithms/Random/XorShift128.cs b/Src/ILGPU.Algorithms/Random/XorShift128.cs
index b942f603d..ccde7beb3 100644
--- a/Src/ILGPU.Algorithms/Random/XorShift128.cs
+++ b/Src/ILGPU.Algorithms/Random/XorShift128.cs
@@ -112,7 +112,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 adce2c54c..725ea5dd6 100644
--- a/Src/ILGPU.Algorithms/Random/XorShift32.cs
+++ b/Src/ILGPU.Algorithms/Random/XorShift32.cs
@@ -83,7 +83,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());