mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
better docs: random (#10546)
This commit is contained in:
@@ -7,12 +7,76 @@
|
||||
# distribution, for details about the copyright.
|
||||
#
|
||||
|
||||
## Nim's standard random number generator. Based on
|
||||
## the ``xoroshiro128+`` (xor/rotate/shift/rotate) library.
|
||||
## Nim's standard random number generator.
|
||||
##
|
||||
## Its implementation is based on the ``xoroshiro128+``
|
||||
## (xor/rotate/shift/rotate) library.
|
||||
## * More information: http://xoroshiro.di.unimi.it/
|
||||
## * C implementation: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
|
||||
##
|
||||
## **Do not use this module for cryptographic purposes!**
|
||||
##
|
||||
## Basic usage
|
||||
## ===========
|
||||
##
|
||||
## To get started, here are some examples:
|
||||
##
|
||||
## .. code-block::
|
||||
##
|
||||
## import random
|
||||
##
|
||||
## # Call randomize() once to initialize the default random number generator
|
||||
## # If this is not called, the same results will occur every time these
|
||||
## # examples are run
|
||||
## randomize()
|
||||
##
|
||||
## # Pick a number between 0 and 100
|
||||
## let num = rand(100)
|
||||
## echo num
|
||||
##
|
||||
## # Roll a six-sided die
|
||||
## let roll = rand(1..6)
|
||||
## echo roll
|
||||
##
|
||||
## # Pick a marble from a bag
|
||||
## let marbles = ["red", "blue", "green", "yellow", "purple"]
|
||||
## let pick = sample(marbles)
|
||||
## echo pick
|
||||
##
|
||||
## # Shuffle some cards
|
||||
## var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
|
||||
## shuffle(cards)
|
||||
## echo cards
|
||||
##
|
||||
## These examples all use the default random number generator. The
|
||||
## `Rand type<#Rand>`_ represents the state of a random number generator.
|
||||
## For convenience, this module contains a default Rand state that corresponds
|
||||
## to the default random number generator. Most procs in this module which do
|
||||
## not take in a Rand parameter, including those called in the above examples,
|
||||
## use the default generator. Those procs are **not** thread-safe.
|
||||
##
|
||||
## Note that the default generator always starts in the same state.
|
||||
## The `randomize proc<#randomize>`_ can be called to initialize the default
|
||||
## generator with a seed based on the current time, and it only needs to be
|
||||
## called once before the first usage of procs from this module. If
|
||||
## ``randomize`` is not called, then the default generator will always produce
|
||||
## the same results.
|
||||
##
|
||||
## Generators that are independent of the default one can be created with the
|
||||
## `initRand proc<#initRand,int64>`_.
|
||||
##
|
||||
## Again, it is important to remember that this module must **not** be used for
|
||||
## cryptographic applications.
|
||||
##
|
||||
## See also
|
||||
## ========
|
||||
## * `math module<math.html>`_ for basic math routines
|
||||
## * `mersenne module<mersenne.html>`_ for the Mersenne Twister random number
|
||||
## generator
|
||||
## * `stats module<stats.html>`_ for statistical analysis
|
||||
## * `list of cryptographic and hashing modules
|
||||
## <lib.html#pure-libraries-cryptography-and-hashing>`_
|
||||
## in the standard library
|
||||
|
||||
import algorithm #For upperBound
|
||||
|
||||
@@ -29,9 +93,19 @@ else:
|
||||
const randMax = 18_446_744_073_709_551_615u64
|
||||
|
||||
type
|
||||
Rand* = object ## State of the random number generator.
|
||||
## The procs that use the default state
|
||||
## are **not** thread-safe!
|
||||
Rand* = object ## State of a random number generator.
|
||||
##
|
||||
## Create a new Rand state using the `initRand proc<#initRand,int64>`_.
|
||||
##
|
||||
## The module contains a default Rand state for convenience.
|
||||
## It corresponds to the default random number generator's state.
|
||||
## The default Rand state always starts with the same values, but the
|
||||
## `randomize proc<#randomize>`_ can be used to seed the default generator
|
||||
## with a value based on the current time.
|
||||
##
|
||||
## Many procs have two variations: one that takes in a Rand parameter and
|
||||
## another that uses the default generator. The procs that use the default
|
||||
## generator are **not** thread-safe!
|
||||
a0, a1: ui
|
||||
|
||||
when defined(JS):
|
||||
@@ -48,7 +122,20 @@ proc rotl(x, k: ui): ui =
|
||||
result = (x shl k) or (x shr (ui(64) - k))
|
||||
|
||||
proc next*(r: var Rand): uint64 =
|
||||
## Uses the state to compute a new ``uint64`` random number.
|
||||
## Computes a random ``uint64`` number using the given state.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,Rand,Natural>`_ that returns an integer between zero and
|
||||
## a given upper bound
|
||||
## * `rand proc<#rand,Rand,range[]>`_ that returns a float
|
||||
## * `rand proc<#rand,Rand,HSlice[T,T]>`_ that accepts a slice
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
## * `skipRandomNumbers proc<#skipRandomNumbers,Rand>`_
|
||||
runnableExamples:
|
||||
var r = initRand(2019)
|
||||
doAssert r.next() == 138_744_656_611_299'u64
|
||||
doAssert r.next() == 979_810_537_855_049_344'u64
|
||||
doAssert r.next() == 3_628_232_584_225_300_704'u64
|
||||
let s0 = r.a0
|
||||
var s1 = r.a1
|
||||
result = s0 + s1
|
||||
@@ -57,9 +144,52 @@ proc next*(r: var Rand): uint64 =
|
||||
r.a1 = rotl(s1, 36) # c
|
||||
|
||||
proc skipRandomNumbers*(s: var Rand) =
|
||||
## This is the jump function for the generator. It is equivalent
|
||||
## to 2^64 calls to next(); it can be used to generate 2^64
|
||||
## non-overlapping subsequences for parallel computations.
|
||||
## The jump function for the generator.
|
||||
##
|
||||
## This proc is equivalent to 2^64 calls to `next<#next,Rand>`_, and it can
|
||||
## be used to generate 2^64 non-overlapping subsequences for parallel
|
||||
## computations.
|
||||
##
|
||||
## When multiple threads are generating random numbers, each thread must
|
||||
## own the `Rand<#Rand>`_ state it is using so that the thread can safely
|
||||
## obtain random numbers. However, if each thread creates its own Rand state,
|
||||
## the subsequences of random numbers that each thread generates may overlap,
|
||||
## even if the provided seeds are unique. This is more likely to happen as the
|
||||
## number of threads and amount of random numbers generated increases.
|
||||
##
|
||||
## If many threads will generate random numbers concurrently, it is better to
|
||||
## create a single Rand state and pass it to each thread. After passing the
|
||||
## Rand state to a thread, call this proc before passing it to the next one.
|
||||
## By using the Rand state this way, the subsequences of random numbers
|
||||
## generated in each thread will never overlap as long as no thread generates
|
||||
## more than 2^64 random numbers.
|
||||
##
|
||||
## The following example below demonstrates this pattern:
|
||||
##
|
||||
## .. code-block::
|
||||
## # Compile this example with --threads:on
|
||||
## import random
|
||||
## import threadpool
|
||||
##
|
||||
## const spawns = 4
|
||||
## const numbers = 100000
|
||||
##
|
||||
## proc randomSum(rand: Rand): int =
|
||||
## var r = rand
|
||||
## for i in 1..numbers:
|
||||
## result += rand(1..10)
|
||||
##
|
||||
## var r = initRand(2019)
|
||||
## var vals: array[spawns, FlowVar[int]]
|
||||
## for val in vals.mitems:
|
||||
## val = spawn(randomSum(r))
|
||||
## r.skipRandomNumbers()
|
||||
##
|
||||
## for val in vals:
|
||||
## echo ^val
|
||||
##
|
||||
## See also:
|
||||
## * `next proc<#next,Rand>`_
|
||||
when defined(JS):
|
||||
const helper = [0xbeac0467u32, 0xd86b048bu32]
|
||||
else:
|
||||
@@ -77,22 +207,16 @@ proc skipRandomNumbers*(s: var Rand) =
|
||||
s.a1 = s1
|
||||
|
||||
proc random*(max: int): int {.benign, deprecated.} =
|
||||
## Returns a random number in the range 0..max-1. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount. **Deprecated since version 0.18.0**.
|
||||
## Use ``rand`` instead.
|
||||
## **Deprecated since version 0.18.0:**
|
||||
## Use `rand(int)<#rand,int>`_ instead.
|
||||
while true:
|
||||
let x = next(state)
|
||||
if x < randMax - (randMax mod ui(max)):
|
||||
return int(x mod uint64(max))
|
||||
|
||||
proc random*(max: float): float {.benign, deprecated.} =
|
||||
## Returns a random number in the range 0..<max. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount. **Deprecated since version 0.18.0**.
|
||||
## Use ``rand`` instead.
|
||||
## **Deprecated since version 0.18.0:**
|
||||
## Use `rand(float)<#rand,float>`_ instead.
|
||||
let x = next(state)
|
||||
when defined(JS):
|
||||
result = (float(x) / float(high(uint32))) * max
|
||||
@@ -101,22 +225,29 @@ proc random*(max: float): float {.benign, deprecated.} =
|
||||
result = (cast[float](u) - 1.0) * max
|
||||
|
||||
proc random*[T](x: HSlice[T, T]): T {.deprecated.} =
|
||||
## For a slice `a .. b` returns a value in the range `a .. b-1`.
|
||||
## **Deprecated since version 0.18.0**.
|
||||
## Use ``rand`` instead.
|
||||
## **Deprecated since version 0.18.0:**
|
||||
## Use `rand[T](HSlice[T, T])<#rand,HSlice[T,T]>`_ instead.
|
||||
result = T(random(x.b - x.a)) + x.a
|
||||
|
||||
proc random*[T](a: openArray[T]): T {.deprecated.} =
|
||||
## returns a random element from the openarray `a`.
|
||||
## **Deprecated since version 0.18.0**.
|
||||
## Use ``rand`` instead.
|
||||
## **Deprecated since version 0.18.0:**
|
||||
## Use `sample[T](openArray[T])<#sample,openArray[T]>`_ instead.
|
||||
result = a[random(a.low..a.len)]
|
||||
|
||||
proc rand*(r: var Rand; max: Natural): int {.benign.} =
|
||||
## Returns a random number in the range 0..max. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount.
|
||||
## Returns a random integer in the range `0..max` using the given state.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,int>`_ that returns an integer using the default
|
||||
## random number generator
|
||||
## * `rand proc<#rand,Rand,range[]>`_ that returns a float
|
||||
## * `rand proc<#rand,Rand,HSlice[T,T]>`_ that accepts a slice
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
runnableExamples:
|
||||
var r = initRand(123)
|
||||
doAssert r.rand(100) == 0
|
||||
doAssert r.rand(100) == 96
|
||||
doAssert r.rand(100) == 66
|
||||
if max == 0: return
|
||||
while true:
|
||||
let x = next(r)
|
||||
@@ -124,17 +255,41 @@ proc rand*(r: var Rand; max: Natural): int {.benign.} =
|
||||
return int(x mod (uint64(max)+1u64))
|
||||
|
||||
proc rand*(max: int): int {.benign.} =
|
||||
## Returns a random number in the range 0..max. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount.
|
||||
## Returns a random integer in the range `0..max`.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the sequence of random
|
||||
## numbers returned from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,Rand,Natural>`_ that returns an integer using a
|
||||
## provided state
|
||||
## * `rand proc<#rand,float>`_ that returns a float
|
||||
## * `rand proc<#rand,HSlice[T,T]>`_ that accepts a slice
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
runnableExamples:
|
||||
randomize(123)
|
||||
doAssert rand(100) == 0
|
||||
doAssert rand(100) == 96
|
||||
doAssert rand(100) == 66
|
||||
rand(state, max)
|
||||
|
||||
proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} =
|
||||
## Returns a random number in the range 0..max. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount.
|
||||
## Returns a random floating point number in the range `0.0..max`
|
||||
## using the given state.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,float>`_ that returns a float using the default
|
||||
## random number generator
|
||||
## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
|
||||
## * `rand proc<#rand,Rand,HSlice[T,T]>`_ that accepts a slice
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
runnableExamples:
|
||||
var r = initRand(234)
|
||||
let f = r.rand(1.0)
|
||||
## f = 8.717181376738381e-07
|
||||
let x = next(r)
|
||||
when defined(JS):
|
||||
result = (float(x) / float(high(uint32))) * max
|
||||
@@ -143,51 +298,162 @@ proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} =
|
||||
result = (cast[float](u) - 1.0) * max
|
||||
|
||||
proc rand*(max: float): float {.benign.} =
|
||||
## Returns a random number in the range 0..max. The sequence of
|
||||
## random number is always the same, unless `randomize` is called
|
||||
## which initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount.
|
||||
## Returns a random floating point number in the range `0.0..max`.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the sequence of random
|
||||
## numbers returned from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,Rand,range[]>`_ that returns a float using a
|
||||
## provided state
|
||||
## * `rand proc<#rand,int>`_ that returns an integer
|
||||
## * `rand proc<#rand,HSlice[T,T]>`_ that accepts a slice
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
runnableExamples:
|
||||
randomize(234)
|
||||
let f = rand(1.0)
|
||||
## f = 8.717181376738381e-07
|
||||
rand(state, max)
|
||||
|
||||
proc rand*[T](r: var Rand; x: HSlice[T, T]): T =
|
||||
## For a slice `a .. b` returns a value in the range `a .. b`.
|
||||
## For a slice `a..b`, returns a value in the range `a..b` using the given
|
||||
## state.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,HSlice[T,T]>`_ that accepts a slice and uses the
|
||||
## default random number generator
|
||||
## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
|
||||
## * `rand proc<#rand,Rand,range[]>`_ that returns a float
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
runnableExamples:
|
||||
var r = initRand(345)
|
||||
doAssert r.rand(1..6) == 4
|
||||
doAssert r.rand(1..6) == 4
|
||||
doAssert r.rand(1..6) == 6
|
||||
result = T(rand(r, x.b - x.a)) + x.a
|
||||
|
||||
proc rand*[T](x: HSlice[T, T]): T =
|
||||
## For a slice `a .. b` returns a value in the range `a .. b`.
|
||||
## For a slice `a..b`, returns a value in the range `a..b`.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the sequence of random
|
||||
## numbers returned from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,Rand,HSlice[T,T]>`_ that accepts a slice and uses
|
||||
## a provided state
|
||||
## * `rand proc<#rand,int>`_ that returns an integer
|
||||
## * `rand proc<#rand,float>`_ that returns a floating point number
|
||||
## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer type
|
||||
runnableExamples:
|
||||
randomize(345)
|
||||
doAssert rand(1..6) == 4
|
||||
doAssert rand(1..6) == 4
|
||||
doAssert rand(1..6) == 6
|
||||
result = rand(state, x)
|
||||
|
||||
proc rand*[T](r: var Rand; a: openArray[T]): T {.deprecated.} =
|
||||
## Returns a random element from the openarray `a`.
|
||||
## **Deprecated since v0.20.0:** use ``sample`` instead.
|
||||
## **Deprecated since version 0.20.0:**
|
||||
## Use `sample[T](Rand, openArray[T])<#sample,Rand,openArray[T]>`_ instead.
|
||||
result = a[rand(r, a.low..a.high)]
|
||||
|
||||
proc rand*[T: SomeInteger](t: typedesc[T]): T =
|
||||
## Returns a random integer in the range `low(T)..high(T)`.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the sequence of random
|
||||
## numbers returned from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `rand proc<#rand,int>`_ that returns an integer
|
||||
## * `rand proc<#rand,float>`_ that returns a floating point number
|
||||
## * `rand proc<#rand,HSlice[T,T]>`_ that accepts a slice
|
||||
runnableExamples:
|
||||
randomize(567)
|
||||
doAssert rand(int8) == 55
|
||||
doAssert rand(int8) == -42
|
||||
doAssert rand(int8) == 43
|
||||
doAssert rand(uint32) == 578980729'u32
|
||||
doAssert rand(uint32) == 4052940463'u32
|
||||
doAssert rand(uint32) == 2163872389'u32
|
||||
result = cast[T](state.next)
|
||||
|
||||
proc rand*[T](a: openArray[T]): T {.deprecated.} =
|
||||
## returns a random element from the openarray `a`.
|
||||
## **Deprecated since v0.20.0:** use ``sample`` instead.
|
||||
## **Deprecated since version 0.20.0:**
|
||||
## Use `sample[T](openArray[T])<#sample,openArray[T]>`_ instead.
|
||||
result = a[rand(a.low..a.high)]
|
||||
|
||||
proc sample*[T](r: var Rand; a: openArray[T]): T =
|
||||
## returns a random element from openArray ``a`` using state in ``r``.
|
||||
## Returns a random element from ``a`` using the given state.
|
||||
##
|
||||
## See also:
|
||||
## * `sample proc<#sample,openArray[T]>`_ that uses the default
|
||||
## random number generator
|
||||
## * `sample proc<#sample,Rand,openArray[T],openArray[U]>`_ that uses a
|
||||
## cumulative distribution function
|
||||
runnableExamples:
|
||||
let marbles = ["red", "blue", "green", "yellow", "purple"]
|
||||
var r = initRand(456)
|
||||
doAssert r.sample(marbles) == "blue"
|
||||
doAssert r.sample(marbles) == "yellow"
|
||||
doAssert r.sample(marbles) == "red"
|
||||
result = a[r.rand(a.low..a.high)]
|
||||
|
||||
proc sample*[T](a: openArray[T]): T =
|
||||
## returns a random element from openArray ``a`` using non-thread-safe state.
|
||||
## Returns a random element from ``a``.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the order of outcomes
|
||||
## from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `sample proc<#sample,Rand,openArray[T]>`_ that uses a provided state
|
||||
## * `sample proc<#sample,openArray[T],openArray[U]>`_ that uses a
|
||||
## cumulative distribution function
|
||||
runnableExamples:
|
||||
let marbles = ["red", "blue", "green", "yellow", "purple"]
|
||||
randomize(456)
|
||||
doAssert sample(marbles) == "blue"
|
||||
doAssert sample(marbles) == "yellow"
|
||||
doAssert sample(marbles) == "red"
|
||||
result = a[rand(a.low..a.high)]
|
||||
|
||||
proc sample*[T, U](r: var Rand; a: openArray[T], cdf: openArray[U]): T =
|
||||
## Sample one element from openArray ``a`` when it has cumulative distribution
|
||||
## function (CDF) ``cdf`` (not necessarily normalized, any type of elements
|
||||
## convertible to ``float``). Uses state in ``r``. E.g.:
|
||||
## Returns an element from ``a`` using a cumulative distribution function
|
||||
## (CDF) and the given state.
|
||||
##
|
||||
## .. code-block:: nim
|
||||
## let val = [ "a", "b", "c", "d" ] # some values
|
||||
## var cnt = [1, 2, 3, 4] # histogram of counts
|
||||
## echo r.sample(val, cnt.cumsummed) # echo a sample
|
||||
## The ``cdf`` argument does not have to be normalized, and it could contain
|
||||
## any type of elements that can be converted to a ``float``. It must be
|
||||
## the same length as ``a``. Each element in ``cdf`` should be greater than
|
||||
## or equal to the previous element.
|
||||
##
|
||||
## The outcome of the `cumsum<math.html#cumsum,openArray[T]>`_ proc and the
|
||||
## return value of the `cumsummed<math.html#cumsummed,openArray[T]>`_ proc,
|
||||
## which are both in the math module, can be used as the ``cdf`` argument.
|
||||
##
|
||||
## See also:
|
||||
## * `sample proc<#sample,openArray[T],openArray[U]>`_ that also utilizes
|
||||
## a CDF but uses the default random number generator
|
||||
## * `sample proc<#sample,Rand,openArray[T]>`_ that does not use a CDF
|
||||
runnableExamples:
|
||||
from math import cumsummed
|
||||
|
||||
let marbles = ["red", "blue", "green", "yellow", "purple"]
|
||||
let count = [1, 6, 8, 3, 4]
|
||||
let cdf = count.cumsummed
|
||||
var r = initRand(789)
|
||||
doAssert r.sample(marbles, cdf) == "red"
|
||||
doAssert r.sample(marbles, cdf) == "green"
|
||||
doAssert r.sample(marbles, cdf) == "blue"
|
||||
assert(cdf.len == a.len) # Two basic sanity checks.
|
||||
assert(float(cdf[^1]) > 0.0)
|
||||
#While we could check cdf[i-1] <= cdf[i] for i in 1..cdf.len, that could get
|
||||
@@ -196,37 +462,128 @@ proc sample*[T, U](r: var Rand; a: openArray[T], cdf: openArray[U]): T =
|
||||
a[cdf.upperBound(U(u))]
|
||||
|
||||
proc sample*[T, U](a: openArray[T], cdf: openArray[U]): T =
|
||||
## Like ``sample(var Rand; openArray[T], openArray[U])``, but uses default
|
||||
## non-thread-safe state.
|
||||
## Returns an element from ``a`` using a cumulative distribution function
|
||||
## (CDF).
|
||||
##
|
||||
## This proc works similarly to
|
||||
## `sample[T, U](Rand, openArray[T], openArray[U])
|
||||
## <#sample,Rand,openArray[T],openArray[U]>`_.
|
||||
## See that proc's documentation for more details.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the order of outcomes
|
||||
## from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `sample proc<#sample,Rand,openArray[T],openArray[U]>`_ that also utilizes
|
||||
## a CDF but uses a provided state
|
||||
## * `sample proc<#sample,openArray[T]>`_ that does not use a CDF
|
||||
runnableExamples:
|
||||
from math import cumsummed
|
||||
|
||||
let marbles = ["red", "blue", "green", "yellow", "purple"]
|
||||
let count = [1, 6, 8, 3, 4]
|
||||
let cdf = count.cumsummed
|
||||
randomize(789)
|
||||
doAssert sample(marbles, cdf) == "red"
|
||||
doAssert sample(marbles, cdf) == "green"
|
||||
doAssert sample(marbles, cdf) == "blue"
|
||||
state.sample(a, cdf)
|
||||
|
||||
proc initRand*(seed: int64): Rand =
|
||||
## Creates a new ``Rand`` state from ``seed``.
|
||||
## Initializes a new `Rand<#Rand>`_ state using the given seed.
|
||||
##
|
||||
## `seed` must not be zero. Providing a specific seed will produce
|
||||
## the same results for that seed each time.
|
||||
##
|
||||
## The resulting state is independent of the default random number
|
||||
## generator's state.
|
||||
##
|
||||
## See also:
|
||||
## * `randomize proc<#randomize,int64>`_ that accepts a seed for the default
|
||||
## random number generator
|
||||
## * `randomize proc<#randomize>`_ that initializes the default random
|
||||
## number generator using the current time
|
||||
runnableExamples:
|
||||
from times import getTime, toUnix, nanosecond
|
||||
|
||||
var r1 = initRand(123)
|
||||
|
||||
let now = getTime()
|
||||
var r2 = initRand(now.toUnix * 1_000_000_000 + now.nanosecond)
|
||||
result.a0 = ui(seed shr 16)
|
||||
result.a1 = ui(seed and 0xffff)
|
||||
discard next(result)
|
||||
|
||||
proc randomize*(seed: int64) {.benign.} =
|
||||
## Initializes the default random number generator
|
||||
## with a specific seed.
|
||||
## Initializes the default random number generator with the given seed.
|
||||
##
|
||||
## `seed` must not be zero. Providing a specific seed will produce
|
||||
## the same results for that seed each time.
|
||||
##
|
||||
## See also:
|
||||
## * `initRand proc<#initRand,int64>`_
|
||||
## * `randomize proc<#randomize>`_ that uses the current time instead
|
||||
runnableExamples:
|
||||
from times import getTime, toUnix, nanosecond
|
||||
|
||||
randomize(123)
|
||||
|
||||
let now = getTime()
|
||||
randomize(now.toUnix * 1_000_000_000 + now.nanosecond)
|
||||
state = initRand(seed)
|
||||
|
||||
proc shuffle*[T](r: var Rand; x: var openArray[T]) =
|
||||
## Swaps the positions of elements in a sequence randomly.
|
||||
## Shuffles a sequence of elements in-place using the given state.
|
||||
##
|
||||
## See also:
|
||||
## * `shuffle proc<#shuffle,openArray[T]>`_ that uses the default
|
||||
## random number generator
|
||||
runnableExamples:
|
||||
var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
|
||||
var r = initRand(678)
|
||||
r.shuffle(cards)
|
||||
doAssert cards == ["King", "Ace", "Queen", "Ten", "Jack"]
|
||||
for i in countdown(x.high, 1):
|
||||
let j = r.rand(i)
|
||||
swap(x[i], x[j])
|
||||
|
||||
proc shuffle*[T](x: var openArray[T]) =
|
||||
## Swaps the positions of elements in a sequence randomly.
|
||||
## Shuffles a sequence of elements in-place.
|
||||
##
|
||||
## If `randomize<#randomize>`_ has not been called, the order of outcomes
|
||||
## from this proc will always be the same.
|
||||
##
|
||||
## This proc uses the default random number generator. Thus, it is **not**
|
||||
## thread-safe.
|
||||
##
|
||||
## See also:
|
||||
## * `shuffle proc<#shuffle,Rand,openArray[T]>`_ that uses a provided state
|
||||
runnableExamples:
|
||||
var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
|
||||
randomize(678)
|
||||
shuffle(cards)
|
||||
doAssert cards == ["King", "Ace", "Queen", "Ten", "Jack"]
|
||||
shuffle(state, x)
|
||||
|
||||
when not defined(nimscript):
|
||||
import times
|
||||
|
||||
proc randomize*() {.benign.} =
|
||||
## Initializes the random number generator with a "random"
|
||||
## number, i.e. a tickcount. Note: Does not work for NimScript.
|
||||
## Initializes the default random number generator with a value based on
|
||||
## the current time.
|
||||
##
|
||||
## This proc only needs to be called once, and it should be called before
|
||||
## the first usage of procs from this module that use the default random
|
||||
## number generator.
|
||||
##
|
||||
## **Note:** Does not work for NimScript.
|
||||
##
|
||||
## See also:
|
||||
## * `randomize proc<#randomize,int64>`_ that accepts a seed
|
||||
## * `initRand proc<#initRand,int64>`_
|
||||
when defined(js):
|
||||
let time = int64(times.epochTime() * 1_000_000_000)
|
||||
randomize(time)
|
||||
|
||||
Reference in New Issue
Block a user