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

scala.concurrent.stm.skel.SimpleRandom.scala Maven / Gradle / Ivy

The newest version!
/* scala-stm - (c) 2009-2011, Stanford University, PPL */

package scala.concurrent.stm.skel


/** A random number generator that focuses on speed and lack of inter-thread
 *  interference, rather than on the quality of the numbers returned.  The
 *  `object SimpleRandom` is striped internally to reduce
 *  contention when accessed from multiple threads.  The `class
 *  SimpleRandom` should only be used by a single thread.
 *  

* The constants in this 64-bit linear congruential random number generator * are from http://nuclear.llnl.gov/CNP/rng/rngman/node4.html. * * @author Nathan Bronson */ object SimpleRandom { // 64 byte cache lines are typical, so there are 8 slots per cache line. // This means that the probability that any two threads have false sharing is // p = 8 / #slots. If there are n processors, each of which is running 1 // thread, then the probability that no other threads have false sharing with // the current thread is (1-p)^(n-1). If p is small, that is about // 1 - (n-1)p, which is pretty close to 1 - np. If we want the probability // of false conflict for a thread to be less than k, then we need np < k, or // p < k/n, or 8/Slots < k/n, or #slots > 8n/k. If we let k = 1/8, then we // get #slots=64*n. private val mask = { val min = 64 * Runtime.getRuntime.availableProcessors var slots = 1 while (slots < min) slots *= 2 slots - 1 } private val states = Array.tabulate(mask + 1)({ _ * 0x123456789abcdefL }) /** Returns a random value chosen from a uniform distribution of all valid * `Int`s. */ def nextInt(): Int = { val id = (Thread.currentThread.getId.asInstanceOf[Int] * 13) & mask val next = step(states(id)) states(id) = next extract(next) } /** Returns a random value chosen from a uniform distribution of the * non-negative integers less than `n`, or throws `IllegalArgumentException` * if `n` is negative or zero. */ def nextInt(n: Int): Int = { if (n <= 0) throw new IllegalArgumentException var x = -1 while (x == -1) x = tryClamp(nextInt(), n) x } private def step(x: Long) = x * 2862933555777941757L + 3037000493L private def extract(x: Long) = (x >> 30).asInstanceOf[Int] /** r is the random, returns -1 on failure. */ private def tryClamp(r: Int, n: Int): Int = { // get a positive number val x = r & Int.MaxValue if ((n & -n) == n) { // for powers of two, we use high bits instead of low bits ((x.toLong * n) >> 31).toInt } else { val z = x % n if (x - z + (n - 1) < 0) { // x is bigger than floor(MAX_INT/n)*n, so we are not getting an even // distribution. Try again. -1 } else { z } } } } /** An clonable unsynchronized random number generator that uses the same * algorithm as the concurrent `object SimpleRandom`. The caller must ensure * that each `SimpleRandom` instance is used from only one thread at a time. * * @author Nathan Bronson */ class SimpleRandom private (private var _state: Long, dummy: Boolean) { import SimpleRandom._ def this(seed: Int) = this(SimpleRandom.step(SimpleRandom.step(seed)), false) def this() = this(System.identityHashCode(Thread.currentThread)) override def clone = new SimpleRandom(_state, false) /** Returns a random value chosen from a uniform distribution of all valid * `Int`s. */ def nextInt(): Int = { _state = step(_state) extract(_state) } /** Returns a random value chosen from a uniform distribution of the * non-negative integers less than `n`, or throws `IllegalArgumentException` * if `n` is negative or zero. */ def nextInt(n: Int): Int = { if (n <= 0) throw new IllegalArgumentException var x = -1 while (x == -1) x = tryClamp(nextInt(), n) x } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy