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