mirror of
https://github.com/kwsch/PKHeX.git
synced 2026-10-02 15:36:51 -05:00
Split xorshift128 to separate RNG
Blame ILCA for using RandomRangeInt to generate unsigned 32bit numbers :D
This commit is contained in:
54
PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs
Normal file
54
PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user