100 lines
2.1 KiB
C#
100 lines
2.1 KiB
C#
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; }
|
|
} |