RandomExtensions
Provides random data generation.
using DotNext.Buffers;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
namespace DotNext
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public static class RandomExtensions
{
internal static readonly int BitwiseHashSalt = Random.get_Shared().Next();
private static void NextString(Random rng, Span<char> buffer, ReadOnlySpan<char> allowedChars)
{
ref char reference = ref MemoryMarshal.GetReference(allowedChars);
Span<char> span = buffer;
for (int i = 0; i < span.Length; i++) {
span[i] = Unsafe.Add(ref reference, rng.Next(0, allowedChars.Length));
}
}
[SkipLocalsInit]
private unsafe static void NextString(RandomNumberGenerator rng, Span<char> buffer, ReadOnlySpan<char> allowedChars)
{
int num = buffer.Length * 4;
MemoryRental<byte> memoryRental;
if ((uint)num > (uint)MemoryRental<byte>.StackallocThreshold)
memoryRental = new MemoryRental<byte>(num, true);
else {
int num2 = num;
memoryRental = new Span<byte>(stackalloc byte[(int)(uint)num2], num2);
}
MemoryRental<byte> memoryRental2 = memoryRental;
try {
rng.GetBytes(memoryRental2.Span);
num = 0;
ref char reference = ref MemoryMarshal.GetReference(allowedChars);
Span<char> span = buffer;
for (int num2 = 0; num2 < span.Length; num2++) {
ref char reference2 = ref span[num2];
uint num3 = (uint)BitConverter.ToInt32(memoryRental2.Span.Slice(num)) % (uint)allowedChars.Length;
reference2 = Unsafe.Add<char>(ref reference, (UIntPtr)num3);
num += 4;
}
} finally {
memoryRental2.Dispose();
}
}
[SkipLocalsInit]
private unsafe static string NextString<TGenerator>(TGenerator generator, IntPtr impl, ReadOnlySpan<char> allowedChars, int length) where TGenerator : class
{
if (length < 0)
throw new ArgumentOutOfRangeException("length");
if (length != 0 && !allowedChars.IsEmpty) {
MemoryRental<char> memoryRental = (length <= MemoryRental<char>.StackallocThreshold) ? ((MemoryRental<char>)new Span<char>((void*)stackalloc byte[(int)checked(unchecked((ulong)(uint)length) * 2)], length)) : new MemoryRental<char>(length, true);
MemoryRental<char> memoryRental2 = memoryRental;
try {
;
return new string(memoryRental2.Span);
} finally {
memoryRental2.Dispose();
}
}
return string.Empty;
}
public unsafe static string NextString(this Random random, [System.Runtime.CompilerServices.Nullable(0)] ReadOnlySpan<char> allowedChars, int length)
{
return NextString(random, (IntPtr)(void*), allowedChars, length);
}
public static string NextString(this Random random, string allowedChars, int length)
{
return random.NextString(allowedChars.AsSpan(), length);
}
public unsafe static string NextString(this RandomNumberGenerator random, [System.Runtime.CompilerServices.Nullable(0)] ReadOnlySpan<char> allowedChars, int length)
{
return NextString(random, (IntPtr)(void*), allowedChars, length);
}
public static string NextString(this RandomNumberGenerator random, string allowedChars, int length)
{
return random.NextString(allowedChars.AsSpan(), length);
}
public static bool NextBoolean(this Random random, double trueProbability = 0.5)
{
if (!trueProbability.IsBetween(0, 1, BoundType.Closed))
throw new ArgumentOutOfRangeException("trueProbability");
return random.NextDouble() >= 1 - trueProbability;
}
public static int Next(this RandomNumberGenerator random)
{
return random.Next<int>() & 2147483647;
}
public static bool NextBoolean(this RandomNumberGenerator random, double trueProbability = 0.5)
{
if (!trueProbability.IsBetween(0, 1, BoundType.Closed))
throw new ArgumentOutOfRangeException("trueProbability");
return random.NextDouble() >= 1 - trueProbability;
}
public static double NextDouble(this RandomNumberGenerator random)
{
return random.Next<ulong>().Normalize();
}
[System.Runtime.CompilerServices.NullableContext(0)]
[SkipLocalsInit]
public unsafe static T Next<[System.Runtime.CompilerServices.IsUnmanaged] T>([System.Runtime.CompilerServices.Nullable(1)] this Random random) where T : struct
{
Unsafe.SkipInit(out T value);
random.NextBytes(new Span<byte>((void*)(&value), sizeof(T)));
return value;
}
[System.Runtime.CompilerServices.NullableContext(0)]
[SkipLocalsInit]
public unsafe static T Next<[System.Runtime.CompilerServices.IsUnmanaged] T>([System.Runtime.CompilerServices.Nullable(1)] this RandomNumberGenerator random) where T : struct
{
Unsafe.SkipInit(out T value);
random.GetBytes(new Span<byte>((void*)(&value), sizeof(T)));
return value;
}
}
}