MRG32k3a Combined recursive generator (pseudo-code)

   /* Constants */
   /* First generator */
   a1 = [0, 1403580, -810728]
   m1 = 2**32 - 209
   /* Second Generator */
   a2 = [527612, 0, -1370589]
   m2 = 2**32 - 22853
    
   d = m1 + 1
   
   class MRG32k3a
       x1 = [0, 0, 0]  /* list of three last values of gen #1 */
       x2 = [0, 0, 0]  /* list of three last values of gen #2 */
       
       method seed(u64 seed_state)
           assert seed_state in range >0 and < d 
           x1 = [seed_state, 0, 0]
           x2 = [seed_state, 0, 0]
       end method
           
       method next_int()
           x1i = (a1[0]*x1[0] + a1[1]*x1[1] + a1[2]*x1[2]) mod m1
           x2i = (a2[0]*x2[0] + a2[1]*x2[1] + a2[2]*x2[2]) mod m2
           x1 = [x1i, x1[0], x1[1]]    /* Keep last three */
           x2 = [x2i, x2[0], x2[1]]    /* Keep last three */
           z = (x1i - x2i) % m1
           answer = (z + 1)
           
           return answer
       end method
       
       method next_float():
           return float next_int() / d
       end method
       
   end class


MRG32k3a Use:
   random_gen = instance MRG32k3a
   random_gen.seed(1234567)
   print(random_gen.next_int())   /* 1459213977 */
   print(random_gen.next_int())   /* 2827710106 */
   print(random_gen.next_int())   /* 4245671317 */
   print(random_gen.next_int())   /* 3877608661 */
   print(random_gen.next_int())   /* 2595287583 */
   
       

Task
 Generate a class/set of functions that generates pseudo-random
numbers as shown above.

 Show that the first five integers generated with the seed `1234567`
are as shown above

 Show that for an initial seed of '987654321' the counts of 100_000
repetitions of

   floor(random_gen.next_float() * 5)

Is as follows:

   0: 20002, 1: 20060, 2: 19948, 3: 20059, 4: 19931

 Show your output here, on this page.


package main
 
import (
    "fmt"
    "log"
    "math"
)
 
var a1 = []int64{0, 1403580, -810728}
var a2 = []int64{527612, 0, -1370589}
 
const m1 = int64((1 << 32) - 209)
const m2 = int64((1 << 32) - 22853)
const d = m1 + 1
 
// Python style modulus
func mod(x, y int64) int64 {
    m := x % y
    if m < 0 {
        if y < 0 {
            return m - y
        } else {
            return m + y
        }
    }
    return m
}
 
type MRG32k3a struct{ x1, x2 [3]int64 }
 
func MRG32k3aNew() *MRG32k3a { return &MRG32k3a{} }
 
func (mrg *MRG32k3a) seed(seedState int64) {
    if seedState <= 0 || seedState >= d {
        log.Fatalf("Argument must be in the range [0, %d].\n", d)
    }
    mrg.x1 = [3]int64{seedState, 0, 0}
    mrg.x2 = [3]int64{seedState, 0, 0}
}
 
func (mrg *MRG32k3a) nextInt() int64 {
    x1i := mod(a1[0]*mrg.x1[0]+a1[1]*mrg.x1[1]+a1[2]*mrg.x1[2], m1)
    x2i := mod(a2[0]*mrg.x2[0]+a2[1]*mrg.x2[1]+a2[2]*mrg.x2[2], m2)
    mrg.x1 = [3]int64{x1i, mrg.x1[0], mrg.x1[1]} /* keep last three */
    mrg.x2 = [3]int64{x2i, mrg.x2[0], mrg.x2[1]} /* keep last three */
    return mod(x1i-x2i, m1) + 1
}
 
func (mrg *MRG32k3a) nextFloat() float64 { return float64(mrg.nextInt()) / float64(d) }
 
func main() {
    randomGen := MRG32k3aNew()
    randomGen.seed(1234567)
    for i := 0; i < 5; i++ {
        fmt.Println(randomGen.nextInt())
    }
 
    var counts [5]int
    randomGen.seed(987654321)
    for i := 0; i < 1e5; i++ {
        j := int(math.Floor(randomGen.nextFloat() * 5))
        counts[j]++
    }
    fmt.Println("\nThe counts for 100,000 repetitions are:")
    for i := 0; i < 5; i++ {
        fmt.Printf("  %d : %d\n", i, counts[i])
    }
}