2021-01-17 08:30:51 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Numerics;
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
namespace LibHac.Tests;
|
|
|
|
|
|
|
|
|
|
public struct Random
|
2021-01-17 08:30:51 +01:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
private ulong _state1;
|
|
|
|
|
private ulong _state2;
|
|
|
|
|
|
|
|
|
|
public Random(ulong seed)
|
2021-01-17 08:30:51 +01:00
|
|
|
|
{
|
2022-12-10 19:12:43 +01:00
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
ulong x = seed;
|
|
|
|
|
ulong z = x + 0x9e3779b97f4a7c15;
|
|
|
|
|
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
|
|
|
|
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
|
|
|
|
x = z ^ (z >> 31);
|
|
|
|
|
z = (x += 0x9e3779b97f4a7c15);
|
|
|
|
|
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
|
|
|
|
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
|
|
|
|
_state1 = z ^ (z >> 31);
|
|
|
|
|
_state2 = x;
|
|
|
|
|
}
|
2021-11-14 20:08:57 +01:00
|
|
|
|
}
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
ulong Next()
|
|
|
|
|
{
|
|
|
|
|
ulong s0 = _state1;
|
|
|
|
|
ulong s1 = _state2;
|
2022-12-10 19:12:43 +01:00
|
|
|
|
ulong result = unchecked(BitOperations.RotateLeft(s0 + s1, 17) + s0);
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
s1 ^= s0;
|
|
|
|
|
_state1 = BitOperations.RotateLeft(s0, 49) ^ s1 ^ (s1 << 21);
|
|
|
|
|
_state2 = BitOperations.RotateLeft(s1, 28);
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
return result;
|
|
|
|
|
}
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
public int Next(int minValue, int maxValue)
|
|
|
|
|
{
|
|
|
|
|
if (minValue > maxValue)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException(nameof(minValue));
|
2021-01-17 08:30:51 +01:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-10 19:12:43 +01:00
|
|
|
|
unchecked
|
|
|
|
|
{
|
|
|
|
|
long range = (long)maxValue - minValue;
|
|
|
|
|
return (int)((uint)Next() * (1.0 / uint.MaxValue) * range) + minValue;
|
|
|
|
|
}
|
2021-11-14 20:08:57 +01:00
|
|
|
|
}
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
public void NextBytes(Span<byte> buffer)
|
|
|
|
|
{
|
|
|
|
|
Span<ulong> bufferUlong = MemoryMarshal.Cast<byte, ulong>(buffer);
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
for (int i = 0; i < bufferUlong.Length; i++)
|
2021-01-17 08:30:51 +01:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
bufferUlong[i] = Next();
|
|
|
|
|
}
|
2021-01-17 08:30:51 +01:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
for (int i = bufferUlong.Length * sizeof(ulong); i < buffer.Length; i++)
|
|
|
|
|
{
|
2022-12-10 19:12:43 +01:00
|
|
|
|
buffer[i] = unchecked((byte)Next());
|
2021-01-17 08:30:51 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-12 02:21:07 +01:00
|
|
|
|
}
|