diff --git a/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs b/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs new file mode 100644 index 000000000..f99828215 --- /dev/null +++ b/PKHeX.Core/Legality/RNG/Algorithms/XorShift128.cs @@ -0,0 +1,54 @@ +using System.Runtime.CompilerServices; + +namespace PKHeX.Core; + +/// +/// Self-modifying RNG structure that implements xorshift. +/// +/// https://en.wikipedia.org/wiki/Xorshift +/// +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}"; + + /// + /// Gets the next random . + /// + 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; + + /// + /// Gets the next random . + /// + [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); + } +} diff --git a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs index edb48d901..211ffbbff 100644 --- a/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs +++ b/PKHeX.Core/Legality/RNG/Algorithms/Xoroshiro128Plus8b.cs @@ -76,25 +76,5 @@ public uint NextUInt(uint max) var rnd = NextUInt(); return rnd - ((rnd / max) * max); } - - /// - /// Gets the next random . - /// - 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); - } } }