random.nim 27 KB

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