lang/js/ SimpleSeedablePseudorandomNumberGenerator


// linear congruence rng
// constants taken from on 'gcc' entry in table at 
// https://en.wikipedia.org/wiki/Linear_congruential_generator

class Rand {
  constructor(s = 0, a = 1103515245, c = 12345, m = 2**31) {
    this.init(a,c,m)
    this.seed(s)
  }
  init(a,c,m) {
    this.a = a | 0
    this.c = c | 0
    this.m = m | 0
    return this
  }
  seed(s = 0) {
    this.x = (s | 0) % this.m
    this.rand()
    this.rand()
    return this
  }
  snow() {
    this.seed(Date.now())
    return this
  }
  inc() {
    this.x = (((this.x * this.a) + this.c) % this.m) | 0
    return this
  }
  rand() {
    const x = this.x
    this.inc()
    return x
  }
  rands(n) {
    n |= 0
    return (new Array(n)).fill().map(_ => this.rand())
  }
}

const example = _ => {
  let r = new Rand()

  for(let i=0; i<10; i++) {
    console.log({x:r.rand()})
  }

  r.seed(10)
  for(let i=0; i<10; i++) {
    console.log({x:r.rand()})
  }

  r.snow()
  for(let i=0; i<10; i++) {
    console.log({x:r.rand()})
  }

  console.log(r.rands(10/))
}

A One-Liner

PRNG = (s=0,a=1103515245,c=12345,m=2**31) => { const f =  _ => (x = (((x * a) + c) % m)); f.seed = s => { x = s | 0; f(); f(); return f; }; return f.seed(s); }

example:

const example = _ => {
  let p = PRNG() // seed with 0
  console.log(p(),p())
  p.seed(Date.now())
  console.log(p(),p())
  p.seed(0) 
  console.log(p(),p()) // demonstrate reproducibility
}