// MIT License - Copyright (c) 2025 wallstop
// Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE
namespace WallstopStudios.UnityHelpers.Core.Random
{
using System;
using System.Runtime.Serialization;
using System.Text.Json.Serialization;
using ProtoBuf;
///
/// A simple Linear Congruential Generator (LCG): extremely fast with low-quality randomness.
///
///
///
/// LCGs are among the oldest PRNGs. This configuration is fast and compact but exhibits correlations and
/// shorter periods compared to modern generators. Best suited for cosmetic randomness where quality is not
/// critical.
///
/// Pros:
///
/// - Blazing fast; trivial implementation.
/// - Tiny state and deterministic behavior.
///
/// Cons:
///
/// - Poor statistical quality vs. PCG/Xoroshiro; noticeable patterns in some uses.
/// - Not cryptographically secure.
///
/// When to use:
///
/// - Cheap visual effects, quick throwaway randomness, prototyping.
///
/// When not to use:
///
/// - Gameplay-critical logic, simulations, or fairness-sensitive systems.
///
///
///
///
/// var rng = new LinearCongruentialGenerator(seed: 12345);
/// int i = rng.Next(0, 100);
/// // Prefer PCG or IllusionFlow for production gameplay.
///
///
[RandomGeneratorMetadata(
RandomQuality.Poor,
"Minimal standard LCG; fails spectral tests and exhibits lattice artifacts beyond small dimensions.",
"Park & Miller 1988",
"" // Communications of the ACM 31(10):1192-1201
)]
[Serializable]
[DataContract]
[ProtoContract]
public sealed class LinearCongruentialGenerator : AbstractRandom
{
public static LinearCongruentialGenerator Instance =>
ThreadLocalRandom.Instance;
public override RandomState InternalState => BuildState(_state);
[ProtoMember(6)]
private uint _state;
public LinearCongruentialGenerator()
: this(Guid.NewGuid()) { }
public LinearCongruentialGenerator(int seed)
{
_state = unchecked((uint)seed);
}
public LinearCongruentialGenerator(Guid seed)
{
_state = unchecked((uint)RandomUtilities.GuidToInt32(seed));
}
[JsonConstructor]
public LinearCongruentialGenerator(RandomState internalState)
{
_state = unchecked((uint)internalState.State1);
RestoreCommonState(internalState);
}
public override uint NextUint()
{
unchecked
{
_state = _state * 1664525U + 1013904223U;
}
return _state;
}
public override IRandom Copy()
{
return new LinearCongruentialGenerator(InternalState);
}
}
}