random.nim 27 KB

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