ported from perforce
This commit is contained in:
100
RobotAndDonkey.Game/Utils/SRandom.cs
Normal file
100
RobotAndDonkey.Game/Utils/SRandom.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
|
||||
namespace RobotAndDonkey.Game.Utils;
|
||||
|
||||
/// <summary>
|
||||
/// Implements a XorShift* PRNG, with 64 bits of internal state.
|
||||
/// See http://en.wikipedia.org/wiki/Xorshift
|
||||
/// </summary>
|
||||
public struct SRandom
|
||||
{
|
||||
public SRandom(ulong seed)
|
||||
{
|
||||
if (seed == 0)
|
||||
throw new InvalidOperationException("Seed needs to be bigger than zero.");
|
||||
|
||||
Seed = seed;
|
||||
}
|
||||
|
||||
public void Shuffle<T>(Span<T> span)
|
||||
{
|
||||
var n = span.Length;
|
||||
|
||||
for (var i = 0; i < n; i++)
|
||||
{
|
||||
var r = i + Next(n - i);
|
||||
(span[r], span[i]) = (span[i], span[r]);
|
||||
}
|
||||
}
|
||||
|
||||
public ulong Next()
|
||||
{
|
||||
Seed ^= Seed >> 12;
|
||||
Seed ^= Seed << 25;
|
||||
Seed ^= Seed >> 27;
|
||||
return Seed * 2685821657736338717UL; // multiplier taken from wikipedia article on XorShift PRNGs
|
||||
}
|
||||
|
||||
public ulong Next(ulong upperLimit)
|
||||
{
|
||||
if (upperLimit == 0)
|
||||
return 0;
|
||||
|
||||
return Next() % upperLimit;
|
||||
}
|
||||
|
||||
public uint Next(uint upperLimit)
|
||||
{
|
||||
if (upperLimit == 0)
|
||||
return 0;
|
||||
|
||||
return (uint)(Next() % upperLimit);
|
||||
}
|
||||
|
||||
public uint Next(uint lowerLimit, uint upperLimit)
|
||||
{
|
||||
if (upperLimit == 0)
|
||||
return 0;
|
||||
|
||||
if (lowerLimit == upperLimit)
|
||||
return lowerLimit;
|
||||
|
||||
return lowerLimit + (uint)(Next() % (upperLimit - lowerLimit));
|
||||
}
|
||||
|
||||
public int Next(int upperLimit)
|
||||
{
|
||||
if (upperLimit == 0)
|
||||
return 0;
|
||||
|
||||
return (int)(Next() % (uint)(upperLimit & 0x7fffffff));
|
||||
}
|
||||
|
||||
public int Next(int lowerLimit, int upperLimit)
|
||||
{
|
||||
if (upperLimit == 0)
|
||||
return 0;
|
||||
|
||||
if (lowerLimit == upperLimit)
|
||||
return lowerLimit;
|
||||
|
||||
return lowerLimit + (int)(Next() % (uint)((upperLimit - lowerLimit) & 0x7fffffff));
|
||||
}
|
||||
|
||||
public double NextDouble()
|
||||
{
|
||||
return Next(int.MaxValue) * (1.0 / int.MaxValue);
|
||||
}
|
||||
|
||||
public float NextSingle()
|
||||
{
|
||||
return (float)NextDouble();
|
||||
}
|
||||
|
||||
public readonly override string ToString()
|
||||
{
|
||||
return $"0x{Seed:X}";
|
||||
}
|
||||
|
||||
public ulong Seed { get; internal set; }
|
||||
}
|
||||
Reference in New Issue
Block a user