Skip to content

Instantly share code, notes, and snippets.

@mepcotterell
Created January 27, 2013 00:12
Show Gist options
  • Save mepcotterell/4645416 to your computer and use it in GitHub Desktop.
Save mepcotterell/4645416 to your computer and use it in GitHub Desktop.
Stream-based Linear Congruential Generator in Scala
/**
* Linear Congruential Generator
*
* This implementation allows you to grab an individual number by its index. It
* also provides a stats object for displaying statistics about the lcg.
*
* @see http://en.wikipedia.org/wiki/Linear_congruential_generator
* @author Michael E. Cotterell <[email protected]>
* @param a the multiplier
* @param c the increment
* @param m the modulus
* @param seed start value
*/
case class LCG (a: Long, c: Long, m: Long, seed: Long) {
import scala.language.postfixOps
private val ref = this
private val m_inverse = 1.0 / m.toDouble
private var i: Int = 1
private lazy val stream: Stream[Long] = 0L #:: seed #:: stream.zip(stream.tail).map({ case (e, last) => (a * last + c) % m })
def gen: Double = stream({i += 1; i}).toDouble * m_inverse
def get (idx: Int): Double = stream(idx + 2) * m_inverse
def length: Int = i - 1
object stats {
lazy val samples: Array[Double] = stream.take(10000 + 2).drop(2).toArray.map( e => e * m_inverse )
lazy val ms: Double = samples.map( e => e * e ).sum / samples.length
lazy val mean: Double = samples.sum / samples.length
lazy val variance: Double = ms - mean * mean
override def toString: String = "%s.stats(samples = %5d, mean = %3.3f, variance = %3.3f)".format(ref, samples.length, mean, variance)
} // test
} // LCG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment