119 lines
2.4 KiB
C#
119 lines
2.4 KiB
C#
using System;
|
|
|
|
namespace MagmaEngine.Math;
|
|
|
|
/// <summary>
|
|
/// Implements a XorShift* PRNG, with 64 bits of internal state.
|
|
/// See http://en.wikipedia.org/wiki/Xorshift
|
|
/// </summary>
|
|
public struct SIntRandom
|
|
{
|
|
public SIntRandom(ulong seed)
|
|
{
|
|
if (seed == 0)
|
|
throw new InvalidOperationException("Seed needs to be bigger than zero.");
|
|
|
|
m_Seed = seed;
|
|
}
|
|
|
|
public ulong Next()
|
|
{
|
|
m_Seed ^= m_Seed >> 12;
|
|
m_Seed ^= m_Seed << 25;
|
|
m_Seed ^= m_Seed >> 27;
|
|
return m_Seed * 2685821657736338717UL; // multiplier taken from wikipedia article on XorShift PRNGs
|
|
}
|
|
|
|
public ulong Next(ulong upperLimit)
|
|
{
|
|
if (upperLimit == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return Next() % upperLimit;
|
|
}
|
|
|
|
public FixPoint16 NextFixPoint16()
|
|
{
|
|
return new() { m_Value = (int)(Next() & 0xffffUL) };
|
|
}
|
|
|
|
public int RandomizedRound(FixPoint16 value)
|
|
{
|
|
int ret = value.ToIntFloor();
|
|
if (NextFixPoint16() < FixPoint16.Fract(value))
|
|
ret++;
|
|
|
|
return ret;
|
|
}
|
|
|
|
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 override readonly string ToString()
|
|
{
|
|
return $"0x{m_Seed:X}";
|
|
}
|
|
|
|
public readonly ulong Seed => m_Seed;
|
|
|
|
private ulong m_Seed;
|
|
} |