Table of Contents

Class RandomStream

Namespace
Mrg32k3a.NET
Assembly
Mrg32k3a.NET.dll

One stream of the MRG32k3a generator: a virtual random number generator occupying its own block of 2^127 values, itself divided into 2^51 substreams of 2^76 values.

public sealed class RandomStream
Inheritance
RandomStream
Inherited Members

Remarks

Streams are handed out by a RandomStreamFactory, or rebuilt from a snapshot with FromState(RandomStreamState, string?). Each new stream starts 2^127 values beyond the previous one, so streams taken from the same factory never overlap in any practical run.

A stream is not thread safe. The intended pattern is one stream per worker.

Internally the recurrence runs on 64 bit integers with no conditional branches, rather than on the exact double-precision arithmetic of L'Ecuyer (1999), Figure 1. The observable sequence is identical and does not depend on the floating point behaviour of the host, so results match across x64 and ARM64 and across every target framework of this library.

Properties

Antithetic

Gets or sets whether this stream returns antithetic variates, that is one minus the value it would otherwise return.

public bool Antithetic { get; set; }

Property Value

bool

Remarks

The flag does not change how far a draw advances the state, so a stream and its antithetic twin stay synchronised. Turning the flag off restores the plain sequence.

In high-precision mode the reflection is applied to each of the two underlying draws rather than to the value they combine into. The two differ in the last bits.

CurrentState

Gets the current state of this stream.

public Mrg32k3aState CurrentState { get; }

Property Value

Mrg32k3aState

HighPrecision

Gets or sets whether NextDouble() returns roughly 53 bits of precision instead of 32, at the cost of advancing the state by two steps instead of one.

public bool HighPrecision { get; set; }

Property Value

bool

Remarks

The high-precision value is the first draw plus the second draw weighted by 2^-24, reduced modulo one. When Antithetic is also set, both draws are reflected first and the weighted term carries an offset of minus one. Switching the flag changes how fast a stream is consumed, so it should be set before a stream is used rather than part way through.

Name

Gets or sets the label carried by this stream.

[AllowNull]
public string Name { get; set; }

Property Value

string

Remarks

Setting null stores an empty label, as everywhere else a name is accepted.

StreamStartState

Gets the initial state of this stream.

public Mrg32k3aState StreamStartState { get; }

Property Value

Mrg32k3aState

SubstreamIndex

Gets the zero-based index of the substream this stream is currently inside.

public long SubstreamIndex { get; }

Property Value

long

Remarks

A stream holds 2^51 substreams, so the index runs from zero to 2^51 - 1. It is part of the stream's state: it is carried by Clone() and by SaveState(), and it is what lets SkipSubstreams(long) tell whether a move would leave this stream's block. Only the substream operations change it; drawing values and Advance(long) do not.

SubstreamStartState

Gets the state at the start of the substream this stream is currently inside.

public Mrg32k3aState SubstreamStartState { get; }

Property Value

Mrg32k3aState

Methods

Advance(long)

Moves the current position of this stream by an arbitrary signed number of steps, leaving its initial state and its substream start untouched.

public void Advance(long steps)

Parameters

steps long

Steps to move; negative values move backwards.

Remarks

To move 2^e + c steps, call AdvanceByPowerOfTwo(int) (or RetreatByPowerOfTwo(int)) with exponent e and then Advance(long) with c. Both are escape hatches. Ordinary use is served by the reset methods and by taking more streams from the factory.

Unlike the substream operations, this one does not refuse to leave the stream's own block. A position inside a substream can be 2^76 steps from its start, which no long can express, so there is no offset to check a move against. Enough steps here will walk into a neighbouring stream, which is the price of the escape hatch.

AdvanceByPowerOfTwo(int)

Moves the current position of this stream forwards by 2^exponent steps, leaving its initial state and its substream start untouched.

public void AdvanceByPowerOfTwo(int exponent)

Parameters

exponent int

A base-two exponent between 0 and 255 inclusive.

Exceptions

ArgumentOutOfRangeException

exponent is outside the supported range.

AsRandom()

Presents this stream as a Random, for APIs and libraries that ask for the framework type.

public StreamBackedRandom AsRandom()

Returns

StreamBackedRandom

A new adapter that draws from this stream, so draws through either one advance the same state.

Clone()

Creates an independent copy of this stream at its present position.

public RandomStream Clone()

Returns

RandomStream

A stream that will produce the same values as this one from now on.

FromState(RandomStreamState, string?)

Rebuilds a stream from a snapshot taken by SaveState().

public static RandomStream FromState(RandomStreamState state, string? name = null)

Parameters

state RandomStreamState

The snapshot to restore.

name string

An optional label overriding the one in the snapshot.

Returns

RandomStream

A stream positioned exactly where the snapshot was taken.

Exceptions

ArgumentNullException

state is null.

ArgumentException

The snapshot is of an unknown version or holds an invalid state.

LoadState(RandomStreamState)

Restores this stream from a snapshot, discarding its present position.

public void LoadState(RandomStreamState state)

Parameters

state RandomStreamState

The snapshot to restore.

Remarks

The anchors of a snapshot have to agree: SubstreamStart must be the start of substream SubstreamIndex of StreamStart, the relation every stream this library produces satisfies. Checking it costs one modular matrix exponentiation and is what keeps a restored stream inside its own block, since the substream operations trust the index to say where the stream is.

Exceptions

ArgumentNullException

state is null.

ArgumentException

The snapshot is of an unknown version or holds an invalid state.

Next(int)

Draws an integer uniform over a half-open range starting at zero, following the .NET convention.

public int Next(int maxExclusive)

Parameters

maxExclusive int

One past the largest value that can be returned.

Returns

int

A value at least zero and below maxExclusive, or zero when maxExclusive is zero.

Exceptions

ArgumentOutOfRangeException

maxExclusive is negative.

Next(int, int)

Draws an integer uniform over a half-open range, following the .NET convention.

public int Next(int minInclusive, int maxExclusive)

Parameters

minInclusive int

Smallest value that can be returned.

maxExclusive int

One past the largest value that can be returned.

Returns

int

A value at least minInclusive and below maxExclusive, or minInclusive when the two bounds are equal.

Exceptions

ArgumentOutOfRangeException

maxExclusive is below minInclusive.

NextDouble()

Draws the next value, uniform on the open interval from zero to one.

public double NextDouble()

Returns

double

A value strictly between zero and one.

Remarks

Honours both Antithetic and HighPrecision. With high precision off the result is always an exact multiple of 1 / (2^32 - 208).

NextDoubleHighPrecision()

Draws the next value with roughly 53 bits of precision, advancing the state by two steps, whatever HighPrecision is set to.

public double NextDoubleHighPrecision()

Returns

double

A value strictly between zero and one.

NextDoubles(double[])

Fills an array with values uniform on the open interval from zero to one.

public void NextDoubles(double[] buffer)

Parameters

buffer double[]

The array to fill.

Exceptions

ArgumentNullException

buffer is null.

NextDoubles(double[], int, int)

Fills part of an array with values uniform on the open interval from zero to one.

public void NextDoubles(double[] buffer, int offset, int count)

Parameters

buffer double[]

The array to write into.

offset int

Index of the first element to write.

count int

Number of elements to write.

Exceptions

ArgumentNullException

buffer is null.

ArgumentOutOfRangeException

The range lies outside buffer.

NextDoubles(Span<double>)

Fills a span with values uniform on the open interval from zero to one.

public void NextDoubles(Span<double> destination)

Parameters

destination Span<double>

The span to fill.

NextInt32Inclusive(int, int)

Draws an integer uniform over a closed range.

public int NextInt32Inclusive(int min, int max)

Parameters

min int

Smallest value that can be returned.

max int

Largest value that can be returned, included in the range.

Returns

int

A value between min and max inclusive.

Exceptions

ArgumentOutOfRangeException

max is below min.

NextInt32sInclusive(int, int, int[], int, int)

Fills part of an array with integers uniform over a closed range.

public void NextInt32sInclusive(int min, int max, int[] buffer, int offset, int count)

Parameters

min int

Smallest value that can be produced.

max int

Largest value that can be produced, included in the range.

buffer int[]

The array to write into.

offset int

Index of the first element to write.

count int

Number of elements to write.

Exceptions

ArgumentNullException

buffer is null.

ArgumentOutOfRangeException

The range lies outside buffer, or max is below min.

NextInt32sInclusive(int, int, Span<int>)

Fills a span with integers uniform over a closed range.

public void NextInt32sInclusive(int min, int max, Span<int> destination)

Parameters

min int

Smallest value that can be produced.

max int

Largest value that can be produced, included in the range.

destination Span<int>

The span to fill.

Exceptions

ArgumentOutOfRangeException

max is below min.

NextInt64(long)

Draws an integer uniform over a half-open range starting at zero, following the .NET convention.

public long NextInt64(long maxExclusive)

Parameters

maxExclusive long

One past the largest value that can be returned.

Returns

long

A value at least zero and below maxExclusive, or zero when maxExclusive is zero.

Remarks

See NextInt64Inclusive(long, long) for how many distinct values a wide range can yield.

Exceptions

ArgumentOutOfRangeException

maxExclusive is negative.

NextInt64(long, long)

Draws an integer uniform over a half-open range, following the .NET convention.

public long NextInt64(long minInclusive, long maxExclusive)

Parameters

minInclusive long

Smallest value that can be returned.

maxExclusive long

One past the largest value that can be returned.

Returns

long

A value at least minInclusive and below maxExclusive, or minInclusive when the two bounds are equal.

Remarks

See NextInt64Inclusive(long, long) for how many distinct values a wide range can yield.

Exceptions

ArgumentOutOfRangeException

maxExclusive is below minInclusive, or the range holds more than MaxValue values.

NextInt64Inclusive(long, long)

Draws an integer uniform over a closed range.

public long NextInt64Inclusive(long min, long max)

Parameters

min long

Smallest value that can be returned.

max long

Largest value that can be returned, included in the range.

Returns

long

A value between min and max inclusive.

Remarks

This makes one call to NextDouble() and scales the result over the closed range. A single draw carries about 2^32 distinct values, or about 2^53 in high-precision mode, so over a range wider than that most values in the range can never be returned.

Exceptions

ArgumentOutOfRangeException

max is below min, or the range holds more than MaxValue values.

RetreatByPowerOfTwo(int)

Moves the current position of this stream backwards by 2^exponent steps, leaving its initial state and its substream start untouched.

public void RetreatByPowerOfTwo(int exponent)

Parameters

exponent int

A base-two exponent between 0 and 255 inclusive.

Exceptions

ArgumentOutOfRangeException

exponent is outside the supported range.

RewindStream()

Returns this stream to its initial state, at the start of its first substream.

public void RewindStream()

RewindSubstream()

Returns this stream to the start of the substream it is currently inside.

public void RewindSubstream()

SaveState()

Captures everything needed to resume this stream later or elsewhere.

public RandomStreamState SaveState()

Returns

RandomStreamState

A fresh snapshot, safe to serialize.

SkipSubstreams(long)

Moves this stream by a signed number of substreams, to the start of the substream it lands on.

public void SkipSubstreams(long count)

Parameters

count long

Substreams to move; negative values move back towards the stream start.

Remarks

The cost grows with the logarithm of count rather than with count itself, because the move is one modular matrix exponentiation per component and not a run of substream jumps. Skipping a million substreams costs about as much as skipping twenty.

A count of zero does nothing at all, and in particular does not return to the start of the current substream; RewindSubstream() does that.

Exceptions

ArgumentOutOfRangeException

The move would leave this stream's own block, that is it would land before substream zero or at or beyond substream 2^51.

SkipToNextSubstream()

Moves this stream to the start of its next substream, 2^76 values further on.

public void SkipToNextSubstream()

Remarks

The exception is a guard on the partitioning rather than a case to program around: reaching it takes 2^51 calls. Use SkipSubstreams(long) to move by more than one substream at a time.

Exceptions

InvalidOperationException

This stream is already on the last of its substreams, so a further one would lie outside its own block.

SkipToSubstream(long)

Moves this stream to the start of the substream at the given index of this stream.

public void SkipToSubstream(long index)

Parameters

index long

A zero-based substream index below 2^51.

Remarks

The index is counted from the start of this stream, not from where it happens to be, so the call lands in the same place however the stream was used beforehand. It is the operation to use to resume a run at a known replication, or to give worker i substream i without walking there. Its cost grows with the logarithm of index.

Exceptions

ArgumentOutOfRangeException

index is negative, or at or beyond the 2^51 substreams this stream holds.

ToDetailedString()

Returns the name of this stream, its three state vectors, its substream index, and its flags.

public string ToDetailedString()

Returns

string

Several lines of text.

ToString()

Returns the name of this stream together with its current state.

public override string ToString()

Returns

string

A single line of text.