2020-07-19 04:39:20 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Numerics;
|
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
namespace LibHac.Tests;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Simple, full-cycle PRNG for use in tests.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class FullCycleRandom
|
2020-07-19 04:39:20 +02:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
private int _state;
|
|
|
|
|
private int _mult;
|
|
|
|
|
private int _inc;
|
|
|
|
|
private int _and;
|
|
|
|
|
private int _max;
|
|
|
|
|
|
|
|
|
|
public FullCycleRandom(int period, int seed)
|
2020-07-19 04:39:20 +02:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
// Avoid exponential growth pattern when initializing with a 0 seed
|
|
|
|
|
seed ^= 0x55555555;
|
|
|
|
|
_max = period - 1;
|
|
|
|
|
int order = BitOperations.Log2((uint)period - 1) + 1;
|
|
|
|
|
|
|
|
|
|
// There isn't any deep reasoning behind the choice of the number of bits
|
|
|
|
|
// in the seed used for initializing each parameter
|
|
|
|
|
int multSeedBits = Math.Max(order >> 1, 2);
|
|
|
|
|
int multSeedMask = (1 << multSeedBits) - 1;
|
|
|
|
|
int multSeed = seed & multSeedMask;
|
|
|
|
|
_mult = (multSeed << 2) | 5;
|
|
|
|
|
|
|
|
|
|
int incSeedBits = Math.Max(order >> 2, 2);
|
|
|
|
|
int incSeedMask = (1 << incSeedBits) - 1;
|
|
|
|
|
int incSeed = (seed >> multSeedBits) & incSeedMask;
|
|
|
|
|
_inc = incSeed | 1;
|
|
|
|
|
|
|
|
|
|
int stateSeedBits = order;
|
|
|
|
|
int stateSeedMask = (1 << stateSeedBits) - 1;
|
|
|
|
|
int stateSeed = (seed >> multSeedBits + incSeedBits) & stateSeedMask;
|
|
|
|
|
_state = stateSeed;
|
|
|
|
|
|
|
|
|
|
_and = (1 << order) - 1;
|
|
|
|
|
}
|
2020-07-19 04:39:20 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
public int Next()
|
|
|
|
|
{
|
|
|
|
|
do
|
2020-07-19 04:39:20 +02:00
|
|
|
|
{
|
2021-11-14 20:08:57 +01:00
|
|
|
|
_state = (_state * _mult + _inc) & _and;
|
|
|
|
|
} while (_state > _max);
|
2020-07-19 04:39:20 +02:00
|
|
|
|
|
2021-11-14 20:08:57 +01:00
|
|
|
|
return _state;
|
2020-07-19 04:39:20 +02:00
|
|
|
|
}
|
|
|
|
|
}
|