Split xorshift128 to separate RNG

Blame ILCA for using RandomRangeInt to generate unsigned 32bit numbers :D
This commit is contained in:
Kurt
2022-01-10 21:07:27 -08:00
parent 1992f36c5b
commit 03cedd4d8b
2 changed files with 54 additions and 20 deletions

View File

@@ -0,0 +1,54 @@
using System.Runtime.CompilerServices;
namespace PKHeX.Core;
/// <summary>
/// Self-modifying RNG structure that implements xorshift.
/// </summary>
/// <remarks>https://en.wikipedia.org/wiki/Xorshift</remarks>
/// <seealso cref="Xoroshiro128Plus"/>
public ref struct XorShift128
{
private uint x, y, z, w;
public XorShift128(uint x, uint y, uint z, uint w)
{
this.x = x;
this.y = y;
this.z = z;
this.w = w;
}
public (uint x, uint y, uint z, uint w) GetState32() => (x, y, z, w);
public (ulong s0, ulong s1) GetState64() => (((ulong)y << 32) | x, ((ulong)w << 32) | z);
public string GetState128 => $"{w:X8}{z:X8}{y:X8}{x:X8}";
/// <summary>
/// Gets the next random <see cref="ulong"/>.
/// </summary>
public uint Next()
{
var t = x ^ (x << 11);
x = y;
y = z;
z = w;
return w = w ^ (w >> 19) ^ t ^ (t >> 8);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint NextUInt() => (uint)NextInt();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint NextUInt(uint max) => NextUInt() % max;
/// <summary>
/// Gets the next random <see cref="ulong"/>.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int NextInt(int start = int.MinValue, int end = int.MaxValue)
{
var next = Next();
var delta = unchecked((uint)(end - start));
return start + (int)(next % delta);
}
}

View File

@@ -76,25 +76,5 @@ public uint NextUInt(uint max)
var rnd = NextUInt();
return rnd - ((rnd / max) * max);
}
/// <summary>
/// Gets the next random <see cref="ulong"/>.
/// </summary>
public int NextInt(int start = int.MinValue, int end = int.MaxValue)
{
var _s0 = s0 & 0xFFFFFFFF;
var _s1 = s1 >> 32;
_s0 ^= (_s0 << 11) & 0xFFFFFFFF;
_s0 ^= (_s0 >> 8);
_s0 ^= (_s1 ^ (_s1 >> 19));
// Final calculations and store back to fields
s0 = ((s1 & 0xFFFFFFFF) << 32) | (s0 >> 32);
s1 = _s0 << 32 | (s1 >> 32);
var delta = unchecked(end - start);
return start + (int)(_s0 % (ulong)delta);
}
}
}