1#
2#
3#            Nim's Runtime Library
4#        (c) Copyright 2017 Andreas Rumpf
5#
6#    See the file "copying.txt", included in this
7#    distribution, for details about the copyright.
8#
9
10## Nim's standard random number generator (RNG).
11##
12## Its implementation is based on the `xoroshiro128+`
13## (xor/rotate/shift/rotate) library.
14## * More information: http://xoroshiro.di.unimi.it
15## * C implementation: http://xoroshiro.di.unimi.it/xoroshiro128plus.c
16##
17## **Do not use this module for cryptographic purposes!**
18##
19## Basic usage
20## ===========
21##
22runnableExamples:
23  # Call randomize() once to initialize the default random number generator.
24  # If this is not called, the same results will occur every time these
25  # examples are run.
26  randomize()
27
28  # Pick a number in 0..100.
29  let num = rand(100)
30  doAssert num in 0..100
31
32  # Roll a six-sided die.
33  let roll = rand(1..6)
34  doAssert roll in 1..6
35
36  # Pick a marble from a bag.
37  let marbles = ["red", "blue", "green", "yellow", "purple"]
38  let pick = sample(marbles)
39  doAssert pick in marbles
40
41  # Shuffle some cards.
42  var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
43  shuffle(cards)
44  doAssert cards.len == 5
45
46## These examples all use the default RNG. The
47## `Rand type <#Rand>`_ represents the state of an RNG.
48## For convenience, this module contains a default Rand state that corresponds
49## to the default RNG. Most procs in this module which do
50## not take in a Rand parameter, including those called in the above examples,
51## use the default generator. Those procs are **not** thread-safe.
52##
53## Note that the default generator always starts in the same state.
54## The `randomize proc <#randomize>`_ can be called to initialize the default
55## generator with a seed based on the current time, and it only needs to be
56## called once before the first usage of procs from this module. If
57## `randomize` is not called, the default generator will always produce
58## the same results.
59##
60## RNGs that are independent of the default one can be created with the
61## `initRand proc <#initRand,int64>`_.
62##
63## Again, it is important to remember that this module must **not** be used for
64## cryptographic applications.
65##
66## See also
67## ========
68## * `std/sysrand module <sysrand.html>`_ for a cryptographically secure pseudorandom number generator
69## * `mersenne module <mersenne.html>`_ for the Mersenne Twister random number generator
70## * `math module <math.html>`_ for basic math routines
71## * `stats module <stats.html>`_ for statistical analysis
72## * `list of cryptographic and hashing modules <lib.html#pure-libraries-hashing>`_
73##   in the standard library
74
75import algorithm, math
76import std/private/since
77
78include system/inclrtl
79{.push debugger: off.}
80
81when defined(js):
82  type Ui = uint32
83
84  const randMax = 4_294_967_295u32
85else:
86  type Ui = uint64
87
88  const randMax = 18_446_744_073_709_551_615u64
89
90type
91  Rand* = object ## State of a random number generator.
92                 ##
93                 ## Create a new Rand state using the `initRand proc <#initRand,int64>`_.
94                 ##
95                 ## The module contains a default Rand state for convenience.
96                 ## It corresponds to the default RNG's state.
97                 ## The default Rand state always starts with the same values, but the
98                 ## `randomize proc <#randomize>`_ can be used to seed the default generator
99                 ## with a value based on the current time.
100                 ##
101                 ## Many procs have two variations: one that takes in a Rand parameter and
102                 ## another that uses the default generator. The procs that use the default
103                 ## generator are **not** thread-safe!
104    a0, a1: Ui
105
106when defined(js):
107  var state = Rand(
108    a0: 0x69B4C98Cu32,
109    a1: 0xFED1DD30u32) # global for backwards compatibility
110else:
111  const DefaultRandSeed = Rand(
112    a0: 0x69B4C98CB8530805u64,
113    a1: 0xFED1DD3004688D67CAu64)
114
115  # racy for multi-threading but good enough for now:
116  var state = DefaultRandSeed # global for backwards compatibility
117
118func isValid(r: Rand): bool {.inline.} =
119  ## Check whether state of `r` is valid.
120  ##
121  ## In `xoroshiro128+`, if all bits of `a0` and `a1` are zero,
122  ## they are always zero after calling `next(r: var Rand)`.
123  not (r.a0 == 0 and r.a1 == 0)
124
125since (1, 5):
126  template randState*(): untyped =
127    ## Makes the default Rand state accessible from other modules.
128    ## Useful for module authors.
129    state
130
131proc rotl(x, k: Ui): Ui =
132  result = (x shl k) or (x shr (Ui(64) - k))
133
134proc next*(r: var Rand): uint64 =
135  ## Computes a random `uint64` number using the given state.
136  ##
137  ## **See also:**
138  ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer between zero and
139  ##   a given upper bound
140  ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
141  ## * `rand proc<#rand,Rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
142  ##   that accepts a slice
143  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
144  ## * `skipRandomNumbers proc<#skipRandomNumbers,Rand>`_
145  runnableExamples("-r:off"):
146    var r = initRand(2019)
147    assert r.next() == 13223559681708962501'u64 # implementation defined
148    assert r.next() == 7229677234260823147'u64 # ditto
149
150  let s0 = r.a0
151  var s1 = r.a1
152  result = s0 + s1
153  s1 = s1 xor s0
154  r.a0 = rotl(s0, 55) xor s1 xor (s1 shl 14) # a, b
155  r.a1 = rotl(s1, 36) # c
156
157proc skipRandomNumbers*(s: var Rand) =
158  ## The jump function for the generator.
159  ##
160  ## This proc is equivalent to `2^64` calls to `next <#next,Rand>`_, and it can
161  ## be used to generate `2^64` non-overlapping subsequences for parallel
162  ## computations.
163  ##
164  ## When multiple threads are generating random numbers, each thread must
165  ## own the `Rand <#Rand>`_ state it is using so that the thread can safely
166  ## obtain random numbers. However, if each thread creates its own Rand state,
167  ## the subsequences of random numbers that each thread generates may overlap,
168  ## even if the provided seeds are unique. This is more likely to happen as the
169  ## number of threads and amount of random numbers generated increases.
170  ##
171  ## If many threads will generate random numbers concurrently, it is better to
172  ## create a single Rand state and pass it to each thread. After passing the
173  ## Rand state to a thread, call this proc before passing it to the next one.
174  ## By using the Rand state this way, the subsequences of random numbers
175  ## generated in each thread will never overlap as long as no thread generates
176  ## more than `2^64` random numbers.
177  ##
178  ## **See also:**
179  ## * `next proc<#next,Rand>`_
180  runnableExamples("--threads:on"):
181    import std/[random, threadpool]
182
183    const spawns = 4
184    const numbers = 100000
185
186    proc randomSum(r: Rand): int =
187      var r = r
188      for i in 1..numbers:
189        result += r.rand(0..10)
190
191    var r = initRand(2019)
192    var vals: array[spawns, FlowVar[int]]
193    for val in vals.mitems:
194      val = spawn randomSum(r)
195      r.skipRandomNumbers()
196
197    for val in vals:
198      doAssert abs(^val - numbers * 5) / numbers < 0.1
199
200  when defined(js):
201    const helper = [0xbeac0467u32, 0xd86b048bu32]
202  else:
203    const helper = [0xbeac0467eba5facbu64, 0xd86b048b86aa9922u64]
204  var
205    s0 = Ui 0
206    s1 = Ui 0
207  for i in 0..high(helper):
208    for b in 0 ..< 64:
209      if (helper[i] and (Ui(1) shl Ui(b))) != 0:
210        s0 = s0 xor s.a0
211        s1 = s1 xor s.a1
212      discard next(s)
213  s.a0 = s0
214  s.a1 = s1
215
216proc rand[T: uint | uint64](r: var Rand; max: T): T =
217  # xxx export in future work
218  if max == 0: return
219  else:
220    let max = uint64(max)
221    when T.high.uint64 == uint64.high:
222      if max == uint64.high: return T(next(r))
223    while true:
224      let x = next(r)
225      # avoid `mod` bias
226      if x <= randMax - (randMax mod max):
227        return T(x mod (max + 1))
228
229proc rand*(r: var Rand; max: Natural): int {.benign.} =
230  ## Returns a random integer in the range `0..max` using the given state.
231  ##
232  ## **See also:**
233  ## * `rand proc<#rand,int>`_ that returns an integer using the default RNG
234  ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
235  ## * `rand proc<#rand,Rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
236  ##   that accepts a slice
237  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
238  runnableExamples:
239    var r = initRand(123)
240    if false:
241      assert r.rand(100) == 96 # implementation defined
242  # bootstrap: can't use `runnableExamples("-r:off")`
243  cast[int](rand(r, uint64(max)))
244    # xxx toUnsigned pending https://github.com/nim-lang/Nim/pull/18445
245
246proc rand*(max: int): int {.benign.} =
247  ## Returns a random integer in the range `0..max`.
248  ##
249  ## If `randomize <#randomize>`_ has not been called, the sequence of random
250  ## numbers returned from this proc will always be the same.
251  ##
252  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
253  ##
254  ## **See also:**
255  ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer using a
256  ##   provided state
257  ## * `rand proc<#rand,float>`_ that returns a float
258  ## * `rand proc<#rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
259  ##   that accepts a slice
260  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
261  runnableExamples("-r:off"):
262    randomize(123)
263    assert [rand(100), rand(100)] == [96, 63] # implementation defined
264
265  rand(state, max)
266
267proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} =
268  ## Returns a random floating point number in the range `0.0..max`
269  ## using the given state.
270  ##
271  ## **See also:**
272  ## * `rand proc<#rand,float>`_ that returns a float using the default RNG
273  ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
274  ## * `rand proc<#rand,Rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
275  ##   that accepts a slice
276  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
277  runnableExamples:
278    var r = initRand(234)
279    let f = r.rand(1.0) # 8.717181376738381e-07
280
281  let x = next(r)
282  when defined(js):
283    result = (float(x) / float(high(uint32))) * max
284  else:
285    let u = (0x3FFu64 shl 52u64) or (x shr 12u64)
286    result = (cast[float](u) - 1.0) * max
287
288proc rand*(max: float): float {.benign.} =
289  ## Returns a random floating point number in the range `0.0..max`.
290  ##
291  ## If `randomize <#randomize>`_ has not been called, the sequence of random
292  ## numbers returned from this proc will always be the same.
293  ##
294  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
295  ##
296  ## **See also:**
297  ## * `rand proc<#rand,Rand,range[]>`_ that returns a float using a
298  ##   provided state
299  ## * `rand proc<#rand,int>`_ that returns an integer
300  ## * `rand proc<#rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
301  ##   that accepts a slice
302  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
303  runnableExamples:
304    randomize(234)
305    let f = rand(1.0) # 8.717181376738381e-07
306
307  rand(state, max)
308
309proc rand*[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T =
310  ## For a slice `a..b`, returns a value in the range `a..b` using the given
311  ## state.
312  ##
313  ## Allowed types for `T` are integers, floats, and enums without holes.
314  ##
315  ## **See also:**
316  ## * `rand proc<#rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
317  ##   that accepts a slice and uses the default RNG
318  ## * `rand proc<#rand,Rand,Natural>`_ that returns an integer
319  ## * `rand proc<#rand,Rand,range[]>`_ that returns a float
320  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
321  runnableExamples:
322    var r = initRand(345)
323    assert r.rand(1..5) <= 5
324    assert r.rand(-1.1 .. 1.2) >= -1.1
325  assert x.a <= x.b
326  when T is SomeFloat:
327    result = rand(r, x.b - x.a) + x.a
328  else: # Integers and Enum types
329    when defined(js):
330      result = cast[T](rand(r, cast[uint](x.b) - cast[uint](x.a)) + cast[uint](x.a))
331    else:
332      result = cast[T](rand(r, cast[uint64](x.b) - cast[uint64](x.a)) + cast[uint64](x.a))
333
334proc rand*[T: Ordinal or SomeFloat](x: HSlice[T, T]): T =
335  ## For a slice `a..b`, returns a value in the range `a..b`.
336  ##
337  ## Allowed types for `T` are integers, floats, and enums without holes.
338  ##
339  ## If `randomize <#randomize>`_ has not been called, the sequence of random
340  ## numbers returned from this proc will always be the same.
341  ##
342  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
343  ##
344  ## **See also:**
345  ## * `rand proc<#rand,Rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
346  ##   that accepts a slice and uses a provided state
347  ## * `rand proc<#rand,int>`_ that returns an integer
348  ## * `rand proc<#rand,float>`_ that returns a floating point number
349  ## * `rand proc<#rand,typedesc[T]>`_ that accepts an integer or range type
350  runnableExamples:
351    randomize(345)
352    assert rand(1..6) <= 6
353
354  result = rand(state, x)
355
356proc rand*[T: SomeInteger](t: typedesc[T]): T =
357  ## Returns a random integer in the range `low(T)..high(T)`.
358  ##
359  ## If `randomize <#randomize>`_ has not been called, the sequence of random
360  ## numbers returned from this proc will always be the same.
361  ##
362  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
363  ##
364  ## **See also:**
365  ## * `rand proc<#rand,int>`_ that returns an integer
366  ## * `rand proc<#rand,float>`_ that returns a floating point number
367  ## * `rand proc<#rand,HSlice[T: Ordinal or float or float32 or float64,T: Ordinal or float or float32 or float64]>`_
368  ##   that accepts a slice
369  runnableExamples:
370    randomize(567)
371    if false: # implementation defined
372      assert rand(int8) == -42
373      assert rand(uint32) == 578980729'u32
374      assert rand(range[1..16]) == 11
375  # pending csources >= 1.4.0 or fixing https://github.com/timotheecour/Nim/issues/251#issuecomment-831599772,
376  # use `runnableExamples("-r:off")` instead of `if false`
377  when T is range:
378    result = rand(state, low(T)..high(T))
379  else:
380    result = cast[T](state.next)
381
382proc sample*[T](r: var Rand; s: set[T]): T =
383  ## Returns a random element from the set `s` using the given state.
384  ##
385  ## **See also:**
386  ## * `sample proc<#sample,set[T]>`_ that uses the default RNG
387  ## * `sample proc<#sample,Rand,openArray[T]>`_ for `openArray`s
388  ## * `sample proc<#sample,Rand,openArray[T],openArray[U]>`_ that uses a
389  ##   cumulative distribution function
390  runnableExamples:
391    var r = initRand(987)
392    let s = {1, 3, 5, 7, 9}
393    assert r.sample(s) in s
394
395  assert card(s) != 0
396  var i = rand(r, card(s) - 1)
397  for e in s:
398    if i == 0: return e
399    dec(i)
400
401proc sample*[T](s: set[T]): T =
402  ## Returns a random element from the set `s`.
403  ##
404  ## If `randomize <#randomize>`_ has not been called, the order of outcomes
405  ## from this proc will always be the same.
406  ##
407  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
408  ##
409  ## **See also:**
410  ## * `sample proc<#sample,Rand,set[T]>`_ that uses a provided state
411  ## * `sample proc<#sample,openArray[T]>`_ for `openArray`s
412  ## * `sample proc<#sample,openArray[T],openArray[U]>`_ that uses a
413  ##   cumulative distribution function
414  runnableExamples:
415    randomize(987)
416    let s = {1, 3, 5, 7, 9}
417    assert sample(s) in s
418
419  sample(state, s)
420
421proc sample*[T](r: var Rand; a: openArray[T]): T =
422  ## Returns a random element from `a` using the given state.
423  ##
424  ## **See also:**
425  ## * `sample proc<#sample,openArray[T]>`_ that uses the default RNG
426  ## * `sample proc<#sample,Rand,openArray[T],openArray[U]>`_ that uses a
427  ##   cumulative distribution function
428  ## * `sample proc<#sample,Rand,set[T]>`_ for sets
429  runnableExamples:
430    let marbles = ["red", "blue", "green", "yellow", "purple"]
431    var r = initRand(456)
432    assert r.sample(marbles) in marbles
433
434  result = a[r.rand(a.low..a.high)]
435
436proc sample*[T](a: openArray[T]): lent T =
437  ## Returns a random element from `a`.
438  ##
439  ## If `randomize <#randomize>`_ has not been called, the order of outcomes
440  ## from this proc will always be the same.
441  ##
442  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
443  ##
444  ## **See also:**
445  ## * `sample proc<#sample,Rand,openArray[T]>`_ that uses a provided state
446  ## * `sample proc<#sample,openArray[T],openArray[U]>`_ that uses a
447  ##   cumulative distribution function
448  ## * `sample proc<#sample,set[T]>`_ for sets
449  runnableExamples:
450    let marbles = ["red", "blue", "green", "yellow", "purple"]
451    randomize(456)
452    assert sample(marbles) in marbles
453
454  result = a[rand(a.low..a.high)]
455
456proc sample*[T, U](r: var Rand; a: openArray[T]; cdf: openArray[U]): T =
457  ## Returns an element from `a` using a cumulative distribution function
458  ## (CDF) and the given state.
459  ##
460  ## The `cdf` argument does not have to be normalized, and it could contain
461  ## any type of elements that can be converted to a `float`. It must be
462  ## the same length as `a`. Each element in `cdf` should be greater than
463  ## or equal to the previous element.
464  ##
465  ## The outcome of the `cumsum<math.html#cumsum,openArray[T]>`_ proc and the
466  ## return value of the `cumsummed<math.html#cumsummed,openArray[T]>`_ proc,
467  ## which are both in the math module, can be used as the `cdf` argument.
468  ##
469  ## **See also:**
470  ## * `sample proc<#sample,openArray[T],openArray[U]>`_ that also utilizes
471  ##   a CDF but uses the default RNG
472  ## * `sample proc<#sample,Rand,openArray[T]>`_ that does not use a CDF
473  ## * `sample proc<#sample,Rand,set[T]>`_ for sets
474  runnableExamples:
475    from std/math import cumsummed
476
477    let marbles = ["red", "blue", "green", "yellow", "purple"]
478    let count = [1, 6, 8, 3, 4]
479    let cdf = count.cumsummed
480    var r = initRand(789)
481    assert r.sample(marbles, cdf) in marbles
482
483  assert(cdf.len == a.len) # Two basic sanity checks.
484  assert(float(cdf[^1]) > 0.0)
485  # While we could check cdf[i-1] <= cdf[i] for i in 1..cdf.len, that could get
486  # awfully expensive even in debugging modes.
487  let u = r.rand(float(cdf[^1]))
488  a[cdf.upperBound(U(u))]
489
490proc sample*[T, U](a: openArray[T]; cdf: openArray[U]): T =
491  ## Returns an element from `a` using a cumulative distribution function
492  ## (CDF).
493  ##
494  ## This proc works similarly to
495  ## `sample <#sample,Rand,openArray[T],openArray[U]>`_.
496  ## See that proc's documentation for more details.
497  ##
498  ## If `randomize <#randomize>`_ has not been called, the order of outcomes
499  ## from this proc will always be the same.
500  ##
501  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
502  ##
503  ## **See also:**
504  ## * `sample proc<#sample,Rand,openArray[T],openArray[U]>`_ that also utilizes
505  ##   a CDF but uses a provided state
506  ## * `sample proc<#sample,openArray[T]>`_ that does not use a CDF
507  ## * `sample proc<#sample,set[T]>`_ for sets
508  runnableExamples:
509    from std/math import cumsummed
510
511    let marbles = ["red", "blue", "green", "yellow", "purple"]
512    let count = [1, 6, 8, 3, 4]
513    let cdf = count.cumsummed
514    randomize(789)
515    assert sample(marbles, cdf) in marbles
516
517  state.sample(a, cdf)
518
519proc gauss*(r: var Rand; mu = 0.0; sigma = 1.0): float {.since: (1, 3).} =
520  ## Returns a Gaussian random variate,
521  ## with mean `mu` and standard deviation `sigma`
522  ## using the given state.
523  # Ratio of uniforms method for normal
524  # https://www2.econ.osaka-u.ac.jp/~tanizaki/class/2013/econome3/13.pdf
525  const K = sqrt(2 / E)
526  var
527    a = 0.0
528    b = 0.0
529  while true:
530    a = rand(r, 1.0)
531    b = (2.0 * rand(r, 1.0) - 1.0) * K
532    if  b * b <= -4.0 * a * a * ln(a): break
533  result = mu + sigma * (b / a)
534
535proc gauss*(mu = 0.0, sigma = 1.0): float {.since: (1, 3).} =
536  ## Returns a Gaussian random variate,
537  ## with mean `mu` and standard deviation `sigma`.
538  ##
539  ## If `randomize <#randomize>`_ has not been called, the order of outcomes
540  ## from this proc will always be the same.
541  ##
542  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
543  result = gauss(state, mu, sigma)
544
545proc initRand*(seed: int64): Rand =
546  ## Initializes a new `Rand <#Rand>`_ state using the given seed.
547  ##
548  ## Providing a specific seed will produce the same results for that seed each time.
549  ##
550  ## The resulting state is independent of the default RNG's state. When `seed == 0`,
551  ## we internally set the seed to an implementation defined non-zero value.
552  ##
553  ## **See also:**
554  ## * `initRand proc<#initRand>`_ that uses the current time
555  ## * `randomize proc<#randomize,int64>`_ that accepts a seed for the default RNG
556  ## * `randomize proc<#randomize>`_ that initializes the default RNG using the current time
557  runnableExamples:
558    from std/times import getTime, toUnix, nanosecond
559
560    var r1 = initRand(123)
561    let now = getTime()
562    var r2 = initRand(now.toUnix * 1_000_000_000 + now.nanosecond)
563  const seedFallback0 = int32.high # arbitrary
564  let seed = if seed != 0: seed else: seedFallback0 # because 0 is a fixed point
565  result.a0 = Ui(seed shr 16)
566  result.a1 = Ui(seed and 0xffff)
567  when not defined(nimLegacyRandomInitRand):
568    # calling `discard next(result)` (even a few times) would still produce
569    # skewed numbers for the 1st call to `rand()`.
570    skipRandomNumbers(result)
571  discard next(result)
572
573proc randomize*(seed: int64) {.benign.} =
574  ## Initializes the default random number generator with the given seed.
575  ##
576  ## Providing a specific seed will produce the same results for that seed each time.
577  ##
578  ## **See also:**
579  ## * `initRand proc<#initRand,int64>`_ that initializes a Rand state
580  ##   with a given seed
581  ## * `randomize proc<#randomize>`_ that uses the current time instead
582  ## * `initRand proc<#initRand>`_ that initializes a Rand state using
583  ##   the current time
584  runnableExamples:
585    from std/times import getTime, toUnix, nanosecond
586
587    randomize(123)
588
589    let now = getTime()
590    randomize(now.toUnix * 1_000_000_000 + now.nanosecond)
591
592  state = initRand(seed)
593
594proc shuffle*[T](r: var Rand; x: var openArray[T]) =
595  ## Shuffles a sequence of elements in-place using the given state.
596  ##
597  ## **See also:**
598  ## * `shuffle proc<#shuffle,openArray[T]>`_ that uses the default RNG
599  runnableExamples:
600    var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
601    var r = initRand(678)
602    r.shuffle(cards)
603    import std/algorithm
604    assert cards.sorted == @["Ace", "Jack", "King", "Queen", "Ten"]
605
606  for i in countdown(x.high, 1):
607    let j = r.rand(i)
608    swap(x[i], x[j])
609
610proc shuffle*[T](x: var openArray[T]) =
611  ## Shuffles a sequence of elements in-place.
612  ##
613  ## If `randomize <#randomize>`_ has not been called, the order of outcomes
614  ## from this proc will always be the same.
615  ##
616  ## This proc uses the default RNG. Thus, it is **not** thread-safe.
617  ##
618  ## **See also:**
619  ## * `shuffle proc<#shuffle,Rand,openArray[T]>`_ that uses a provided state
620  runnableExamples:
621    var cards = ["Ace", "King", "Queen", "Jack", "Ten"]
622    randomize(678)
623    shuffle(cards)
624    import std/algorithm
625    assert cards.sorted == @["Ace", "Jack", "King", "Queen", "Ten"]
626
627  shuffle(state, x)
628
629when not defined(standalone):
630  when defined(js):
631    import std/times
632  else:
633    when defined(nimscript):
634      import std/hashes
635    else:
636      import std/[hashes, os, sysrand, monotimes]
637
638      when compileOption("threads"):
639        import locks
640        var baseSeedLock: Lock
641        baseSeedLock.initLock
642
643    var baseState: Rand
644
645  proc initRand(): Rand =
646    ## Initializes a new Rand state.
647    ##
648    ## The resulting state is independent of the default RNG's state.
649    ##
650    ## **Note:** Does not work for the compile-time VM.
651    ##
652    ## See also:
653    ## * `initRand proc<#initRand,int64>`_ that accepts a seed for a new Rand state
654    ## * `randomize proc<#randomize>`_ that initializes the default RNG using the current time
655    ## * `randomize proc<#randomize,int64>`_ that accepts a seed for the default RNG
656    when defined(js):
657      let time = int64(times.epochTime() * 1000) and 0x7fff_ffff
658      result = initRand(time)
659    else:
660      proc getRandomState(): Rand =
661        when defined(nimscript):
662          result = Rand(
663            a0: CompileTime.hash.Ui,
664            a1: CompileDate.hash.Ui)
665          if not result.isValid:
666            result = DefaultRandSeed
667        else:
668          var urand: array[sizeof(Rand), byte]
669
670          for i in 0 .. 7:
671            if sysrand.urandom(urand):
672              copyMem(result.addr, urand[0].addr, sizeof(Rand))
673              if result.isValid:
674                break
675
676          if not result.isValid:
677            # Don't try to get alternative random values from other source like time or process/thread id,
678            # because such code would be never tested and is a liability for security.
679            quit("Failed to initializes baseState in random module as sysrand.urandom doesn't work.")
680
681      when compileOption("threads"):
682        baseSeedLock.withLock:
683          if not baseState.isValid:
684            baseState = getRandomState()
685          result = baseState
686          baseState.skipRandomNumbers
687      else:
688        if not baseState.isValid:
689          baseState = getRandomState()
690        result = baseState
691        baseState.skipRandomNumbers
692
693  since (1, 5, 1):
694    export initRand
695
696  proc randomize*() {.benign.} =
697    ## Initializes the default random number generator with a seed based on
698    ## random number source.
699    ##
700    ## This proc only needs to be called once, and it should be called before
701    ## the first usage of procs from this module that use the default RNG.
702    ##
703    ## **Note:** Does not work for the compile-time VM.
704    ##
705    ## **See also:**
706    ## * `randomize proc<#randomize,int64>`_ that accepts a seed
707    ## * `initRand proc<#initRand>`_ that initializes a Rand state using
708    ##   the current time
709    ## * `initRand proc<#initRand,int64>`_ that initializes a Rand state
710    ##   with a given seed
711    state = initRand()
712
713{.pop.}
714