rngstream

package module
v0.2.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2023 License: MIT Imports: 3 Imported by: 5

README

RngStream

Report Card Go Reference

Package rngstream is 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 main description and documentation is in the c++ package, in the paper streams4.pdf.
The implementations for c and java give a short description of the interfaces in C and Java, respectively.

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.

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

Thank you.

(The above text modified from http://www.iro.umontreal.ca/~lecuyer/myftp/streams00/readme.txt).

This Go translation is copyright 2023 The Board of Trustees of the University of Illinois. See LICENSE.md for details.

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func SetPackageSeed

func SetPackageSeed(seed []uint64) bool

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

func New(name string) *RngStream

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

func (g *RngStream) AdvanceState(e, c int64)

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

func (g *RngStream) GetState() []uint64

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

func (g *RngStream) RandInt(i int, j int) int

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

func (g *RngStream) RandU01() float64

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

func (g *RngStream) SetAntithetic(a bool)

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

func (g *RngStream) SetIncreasedPrecis(incp bool)

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

func (g *RngStream) SetSeed(seed []uint64) bool

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}

Directories

Path Synopsis
Example code.
Example code.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL