rand.odin 19 KB

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