All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spire.random.rng.Marsaglia32a6.scala Maven / Gradle / Ivy

package spire.random
package rng

import java.nio.ByteBuffer
import java.util.Arrays

// Contributed by Rex Kerr

/**
 * Marsaglia "Weyl sequence" RNG with cycle length of 2^192^ - 2^32^
 * from [[http://www.jstatsoft.org/v08/i14/paper]]. Quite fast and
 * quite random; requires 24 bytes of state.
 */
class Marsaglia32a6(_x: Int, _y: Int, _z: Int, _w: Int, _v: Int, _d: Int) extends IntBasedGenerator {
  private[this] var x: Int = _x
  private[this] var y: Int = _y
  private[this] var z: Int = _z
  private[this] var w: Int = _w
  private[this] var v: Int = _v
  private[this] var d: Int = _d

  def copyInit: Marsaglia32a6 = new Marsaglia32a6(x, y, z, w, v, d)

  def getSeed: Array[Int] = {
    val ints = new Array[Int](6)
    ints(0) = x
    ints(1) = y
    ints(2) = z
    ints(3) = w
    ints(4) = v
    ints(5) = d
    ints
  }

  def setSeed(seed: Array[Int]): Unit = {
    val zs = if (seed.length < 6) Arrays.copyOf(seed, 6) else seed
    x = zs(0)
    y = zs(0)
    z = zs(0)
    w = zs(0)
    v = zs(0)
    d = zs(0)
  }

  def getSeedBytes: Array[Byte] = {
    val bytes = new Array[Byte](24)
    val bb = ByteBuffer.wrap(bytes)
    bb.putInt(x)
    bb.putInt(y)
    bb.putInt(z)
    bb.putInt(w)
    bb.putInt(v)
    bb.putInt(d)
    bytes
  }

  def setSeedBytes(bytes: Array[Byte]): Unit = {
    val bs = if (bytes.length < 24) Arrays.copyOf(bytes, 24) else bytes
    val bb = ByteBuffer.wrap(bs)
    x = bb.getInt()
    y = bb.getInt()
    z = bb.getInt()
    w = bb.getInt()
    v = bb.getInt()
    d = bb.getInt()
  }

  def nextInt(): Int = {
    val t = x ^ (x >>> 2)
    x = y
    y = z
    z = w
    w = v
    v = v ^ (v << 4) ^ (t ^ (t << 1))
    d += 362437
    d + v
  }
}

object Marsaglia32a6 extends GeneratorCompanion[Marsaglia32a6, Array[Int]] {
  def fromBytes(bytes: Array[Byte]): Marsaglia32a6 = {
    val bs = if (bytes.length < 24) Arrays.copyOf(bytes, 24) else bytes
    val bb = ByteBuffer.wrap(bytes)
    val x = bb.getInt()
    val y = bb.getInt()
    val z = bb.getInt()
    val w = bb.getInt()
    val v = bb.getInt()
    val d = bb.getInt()
    new Marsaglia32a6(x, y, z, w, v, d)
  }

  def fromSeed(ints: Array[Int]): Marsaglia32a6 = {
    val zs = if (ints.length < 6) Arrays.copyOf(ints, 6) else ints
    new Marsaglia32a6(zs(0), zs(1), zs(2), zs(3), zs(4), zs(5))
  }

  def fromTime(time: Long = System.nanoTime): Marsaglia32a6 = {
    val lcg = Lcg64.fromTime(time)
    val x = lcg.nextInt()
    val y = lcg.nextInt()
    val z = lcg.nextInt()
    val w = lcg.nextInt()
    val v = lcg.nextInt()
    val d = lcg.nextInt()
    new Marsaglia32a6(x, y, z, w, v, d)
  }

  def randomSeed: Array[Int] = GlobalRng.generateInts(6)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy