Class MersenneTwister
A Mersenne Twister (MT19937) random number generator. Provides very high quality randomness with an enormous period, suitable for scientific simulations and tooling.
Implements
Inherited Members
Namespace: Scylla.Core.Util.Random
Assembly: ScyllaCore.dll
Syntax
[Serializable]
public sealed class MersenneTwister : IRandomSource
Remarks
Mersenne Twister MT19937 (Matsumoto and Nishimura, 1998) is a high-quality PRNG with:
- 624 x 32-bit internal state (~2.5 KB)
- Period of 2^19937 - 1 (a Mersenne prime)
- Excellent statistical quality and 623-dimensional equidistribution
- Wide industry adoption in scientific and simulation software
Best suited for:
- Scientific simulations and Monte Carlo methods
- Offline procedural generation tools
- Applications that require extremely long non-repeating sequences
Due to its large state size (~2.5 KB), MersenneTwister is implemented as a
class rather than a struct to avoid expensive copy-by-value semantics.
For real-time gameplay code where memory compactness matters, prefer
Xoshiro256StarStar or PCG32 instead.
State can be captured and restored with GetState() and SetState(MersenneTwisterState), enabling deterministic replay and save/load functionality.
Constructors
MersenneTwister(uint)
Creates a Mersenne Twister RNG with the specified 32-bit seed.
Declaration
public MersenneTwister(uint seed)
Parameters
| Type | Name | Description |
|---|---|---|
| uint | seed | The seed value used to initialize the internal state array via the standard MT19937 32-bit initialization recurrence. |
MersenneTwister(ulong)
Creates a Mersenne Twister RNG with the specified 64-bit seed.
Declaration
public MersenneTwister(ulong seed)
Parameters
| Type | Name | Description |
|---|---|---|
| ulong | seed | The seed value used to initialize the internal 624-word state array. The seed is expanded via SplitMix64 into four 32-bit values and fed into the array-initialization procedure for better state coverage than a plain 32-bit seed. |
Methods
FromSeed(int)
Creates a Mersenne Twister RNG from the specified 32-bit signed seed value.
Declaration
public static MersenneTwister FromSeed(int seed)
Parameters
| Type | Name | Description |
|---|---|---|
| int | seed | The seed value. It is reinterpreted as an unsigned 32-bit integer before being passed to the standard MT19937 initialization procedure. |
Returns
| Type | Description |
|---|---|
| MersenneTwister | A fully initialized MersenneTwister instance. |
FromSeed(long)
Creates a Mersenne Twister RNG from the specified 64-bit signed seed value.
Declaration
public static MersenneTwister FromSeed(long seed)
Parameters
| Type | Name | Description |
|---|---|---|
| long | seed | The seed value. It is reinterpreted as an unsigned 64-bit integer, then expanded via SplitMix64 to fill the full state array. |
Returns
| Type | Description |
|---|---|
| MersenneTwister | A fully initialized MersenneTwister instance. |
FromSeed(uint)
Creates a Mersenne Twister RNG from the specified 32-bit unsigned seed value.
Declaration
public static MersenneTwister FromSeed(uint seed)
Parameters
| Type | Name | Description |
|---|---|---|
| uint | seed | The seed value used to initialize the RNG state via the standard MT19937 32-bit initialization recurrence. |
Returns
| Type | Description |
|---|---|
| MersenneTwister | A fully initialized MersenneTwister instance. |
FromSeed(ulong)
Creates a Mersenne Twister RNG using the specified 64-bit unsigned seed value.
Declaration
public static MersenneTwister FromSeed(ulong seed)
Parameters
| Type | Name | Description |
|---|---|---|
| ulong | seed | The seed value used to initialize the RNG state. The seed is expanded through SplitMix64 to produce four 32-bit words which are then mixed into the full 624-element state via the array-initialization procedure. |
Returns
| Type | Description |
|---|---|
| MersenneTwister | A fully initialized MersenneTwister instance ready to generate values. |
FromString(string)
Creates a Mersenne Twister RNG from a stable hash of the given string. The string is hashed using FNV-1a to produce a reproducible 64-bit seed, making this useful for named procedural seeds (e.g., level names, world IDs).
Declaration
public static MersenneTwister FromString(string seed)
Parameters
| Type | Name | Description |
|---|---|---|
| string | seed | The string used to generate a stable, cross-platform seed hash. The same string always produces the same RNG sequence on any platform. |
Returns
| Type | Description |
|---|---|
| MersenneTwister | A fully initialized MersenneTwister instance. |
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown if |
GetState()
Retrieves the current internal state of the RNG for serialization or checkpointing.
Declaration
public MersenneTwisterState GetState()
Returns
| Type | Description |
|---|---|
| MersenneTwisterState | A MersenneTwisterState containing a deep copy of the 624-element state array and the current index. Restoring this snapshot via SetState(MersenneTwisterState) will reproduce the exact same sequence of values. |
Remarks
The returned state struct contains an independent copy of the internal array. Modifying the original RNG after calling GetState() does not affect the saved snapshot, and vice versa.
NextBytes(byte[], int, int)
Fills a specified portion of a byte array with random bytes generated by the Mersenne Twister algorithm.
Declaration
public void NextBytes(byte[] buffer, int offset = 0, int count = -1)
Parameters
| Type | Name | Description |
|---|---|---|
| byte[] | buffer | The byte array to populate. Must not be |
| int | offset | The zero-based index in |
| int | count | The number of bytes to write starting at |
Remarks
Each call to NextUInt32() produces 4 bytes. The bytes are written in little-endian order (least-significant byte first). Any unused bytes from the final 32-bit draw are discarded.
Exceptions
| Type | Condition |
|---|---|
| ArgumentNullException | Thrown when |
| ArgumentOutOfRangeException | Thrown when |
NextUInt32()
Returns an unsigned 32-bit random value using the Mersenne Twister algorithm.
Declaration
public uint NextUInt32()
Returns
| Type | Description |
|---|---|
| uint | A uniformly distributed unsigned 32-bit integer in the range
[ |
Remarks
When the internal index _mti reaches Scylla.Core.Util.Random.MersenneTwister.N (624), the generator
regenerates all 624 state words via the twist recurrence (see Scylla.Core.Util.Random.MersenneTwister.GenerateWords())
before returning a value. This regeneration step is the most expensive part of the
algorithm but amortizes to a low per-call cost over the full batch.
After retrieving a raw state word, four tempering transformations are applied
to improve the distribution of the output bits:
y ^= y >> 11,
y ^= (y << 7) & 0x9D2C5680,
y ^= (y << 15) & 0xEFC60000,
y ^= y >> 18.
These constants are defined as part of the MT19937 specification.
NextUInt64()
Returns an unsigned 64-bit random value by combining two consecutive 32-bit outputs.
Declaration
public ulong NextUInt64()
Returns
| Type | Description |
|---|---|
| ulong | A 64-bit unsigned integer assembled by placing the first NextUInt32() result in the high 32 bits and the second in the low 32 bits. Consumes two words from the internal state per call. |
Remarks
Because Mersenne Twister is natively a 32-bit generator, producing a 64-bit value requires two sequential calls to NextUInt32(). If only the upper or lower half of the 64-bit value is needed, prefer calling NextUInt32() directly to avoid wasting the second draw. For natively 64-bit generators see Xoshiro256StarStar or Xoroshiro128Plus.
SetState(MersenneTwisterState)
Restores the RNG to a previously saved state, enabling deterministic replay from a known checkpoint.
Declaration
public void SetState(MersenneTwisterState state)
Parameters
| Type | Name | Description |
|---|---|---|
| MersenneTwisterState | state | The state snapshot to restore. MT must be a non-null array with exactly 624 elements. MTI will be clamped to the range [0, 624] if it falls outside that range. |
Remarks
After a successful call, the generator will produce the same sequence it would
have produced after the original GetState() call. The state array
is copied into the internal buffer, so subsequent modifications to
state.MT do not affect this instance.
Exceptions
| Type | Condition |
|---|---|
| ArgumentException | Thrown when |