// 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); } } }