Documentation ¶
Overview ¶
Package rngstream is a Go implementation of RngStreams, an object-oriented random-number package with many long streams and substreams, based on the MRG32k3a RNG from reference [1] below and proposed in [2].
It has implementations in C, C++, Go, Java, R, OpenCL, and some other languages.
The package is copyrighted by Pierre L'Ecuyer and the University of Montreal. It can be used freely for any purpose.
e-mail: lecuyer@iro.umontreal.ca http://www.iro.umontreal.ca/~lecuyer/
If you use it for your research, please cite the following relevant publications in which MRG32k3a and the package with multiple streams were proposed:
[1] P. L'Ecuyer, “Good Parameter Sets for Combined Multiple Recursive Random Number Generators”, Operations Research, 47, 1 (1999), 159--164. See https://www-labs.iro.umontreal.ca/~lecuyer/myftp/papers/opres-combmrg2-1999.pdf
[2] P. L'Ecuyer, R. Simard, E. J. Chen, and W. D. Kelton, “An Objected-Oriented Random-Number Package with Many Long Streams and Substreams”, Operations Research, 50, 6 (2002), 1073--1075 See https://www-labs.iro.umontreal.ca/~lecuyer/myftp/papers/streams00.pdf
This Go translation is copyright 2023 The Board of Trustees of the University of Illinois. All rights reserved.
Index ¶
- func SetPackageSeed(seed []uint64) bool
- func SetRngStreamMasterSeed(seed uint64)
- type RngStream
- func (g *RngStream) AdvanceState(e, c int64)
- func (g *RngStream) GetState() []uint64
- func (g *RngStream) RandInt(i int, j int) int
- func (g *RngStream) RandU01() float64
- func (g *RngStream) ResetNextSubstream()
- func (g *RngStream) ResetStartStream()
- func (g *RngStream) ResetStartSubstream()
- func (g *RngStream) SetAntithetic(a bool)
- func (g *RngStream) SetIncreasedPrecis(incp bool)
- func (g *RngStream) SetSeed(seed []uint64) bool
- func (g *RngStream) WriteState()
- func (g *RngStream) WriteStateFull()
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SetPackageSeed ¶
SetPackageSeed sets the initial seed s0 of the package to the six integers in the vector seed. The first 3 integers in the seed must all be less than m1 = 4294967087, and not all 0; and the last 3 integers must all be less than m2 = 4294944443, and not all 0. If this method is not called, the default initial seed is (12345, 12345, 12345, 12345, 12345, 12345). Returns false for invalid seeds, and true otherwise.
See also SetRngStreamMasterSeed
Example (Equal) ¶
package main import ( "fmt" "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Construct two generators with identical seeds rngstream.SetPackageSeed(initialSeed) g1 := rngstream.New("g1") rngstream.SetPackageSeed(initialSeed) g2 := rngstream.New("g2") b1 := g1.RandU01() == g2.RandU01() b2 := g1.RandU01() == g2.RandU01() fmt.Printf("%v %v\n", b1, b2) }
Output: true true
Example (Notequal) ¶
package main import ( "fmt" "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Construct two generators, but allow the seed to advance for second rngstream.SetPackageSeed(initialSeed) g1 := rngstream.New("g1") g2 := rngstream.New("g2") b1 := g1.RandU01() == g2.RandU01() b2 := g1.RandU01() == g2.RandU01() fmt.Printf("%v %v\n", b1, b2) }
Output: false false
func SetRngStreamMasterSeed ¶
func SetRngStreamMasterSeed(seed uint64)
SetRngStreamMasterSeed sets the initial seed s0 of the package to the six successive integers starting with `seed`. Seed must be less than 4294944443-6.
See also SetPackageSeed.
Example (Equal) ¶
package main import ( "fmt" "github.com/iti/rngstream" ) func main() { // Construct two generators with identical seeds rngstream.SetRngStreamMasterSeed(5555) g1 := rngstream.New("g1") rngstream.SetRngStreamMasterSeed(5555) g2 := rngstream.New("g2") b1 := g1.RandU01() == g2.RandU01() b2 := g1.RandU01() == g2.RandU01() fmt.Printf("%v %v\n", b1, b2) }
Output: true true
Example (Notequal) ¶
package main import ( "fmt" "github.com/iti/rngstream" ) func main() { // Construct two generators, but allow the seed to advance for second rngstream.SetRngStreamMasterSeed(5555) g1 := rngstream.New("g1") g2 := rngstream.New("g2") b1 := g1.RandU01() == g2.RandU01() b2 := g1.RandU01() == g2.RandU01() fmt.Printf("%v %v\n", b1, b2) }
Output: false false
Types ¶
type RngStream ¶
type RngStream struct {
// contains filtered or unexported fields
}
RngStream contains the (opaque) state required to completely describe a single stream.
Example ¶
package main import ( "fmt" "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { var g *rngstream.RngStream // Reset seed to make test deterministic rngstream.SetPackageSeed(initialSeed) g = rngstream.New("g") b := g.RandU01() == g.RandU01() fmt.Printf("%v\n", b) }
Output: false
func New ¶
New creates a new stream with (optional) descriptor `name`. It initializes its seed Ig, and sets Bg and Cg to Ig. It also sets its `anti` and `incPrec` switches to false. The seed Ig is equal to the initial seed of the package if this is the first stream created; otherwise it is Z steps ahead of the seed of the most recently created stream.
Example ¶
package main import ( "fmt" "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Reset seed to make test deterministic rngstream.SetPackageSeed(initialSeed) // Create a random number generator g := rngstream.New("g") // Fetch some pseudo-random numbers f1 := g.RandU01() f2 := g.RandU01() fmt.Printf("%.5f %.5f\n", f1, f2) }
Output: 0.12701 0.31853
Example (Double) ¶
package main import ( "fmt" "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Reset seed to make test deterministic rngstream.SetPackageSeed(initialSeed) // Each call to New gets a distinct seed g1 := rngstream.New("g1") g2 := rngstream.New("g2") // Fetch some pseudo-random numbers f1_1 := g1.RandU01() f1_2 := g1.RandU01() f2_1 := g2.RandU01() f2_2 := g2.RandU01() fmt.Printf("%.5f %.5f %.5f %.5f\n", f1_1, f1_2, f2_1, f2_2) }
Output: 0.12701 0.31853 0.75958 0.97831
func (*RngStream) AdvanceState ¶
AdvanceState advances the state by n steps (see below for the meaning of n), without modifying the states of other streams or the values of Bg and Ig in the current object. If e > 0, then n = 2**e + c; if e < 0, then n = −2**−e + c; and if e = 0, then n = c. Note: c is allowed to take negative values. We discourage the use of this method.
Example (Equal) ¶
package main import ( "fmt" "github.com/iti/rngstream" ) func main() { // Construct two generators with identical seeds rngstream.SetRngStreamMasterSeed(5555) g1 := rngstream.New("g1") rngstream.SetRngStreamMasterSeed(5555) g2 := rngstream.New("g2") // Consume 10 random numbers for i := 0; i < 10; i++ { g1.RandU01() } // Consume 10 random numbers g2.AdvanceState(0, 10) b := g1.RandU01() == g2.RandU01() fmt.Printf("%v\n", b) }
Output: true
func (*RngStream) GetState ¶
GetState returns the current state Cg of this stream. This is convenient if we want to save the state for subsequent use.
Example ¶
package main import ( "fmt" "github.com/iti/rngstream" ) func main() { // Construct generator with known state rngstream.SetRngStreamMasterSeed(5555) g1 := rngstream.New("g1") // Consume 10 random numbers g1.AdvanceState(0, 10) // Grab the current state & get a random number. state := g1.GetState() r1 := g1.RandU01() // Consume 10 more random numbers g1.AdvanceState(0, 10) // Restore the state & get a random number. g1.SetSeed(state) r2 := g1.RandU01() b := r1 == r2 fmt.Printf("%v\n", b) }
Output: true
func (*RngStream) RandInt ¶
RandInt returns a (pseudo)random number from the discrete uniform distribution over the integers {i, i + 1,...,j} Makes one call to RandU01.
Example ¶
package main import ( "fmt" "github.com/iti/rngstream" ) func main() { // Construct generator with known state rngstream.SetRngStreamMasterSeed(5555) g1 := rngstream.New("g1") // Generate some numbers fmt.Printf("%v %v %v %v\n", g1.RandInt(1, 3), g1.RandInt(1, 3), g1.RandInt(1, 3), g1.RandInt(1, 3)) }
Output: 3 3 1 2
func (*RngStream) RandU01 ¶
RandU01 normally returns a (pseudo)random number from the uniform distribution over the interval (0, 1), after advancing the state by one step. The returned number has 32 bits of precision in the sense that it is always a multiple of 1/(2^32 −208). However, if IncreasedPrecis(true) has been called for this stream, the state is advanced by two steps and the returned number has 53 bits of precision.
Example ¶
package main import ( "fmt" "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Reset seed to make test deterministic rngstream.SetPackageSeed(initialSeed) // Create a random number generator g := rngstream.New("g") // Fetch some pseudo-random numbers f1 := g.RandU01() f2 := g.RandU01() fmt.Printf("%.5f %.5f\n", f1, f2) }
Output: 0.12701 0.31853
func (*RngStream) ResetNextSubstream ¶
func (g *RngStream) ResetNextSubstream()
ResetNextSubstream reinitializes the stream to the beginning of its next substream: Ng is computed, and Cg and Bg are set to Ng.
func (*RngStream) ResetStartStream ¶
func (g *RngStream) ResetStartStream()
ResetStartStream Reinitializes the stream to its initial state: Cg and Bg are set to Ig.
func (*RngStream) ResetStartSubstream ¶
func (g *RngStream) ResetStartSubstream()
ResetStartSubstream reinitializes the stream to the beginning of its current substream: Cg is set to Bg.
func (*RngStream) SetAntithetic ¶
SetAntithetic write the `anti` internal variable. If a = true, the stream will start generating antithetic variates, i.e., 1 − U instead of U, until this method is called again with a = false.
func (*RngStream) SetIncreasedPrecis ¶
SetIncreasedPrecis writes to the internal incPrec variable. After calling this method with incp = true, each call to the generator (direct or indirect) for this stream will return a uniform random number with more bits of resolution (53 bits if machine follows IEEE 754 standard) instead of 32 bits, and will advance the state of the stream by 2 steps instead of 1. More precisely, if s is a stream of the class RngStream, in the nonantithetic case, the instruction “u = s.RandU01()” will be equivalent to “u = (s.RandU01() + s.RandU01() * fact) % 1.0” where the constant fact is equal to 2−24. This also applies when calling RandU01 indirectly (e.g., via RandInt, etc.). By default, or if this method is called again with incp = false, each call to RandU01 for this stream advances the state by 1 step and returns a number with 32 bits of resolution.
func (*RngStream) SetSeed ¶
SetSeed sets the initial seed Ig of the stream to the vector seed. The vector seed should contain valid seed values as described in SetPackageSeed. The state of the stream is then reset to this initial seed. The states and seeds of the other streams are not modified. As a result, after calling this method, the initial seeds of the streams are no longer spaced Z values apart. We discourage the use of this method; proper use of the Reset* methods is preferable. Returns false for invalid seeds, and true otherwise.
Example ¶
package main import ( "fmt" "github.com/iti/rngstream" ) func main() { // Construct generator with known state rngstream.SetRngStreamMasterSeed(5555) g1 := rngstream.New("g1") // Consume 10 random numbers g1.AdvanceState(0, 10) // Grab the current state & get a random number. state := g1.GetState() r1 := g1.RandU01() // Consume 10 more random numbers g1.AdvanceState(0, 10) // Restore the state & get a random number. g1.SetSeed(state) r2 := g1.RandU01() b := r1 == r2 fmt.Printf("%v\n", b) }
Output: true
func (*RngStream) WriteState ¶
func (g *RngStream) WriteState()
WriteState writes (to standard output) the current state Cg of this stream.
Example ¶
package main import ( "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Reset seed to make test deterministic rngstream.SetPackageSeed(initialSeed) // Construct a generator g := rngstream.New("g") // Initial state value g.WriteState() // Consume 10 random numbers for i := 0; i < 10; i++ { g.RandU01() } // Current state value g.WriteState() }
Output: g: Cg = {12345,12345,12345,12345,12345,12345 } g: Cg = {2989318136,3378525425,1773647758,1462200156,2794459678,2822254363 }
func (*RngStream) WriteStateFull ¶
func (g *RngStream) WriteStateFull()
WriteStateFull writes (to standard output) the value of all the internal variables of this stream: name, anti, incPrec, Ig, Bg, Cg.
Example ¶
package main import ( "github.com/iti/rngstream" ) var initialSeed = []uint64{12345, 12345, 12345, 12345, 12345, 12345} func main() { // Reset seed to make test deterministic rngstream.SetPackageSeed(initialSeed) // Construct a generator g := rngstream.New("g") // Initial state value g.WriteStateFull() }
Output: g: Anti = false IncPrec = false Ig = { 12345,12345,12345,12345,12345,12345 } Bg = { 12345,12345,12345,12345,12345,12345 } Cg = { 12345,12345,12345,12345,12345,12345}