/// Simple deterministic RNG (xorshift32) with serializable state.
class DeterministicRandom {
  DeterministicRandom(int seed) : _state = seed & _mask;

  DeterministicRandom.clone(DeterministicRandom other)
    : _state = other._state & _mask;

  DeterministicRandom.fromState(int state) : _state = state & _mask;

  static const int _mask = 0xFFFFFFFF;

  int _state;

  int get state => _state;

  /// Returns next unsigned 32-bit value.
  int nextUint32() {
    var x = _state;
    x ^= (x << 13) & _mask;
    x ^= (x >> 17) & _mask;
    x ^= (x << 5) & _mask;
    _state = x & _mask;
    return _state;
  }

  int nextInt(int maxExclusive) {
    if (maxExclusive <= 0) {
      throw ArgumentError.value(maxExclusive, 'maxExclusive', 'must be > 0');
    }
    return nextUint32() % maxExclusive;
  }

  double nextDouble() {
    // 2^32 as double.
    const double denom = 4294967296.0;
    return nextUint32() / denom;
  }
}
