rand.odin 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /*
  2. Package core:math/rand implements various random number generators
  3. */
  4. package rand
  5. import "core:intrinsics"
  6. import "core:mem"
  7. Rand :: struct {
  8. state: u64,
  9. inc: u64,
  10. is_system: bool,
  11. }
  12. @(private)
  13. global_rand := create(u64(intrinsics.read_cycle_counter()))
  14. /*
  15. Sets the seed used by the global random number generator.
  16. Inputs:
  17. - seed: The seed value
  18. Example:
  19. import "core:math/rand"
  20. import "core:fmt"
  21. set_global_seed_example :: proc() {
  22. rand.set_global_seed(1)
  23. fmt.println(rand.uint64())
  24. }
  25. Possible Output:
  26. 10
  27. */
  28. set_global_seed :: proc(seed: u64) {
  29. init(&global_rand, seed)
  30. }
  31. /*
  32. Creates a new random number generator.
  33. Inputs:
  34. - seed: The seed value to create the random number generator with
  35. Returns:
  36. - res: The created random number generator
  37. Example:
  38. import "core:math/rand"
  39. import "core:fmt"
  40. create_example :: proc() {
  41. my_rand := rand.create(1)
  42. fmt.println(rand.uint64(&my_rand))
  43. }
  44. Possible Output:
  45. 10
  46. */
  47. @(require_results)
  48. create :: proc(seed: u64) -> (res: Rand) {
  49. r: Rand
  50. init(&r, seed)
  51. return r
  52. }
  53. /*
  54. Initialises a random number generator.
  55. Inputs:
  56. - r: The random number generator to initialise
  57. - seed: The seed value to initialise this random number generator
  58. Example:
  59. import "core:math/rand"
  60. import "core:fmt"
  61. init_example :: proc() {
  62. my_rand: rand.Rand
  63. rand.init(&my_rand, 1)
  64. fmt.println(rand.uint64(&my_rand))
  65. }
  66. Possible Output:
  67. 10
  68. */
  69. init :: proc(r: ^Rand, seed: u64) {
  70. r.state = 0
  71. r.inc = (seed << 1) | 1
  72. _random(r)
  73. r.state += seed
  74. _random(r)
  75. }
  76. /*
  77. Initialises a random number generator to use the system random number generator.
  78. The system random number generator is platform specific.
  79. On `linux` refer to the `getrandom` syscall.
  80. On `darwin` refer to `getentropy`.
  81. On `windows` refer to `BCryptGenRandom`.
  82. All other platforms wi
  83. Inputs:
  84. - r: The random number generator to use the system random number generator
  85. WARNING: Panics if the system is not either `windows`, `darwin` or `linux`
  86. Example:
  87. import "core:math/rand"
  88. import "core:fmt"
  89. init_as_system_example :: proc() {
  90. my_rand: rand.Rand
  91. rand.init_as_system(&my_rand)
  92. fmt.println(rand.uint64(&my_rand))
  93. }
  94. Possible Output:
  95. 10
  96. */
  97. init_as_system :: proc(r: ^Rand) {
  98. if !#defined(_system_random) {
  99. panic(#procedure + " is not supported on this platform yet")
  100. }
  101. r.state = 0
  102. r.inc = 0
  103. r.is_system = true
  104. }
  105. @(private)
  106. _random :: proc(r: ^Rand) -> u32 {
  107. r := r
  108. if r == nil {
  109. // NOTE(bill, 2020-09-07): Do this so that people can
  110. // enforce the global random state if necessary with `nil`
  111. r = &global_rand
  112. }
  113. when #defined(_system_random) {
  114. if r.is_system {
  115. return _system_random()
  116. }
  117. }
  118. old_state := r.state
  119. r.state = old_state * 6364136223846793005 + (r.inc|1)
  120. xor_shifted := u32(((old_state>>18) ~ old_state) >> 27)
  121. rot := u32(old_state >> 59)
  122. return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31))
  123. }
  124. /*
  125. Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
  126. Inputs:
  127. - r: The random number generator to use, or nil for the global generator
  128. Returns:
  129. - val: A random unsigned 32 bit value
  130. Example:
  131. import "core:math/rand"
  132. import "core:fmt"
  133. uint32_example :: proc() {
  134. // Using the global random number generator
  135. fmt.println(rand.uint32())
  136. // Using local random number generator
  137. my_rand := rand.create(1)
  138. fmt.println(rand.uint32(&my_rand))
  139. }
  140. Possible Output:
  141. 10
  142. 389
  143. */
  144. @(require_results)
  145. uint32 :: proc(r: ^Rand = nil) -> (val: u32) { return _random(r) }
  146. /*
  147. Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
  148. Inputs:
  149. - r: The random number generator to use, or nil for the global generator
  150. Returns:
  151. - val: A random unsigned 64 bit value
  152. Example:
  153. import "core:math/rand"
  154. import "core:fmt"
  155. uint64_example :: proc() {
  156. // Using the global random number generator
  157. fmt.println(rand.uint64())
  158. // Using local random number generator
  159. my_rand := rand.create(1)
  160. fmt.println(rand.uint64(&my_rand))
  161. }
  162. Possible Output:
  163. 10
  164. 389
  165. */
  166. @(require_results)
  167. uint64 :: proc(r: ^Rand = nil) -> (val: u64) {
  168. a := u64(_random(r))
  169. b := u64(_random(r))
  170. return (a<<32) | b
  171. }
  172. /*
  173. Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
  174. Inputs:
  175. - r: The random number generator to use, or nil for the global generator
  176. Returns:
  177. - val: A random unsigned 128 bit value
  178. Example:
  179. import "core:math/rand"
  180. import "core:fmt"
  181. uint128_example :: proc() {
  182. // Using the global random number generator
  183. fmt.println(rand.uint128())
  184. // Using local random number generator
  185. my_rand := rand.create(1)
  186. fmt.println(rand.uint128(&my_rand))
  187. }
  188. Possible Output:
  189. 10
  190. 389
  191. */
  192. @(require_results)
  193. uint128 :: proc(r: ^Rand = nil) -> (val: u128) {
  194. a := u128(_random(r))
  195. b := u128(_random(r))
  196. c := u128(_random(r))
  197. d := u128(_random(r))
  198. return (a<<96) | (b<<64) | (c<<32) | d
  199. }
  200. /*
  201. Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
  202. The sign bit will always be set to 0, thus all generated numbers will be positive.
  203. Inputs:
  204. - r: The random number generator to use, or nil for the global generator
  205. Returns:
  206. - val: A random 31 bit value
  207. Example:
  208. import "core:math/rand"
  209. import "core:fmt"
  210. int31_example :: proc() {
  211. // Using the global random number generator
  212. fmt.println(rand.int31())
  213. // Using local random number generator
  214. my_rand := rand.create(1)
  215. fmt.println(rand.int31(&my_rand))
  216. }
  217. Possible Output:
  218. 10
  219. 389
  220. */
  221. @(require_results) int31 :: proc(r: ^Rand = nil) -> (val: i32) { return i32(uint32(r) << 1 >> 1) }
  222. /*
  223. Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
  224. The sign bit will always be set to 0, thus all generated numbers will be positive.
  225. Inputs:
  226. - r: The random number generator to use, or nil for the global generator
  227. Returns:
  228. - val: A random 63 bit value
  229. Example:
  230. import "core:math/rand"
  231. import "core:fmt"
  232. int63_example :: proc() {
  233. // Using the global random number generator
  234. fmt.println(rand.int63())
  235. // Using local random number generator
  236. my_rand := rand.create(1)
  237. fmt.println(rand.int63(&my_rand))
  238. }
  239. Possible Output:
  240. 10
  241. 389
  242. */
  243. @(require_results) int63 :: proc(r: ^Rand = nil) -> (val: i64) { return i64(uint64(r) << 1 >> 1) }
  244. /*
  245. Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used.
  246. The sign bit will always be set to 0, thus all generated numbers will be positive.
  247. Inputs:
  248. - r: The random number generator to use, or nil for the global generator
  249. Returns:
  250. - val: A random 127 bit value
  251. Example:
  252. import "core:math/rand"
  253. import "core:fmt"
  254. int127_example :: proc() {
  255. // Using the global random number generator
  256. fmt.println(rand.int127())
  257. // Using local random number generator
  258. my_rand := rand.create(1)
  259. fmt.println(rand.int127(&my_rand))
  260. }
  261. Possible Output:
  262. 10
  263. 389
  264. */
  265. @(require_results) int127 :: proc(r: ^Rand = nil) -> (val: i128) { return i128(uint128(r) << 1 >> 1) }
  266. /*
  267. Generates a random 31 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  268. Inputs:
  269. - n: The upper bound of the generated number, this value is exclusive
  270. - r: The random number generator to use, or nil for the global generator
  271. Returns:
  272. - val: A random 31 bit value in the range `(0, n]`
  273. WARNING: Panics if n is less than 0
  274. Example:
  275. import "core:math/rand"
  276. import "core:fmt"
  277. int31_max_example :: proc() {
  278. // Using the global random number generator
  279. fmt.println(rand.int31_max(16))
  280. // Using local random number generator
  281. my_rand := rand.create(1)
  282. fmt.println(rand.int31_max(1024, &my_rand))
  283. }
  284. Possible Output:
  285. 6
  286. 500
  287. */
  288. @(require_results)
  289. int31_max :: proc(n: i32, r: ^Rand = nil) -> (val: i32) {
  290. if n <= 0 {
  291. panic("Invalid argument to int31_max")
  292. }
  293. if n&(n-1) == 0 {
  294. return int31(r) & (n-1)
  295. }
  296. max := i32((1<<31) - 1 - (1<<31)%u32(n))
  297. v := int31(r)
  298. for v > max {
  299. v = int31(r)
  300. }
  301. return v % n
  302. }
  303. /*
  304. Generates a random 63 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  305. Inputs:
  306. - n: The upper bound of the generated number, this value is exclusive
  307. - r: The random number generator to use, or nil for the global generator
  308. Returns:
  309. - val: A random 63 bit value in the range `(0, n]`
  310. WARNING: Panics if n is less than 0
  311. Example:
  312. import "core:math/rand"
  313. import "core:fmt"
  314. int63_max_example :: proc() {
  315. // Using the global random number generator
  316. fmt.println(rand.int63_max(16))
  317. // Using local random number generator
  318. my_rand := rand.create(1)
  319. fmt.println(rand.int63_max(1024, &my_rand))
  320. }
  321. Possible Output:
  322. 6
  323. 500
  324. */
  325. @(require_results)
  326. int63_max :: proc(n: i64, r: ^Rand = nil) -> (val: i64) {
  327. if n <= 0 {
  328. panic("Invalid argument to int63_max")
  329. }
  330. if n&(n-1) == 0 {
  331. return int63(r) & (n-1)
  332. }
  333. max := i64((1<<63) - 1 - (1<<63)%u64(n))
  334. v := int63(r)
  335. for v > max {
  336. v = int63(r)
  337. }
  338. return v % n
  339. }
  340. /*
  341. Generates a random 127 bit value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  342. Inputs:
  343. - n: The upper bound of the generated number, this value is exclusive
  344. - r: The random number generator to use, or nil for the global generator
  345. Returns:
  346. - val: A random 127 bit value in the range `(0, n]`
  347. WARNING: Panics if n is less than 0
  348. Example:
  349. import "core:math/rand"
  350. import "core:fmt"
  351. int127_max_example :: proc() {
  352. // Using the global random number generator
  353. fmt.println(rand.int127_max(16))
  354. // Using local random number generator
  355. my_rand := rand.create(1)
  356. fmt.println(rand.int127_max(1024, &my_rand))
  357. }
  358. Possible Output:
  359. 6
  360. 500
  361. */
  362. @(require_results)
  363. int127_max :: proc(n: i128, r: ^Rand = nil) -> (val: i128) {
  364. if n <= 0 {
  365. panic("Invalid argument to int127_max")
  366. }
  367. if n&(n-1) == 0 {
  368. return int127(r) & (n-1)
  369. }
  370. max := i128((1<<127) - 1 - (1<<127)%u128(n))
  371. v := int127(r)
  372. for v > max {
  373. v = int127(r)
  374. }
  375. return v % n
  376. }
  377. /*
  378. Generates a random integer value in the range `(0, n]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  379. Inputs:
  380. - n: The upper bound of the generated number, this value is exclusive
  381. - r: The random number generator to use, or nil for the global generator
  382. Returns:
  383. - val: A random integer value in the range `(0, n]`
  384. WARNING: Panics if n is less than 0
  385. Example:
  386. import "core:math/rand"
  387. import "core:fmt"
  388. int_max_example :: proc() {
  389. // Using the global random number generator
  390. fmt.println(rand.int_max(16))
  391. // Using local random number generator
  392. my_rand := rand.create(1)
  393. fmt.println(rand.int_max(1024, &my_rand))
  394. }
  395. Possible Output:
  396. 6
  397. 500
  398. */
  399. @(require_results)
  400. int_max :: proc(n: int, r: ^Rand = nil) -> (val: int) {
  401. if n <= 0 {
  402. panic("Invalid argument to int_max")
  403. }
  404. when size_of(int) == 4 {
  405. return int(int31_max(i32(n), r))
  406. } else {
  407. return int(int63_max(i64(n), r))
  408. }
  409. }
  410. /*
  411. Generates a random double floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  412. Inputs:
  413. - r: The random number generator to use, or nil for the global generator
  414. Returns:
  415. - val: A random double floating point value in the range `(0, 1]`
  416. Example:
  417. import "core:math/rand"
  418. import "core:fmt"
  419. float64_example :: proc() {
  420. // Using the global random number generator
  421. fmt.println(rand.float64())
  422. // Using local random number generator
  423. my_rand := rand.create(1)
  424. fmt.println(rand.float64(&my_rand))
  425. }
  426. Possible Output:
  427. 0.043
  428. 0.511
  429. */
  430. @(require_results) float64 :: proc(r: ^Rand = nil) -> (val: f64) { return f64(int63_max(1<<53, r)) / (1 << 53) }
  431. /*
  432. Generates a random single floating point value in the range `(0, 1]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  433. Inputs:
  434. - r: The random number generator to use, or nil for the global generator
  435. Returns:
  436. - val: A random single floating point value in the range `(0, 1]`
  437. Example:
  438. import "core:math/rand"
  439. import "core:fmt"
  440. float32_example :: proc() {
  441. // Using the global random number generator
  442. fmt.println(rand.float32())
  443. // Using local random number generator
  444. my_rand := rand.create(1)
  445. fmt.println(rand.float32(&my_rand))
  446. }
  447. Possible Output:
  448. 0.043
  449. 0.511
  450. */
  451. @(require_results) float32 :: proc(r: ^Rand = nil) -> (val: f32) { return f32(float64(r)) }
  452. /*
  453. Generates a random double floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  454. Inputs:
  455. - low: The lower bounds of the value, this value is inclusive
  456. - high: The upper bounds of the value, this value is exclusive
  457. - r: The random number generator to use, or nil for the global generator
  458. Returns:
  459. - val: A random double floating point value in the range `(low, high]`
  460. Example:
  461. import "core:math/rand"
  462. import "core:fmt"
  463. float64_range_example :: proc() {
  464. // Using the global random number generator
  465. fmt.println(rand.float64_range(-10, 300))
  466. // Using local random number generator
  467. my_rand := rand.create(1)
  468. fmt.println(rand.float64_range(600, 900, &my_rand))
  469. }
  470. Possible Output:
  471. 15.312
  472. 673.130
  473. */
  474. @(require_results) float64_range :: proc(low, high: f64, r: ^Rand = nil) -> (val: f64) { return (high-low)*float64(r) + low }
  475. /*
  476. Generates a random single floating point value in the range `(low, high]` using the provided random number generator. If no generator is provided the global random number generator will be used.
  477. Inputs:
  478. - low: The lower bounds of the value, this value is inclusive
  479. - high: The upper bounds of the value, this value is exclusive
  480. - r: The random number generator to use, or nil for the global generator
  481. Returns:
  482. - val: A random single floating point value in the range `(low, high]`
  483. Example:
  484. import "core:math/rand"
  485. import "core:fmt"
  486. float32_range_example :: proc() {
  487. // Using the global random number generator
  488. fmt.println(rand.float32_range(-10, 300))
  489. // Using local random number generator
  490. my_rand := rand.create(1)
  491. fmt.println(rand.float32_range(600, 900, &my_rand))
  492. }
  493. Possible Output:
  494. 15.312
  495. 673.130
  496. */
  497. @(require_results) float32_range :: proc(low, high: f32, r: ^Rand = nil) -> (val: f32) { return (high-low)*float32(r) + low }
  498. /*
  499. Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
  500. Inputs:
  501. - p: The byte slice to fill
  502. - r: The random number generator to use, or nil for the global generator
  503. Returns:
  504. - n: The number of bytes generated
  505. Example:
  506. import "core:math/rand"
  507. import "core:fmt"
  508. read_example :: proc() {
  509. // Using the global random number generator
  510. data: [8]byte
  511. n := rand.read(data[:])
  512. fmt.println(n)
  513. fmt.println(data)
  514. }
  515. Possible Output:
  516. 8
  517. [32, 4, 59, 7, 1, 2, 2, 119]
  518. */
  519. @(require_results)
  520. read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
  521. pos := i8(0)
  522. val := i64(0)
  523. for n = 0; n < len(p); n += 1 {
  524. if pos == 0 {
  525. val = int63(r)
  526. pos = 7
  527. }
  528. p[n] = byte(val)
  529. val >>= 8
  530. pos -= 1
  531. }
  532. return
  533. }
  534. /*
  535. Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used.
  536. *Allocates Using Provided Allocator*
  537. Inputs:
  538. - n: The size of the created slice
  539. - r: The random number generator to use, or nil for the global generator
  540. - allocator: (default: context.allocator)
  541. Returns:
  542. - res: A slice filled with random values
  543. - err: An allocator error if one occured, `nil` otherwise
  544. Example:
  545. import "core:math/rand"
  546. import "core:mem"
  547. import "core:fmt"
  548. perm_example :: proc() -> (err: mem.Allocator_Error) {
  549. // Using the global random number generator and using the context allocator
  550. data := rand.perm(4) or_return
  551. fmt.println(data)
  552. defer delete(data, context.allocator)
  553. // Using local random number generator and temp allocator
  554. my_rand := rand.create(1)
  555. data_tmp := rand.perm(4, &my_rand, context.temp_allocator) or_return
  556. fmt.println(data_tmp)
  557. return
  558. }
  559. Possible Output:
  560. [7201011, 3, 9123, 231131]
  561. [19578, 910081, 131, 7]
  562. */
  563. @(require_results)
  564. perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
  565. m := make([]int, n, allocator) or_return
  566. for i := 0; i < n; i += 1 {
  567. j := int_max(i+1, r)
  568. m[i] = m[j]
  569. m[j] = i
  570. }
  571. return m, {}
  572. }
  573. /*
  574. Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used.
  575. Inputs:
  576. - array: The slice to randomize
  577. - r: The random number generator to use, or nil for the global generator
  578. Example:
  579. import "core:math/rand"
  580. import "core:fmt"
  581. shuffle_example :: proc() {
  582. // Using the global random number generator
  583. data: [4]int = { 1, 2, 3, 4 }
  584. fmt.println(data) // the contents are in order
  585. rand.shuffle(data[:])
  586. fmt.println(data) // the contents have been shuffled
  587. }
  588. Possible Output:
  589. [1, 2, 3, 4]
  590. [2, 4, 3, 1]
  591. */
  592. shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
  593. n := i64(len(array))
  594. if n < 2 {
  595. return
  596. }
  597. for i := i64(0); i < n; i += 1 {
  598. j := int63_max(n, r)
  599. array[i], array[j] = array[j], array[i]
  600. }
  601. }
  602. /*
  603. Returns a random element from the provided slice. If no generator is provided the global random number generator will be used.
  604. Inputs:
  605. - array: The slice to choose an element from
  606. - r: The random number generator to use, or nil for the global generator
  607. Returns:
  608. - res: A random element from `array`
  609. Example:
  610. import "core:math/rand"
  611. import "core:fmt"
  612. choice_example :: proc() {
  613. // Using the global random number generator
  614. data: [4]int = { 1, 2, 3, 4 }
  615. fmt.println(rand.choice(data[:]))
  616. fmt.println(rand.choice(data[:]))
  617. fmt.println(rand.choice(data[:]))
  618. fmt.println(rand.choice(data[:]))
  619. }
  620. Possible Output:
  621. 3
  622. 2
  623. 2
  624. 4
  625. */
  626. @(require_results)
  627. choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
  628. n := i64(len(array))
  629. if n < 1 {
  630. return E{}
  631. }
  632. return array[int63_max(n, r)]
  633. }