rand.odin 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. // Random number generators.
  2. package rand
  3. import "base:intrinsics"
  4. import "base:runtime"
  5. import "core:math"
  6. import "core:mem"
  7. Generator :: runtime.Random_Generator
  8. Generator_Query_Info :: runtime.Random_Generator_Query_Info
  9. Default_Random_State :: runtime.Default_Random_State
  10. default_random_generator :: runtime.default_random_generator
  11. @(require_results)
  12. create :: proc(seed: u64) -> (state: Default_Random_State) {
  13. seed := seed
  14. runtime.default_random_generator_proc(&state, .Reset, ([^]byte)(&seed)[:size_of(seed)])
  15. return
  16. }
  17. /*
  18. Reset the seed used by the context.random_generator.
  19. Inputs:
  20. - seed: The seed value
  21. Example:
  22. import "core:math/rand"
  23. import "core:fmt"
  24. reset_example :: proc() {
  25. rand.reset(1)
  26. fmt.println(rand.uint64())
  27. }
  28. Possible Output:
  29. 10
  30. */
  31. reset :: proc(seed: u64, gen := context.random_generator) {
  32. runtime.random_generator_reset_u64(gen, seed)
  33. }
  34. reset_bytes :: proc(bytes: []byte, gen := context.random_generator) {
  35. runtime.random_generator_reset_bytes(gen, bytes)
  36. }
  37. query_info :: proc(gen := context.random_generator) -> Generator_Query_Info {
  38. return runtime.random_generator_query_info(gen)
  39. }
  40. /*
  41. 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.
  42. Returns:
  43. - val: A random unsigned 32 bit value
  44. Example:
  45. import "core:math/rand"
  46. import "core:fmt"
  47. uint32_example :: proc() {
  48. fmt.println(rand.uint32())
  49. }
  50. Possible Output:
  51. 10
  52. 389
  53. */
  54. @(require_results)
  55. uint32 :: proc(gen := context.random_generator) -> (val: u32) {return u32(uint64(gen))}
  56. /*
  57. 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.
  58. Returns:
  59. - val: A random unsigned 64 bit value
  60. Example:
  61. import "core:math/rand"
  62. import "core:fmt"
  63. uint64_example :: proc() {
  64. fmt.println(rand.uint64())
  65. }
  66. Possible Output:
  67. 10
  68. 389
  69. */
  70. @(require_results)
  71. uint64 :: proc(gen := context.random_generator) -> (val: u64) {
  72. ok := runtime.random_generator_read_ptr(gen, &val, size_of(val))
  73. assert(ok, "uninitialized gen/context.random_generator")
  74. return
  75. }
  76. /*
  77. 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.
  78. Returns:
  79. - val: A random unsigned 128 bit value
  80. Example:
  81. import "core:math/rand"
  82. import "core:fmt"
  83. uint128_example :: proc() {
  84. fmt.println(rand.uint128())
  85. }
  86. Possible Output:
  87. 10
  88. 389
  89. */
  90. @(require_results)
  91. uint128 :: proc(gen := context.random_generator) -> (val: u128) {
  92. a := u128(uint64(gen))
  93. b := u128(uint64(gen))
  94. return (a<<64) | b
  95. }
  96. /*
  97. 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.
  98. The sign bit will always be set to 0, thus all generated numbers will be positive.
  99. Returns:
  100. - val: A random 31 bit value
  101. Example:
  102. import "core:math/rand"
  103. import "core:fmt"
  104. int31_example :: proc() {
  105. fmt.println(rand.int31())
  106. }
  107. Possible Output:
  108. 10
  109. 389
  110. */
  111. @(require_results) int31 :: proc(gen := context.random_generator) -> (val: i32) { return i32(uint32(gen) << 1 >> 1) }
  112. /*
  113. 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.
  114. The sign bit will always be set to 0, thus all generated numbers will be positive.
  115. Returns:
  116. - val: A random 63 bit value
  117. Example:
  118. import "core:math/rand"
  119. import "core:fmt"
  120. int63_example :: proc() {
  121. fmt.println(rand.int63())
  122. }
  123. Possible Output:
  124. 10
  125. 389
  126. */
  127. @(require_results) int63 :: proc(gen := context.random_generator) -> (val: i64) { return i64(uint64(gen) << 1 >> 1) }
  128. /*
  129. 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.
  130. The sign bit will always be set to 0, thus all generated numbers will be positive.
  131. Returns:
  132. - val: A random 127 bit value
  133. Example:
  134. import "core:math/rand"
  135. import "core:fmt"
  136. int127_example :: proc() {
  137. fmt.println(rand.int127())
  138. }
  139. Possible Output:
  140. 10
  141. 389
  142. */
  143. @(require_results) int127 :: proc(gen := context.random_generator) -> (val: i128) { return i128(uint128(gen) << 1 >> 1) }
  144. /*
  145. 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.
  146. Inputs:
  147. - n: The upper bound of the generated number, this value is exclusive
  148. Returns:
  149. - val: A random 31 bit value in the range `[0, n)`
  150. WARNING: Panics if n is less than 0
  151. Example:
  152. import "core:math/rand"
  153. import "core:fmt"
  154. int31_max_example :: proc() {
  155. fmt.println(rand.int31_max(16))
  156. }
  157. Possible Output:
  158. 6
  159. 500
  160. */
  161. @(require_results)
  162. int31_max :: proc(n: i32, gen := context.random_generator) -> (val: i32) {
  163. if n <= 0 {
  164. panic("Invalid argument to int31_max")
  165. }
  166. if n&(n-1) == 0 {
  167. return int31(gen) & (n-1)
  168. }
  169. max := i32((1<<31) - 1 - (1<<31)%u32(n))
  170. v := int31(gen)
  171. for v > max {
  172. v = int31(gen)
  173. }
  174. return v % n
  175. }
  176. /*
  177. 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.
  178. Inputs:
  179. - n: The upper bound of the generated number, this value is exclusive
  180. Returns:
  181. - val: A random 63 bit value in the range `[0, n)`
  182. WARNING: Panics if n is less than 0
  183. Example:
  184. import "core:math/rand"
  185. import "core:fmt"
  186. int63_max_example :: proc() {
  187. fmt.println(rand.int63_max(16))
  188. }
  189. Possible Output:
  190. 6
  191. 500
  192. */
  193. @(require_results)
  194. int63_max :: proc(n: i64, gen := context.random_generator) -> (val: i64) {
  195. if n <= 0 {
  196. panic("Invalid argument to int63_max")
  197. }
  198. if n&(n-1) == 0 {
  199. return int63(gen) & (n-1)
  200. }
  201. max := i64((1<<63) - 1 - (1<<63)%u64(n))
  202. v := int63(gen)
  203. for v > max {
  204. v = int63(gen)
  205. }
  206. return v % n
  207. }
  208. /*
  209. 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.
  210. Inputs:
  211. - n: The upper bound of the generated number, this value is exclusive
  212. Returns:
  213. - val: A random 127 bit value in the range `[0, n)`
  214. WARNING: Panics if n is less than 0
  215. Example:
  216. import "core:math/rand"
  217. import "core:fmt"
  218. int127_max_example :: proc() {
  219. fmt.println(rand.int127_max(16))
  220. }
  221. Possible Output:
  222. 6
  223. 500
  224. */
  225. @(require_results)
  226. int127_max :: proc(n: i128, gen := context.random_generator) -> (val: i128) {
  227. if n <= 0 {
  228. panic("Invalid argument to int127_max")
  229. }
  230. if n&(n-1) == 0 {
  231. return int127(gen) & (n-1)
  232. }
  233. max := i128((1<<127) - 1 - (1<<127)%u128(n))
  234. v := int127(gen)
  235. for v > max {
  236. v = int127(gen)
  237. }
  238. return v % n
  239. }
  240. /*
  241. 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.
  242. Inputs:
  243. - n: The upper bound of the generated number, this value is exclusive
  244. Returns:
  245. - val: A random integer value in the range `[0, n)`
  246. WARNING: Panics if n is less than 0
  247. Example:
  248. import "core:math/rand"
  249. import "core:fmt"
  250. int_max_example :: proc() {
  251. fmt.println(rand.int_max(16))
  252. }
  253. Possible Output:
  254. 6
  255. 13
  256. */
  257. @(require_results)
  258. int_max :: proc(n: int, gen := context.random_generator) -> (val: int) {
  259. if n <= 0 {
  260. panic("Invalid argument to int_max")
  261. }
  262. when size_of(int) == 4 {
  263. return int(int31_max(i32(n), gen))
  264. } else {
  265. return int(int63_max(i64(n), gen))
  266. }
  267. }
  268. /*
  269. 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.
  270. Returns:
  271. - val: A random double floating point value in the range `[0, 1)`
  272. Example:
  273. import "core:math/rand"
  274. import "core:fmt"
  275. float64_example :: proc() {
  276. fmt.println(rand.float64())
  277. }
  278. Possible Output:
  279. 0.043
  280. 0.511
  281. */
  282. @(require_results) float64 :: proc(gen := context.random_generator) -> (val: f64) { return f64(int63_max(1<<53, gen)) / (1 << 53) }
  283. /*
  284. 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.
  285. Returns:
  286. - val: A random single floating point value in the range `[0, 1)`
  287. Example:
  288. import "core:math/rand"
  289. import "core:fmt"
  290. float32_example :: proc() {
  291. fmt.println(rand.float32())
  292. }
  293. Possible Output:
  294. 0.043
  295. 0.511
  296. */
  297. @(require_results) float32 :: proc(gen := context.random_generator) -> (val: f32) { return f32(int31_max(1<<24, gen)) / (1 << 24) }
  298. /*
  299. 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.
  300. WARNING: Panics if `high < low`
  301. Inputs:
  302. - low: The lower bounds of the value, this value is inclusive
  303. - high: The upper bounds of the value, this value is exclusive
  304. Returns:
  305. - val: A random double floating point value in the range [low, high)
  306. Example:
  307. import "core:math/rand"
  308. import "core:fmt"
  309. float64_range_example :: proc() {
  310. fmt.println(rand.float64_range(-10, 300))
  311. }
  312. Possible Output:
  313. 15.312
  314. 273.15
  315. */
  316. @(require_results) float64_range :: proc(low, high: f64, gen := context.random_generator) -> (val: f64) {
  317. assert(low <= high, "low must be lower than or equal to high")
  318. val = (high-low)*float64(gen) + low
  319. if val >= high {
  320. val = max(low, high * (1 - math.F64_EPSILON))
  321. }
  322. return
  323. }
  324. /*
  325. 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.
  326. Inputs:
  327. - low: The lower bounds of the value, this value is inclusive
  328. - high: The upper bounds of the value, this value is exclusive
  329. Returns:
  330. - val: A random single floating point value in the range [low, high)
  331. WARNING: Panics if `high < low`
  332. Example:
  333. import "core:math/rand"
  334. import "core:fmt"
  335. float32_range_example :: proc() {
  336. fmt.println(rand.float32_range(-10, 300))
  337. }
  338. Possible Output:
  339. 15.312
  340. 273.15
  341. */
  342. @(require_results) float32_range :: proc(low, high: f32, gen := context.random_generator) -> (val: f32) {
  343. assert(low <= high, "low must be lower than or equal to high")
  344. val = (high-low)*float32(gen) + low
  345. if val >= high {
  346. val = max(low, high * (1 - math.F32_EPSILON))
  347. }
  348. return
  349. }
  350. /*
  351. 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.
  352. Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value.
  353. Inputs:
  354. - p: The byte slice to fill
  355. Returns:
  356. - n: The number of bytes generated
  357. Example:
  358. import "core:math/rand"
  359. import "core:fmt"
  360. read_example :: proc() {
  361. data: [8]byte
  362. n := rand.read(data[:])
  363. fmt.println(n)
  364. fmt.println(data)
  365. }
  366. Possible Output:
  367. 8
  368. [32, 4, 59, 7, 1, 2, 2, 119]
  369. */
  370. @(require_results)
  371. read :: proc(p: []byte, gen := context.random_generator) -> (n: int) {
  372. if !runtime.random_generator_read_bytes(gen, p) {return 0}
  373. return len(p)
  374. }
  375. /*
  376. 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.
  377. *Allocates Using Provided Allocator*
  378. Inputs:
  379. - n: The size of the created slice
  380. - allocator: (default: context.allocator)
  381. Returns:
  382. - res: A slice filled with random values
  383. - err: An allocator error if one occured, `nil` otherwise
  384. Example:
  385. import "core:math/rand"
  386. import "core:mem"
  387. import "core:fmt"
  388. perm_example :: proc() -> (err: mem.Allocator_Error) {
  389. data := rand.perm(4) or_return
  390. fmt.println(data)
  391. defer delete(data, context.allocator)
  392. return
  393. }
  394. Possible Output:
  395. [7201011, 3, 9123, 231131]
  396. [19578, 910081, 131, 7]
  397. */
  398. @(require_results)
  399. perm :: proc(n: int, allocator := context.allocator, gen := context.random_generator) -> (res: []int, err: mem.Allocator_Error) #optional_allocator_error {
  400. m := make([]int, n, allocator) or_return
  401. for i := 0; i < n; i += 1 {
  402. j := int_max(i+1, gen)
  403. m[i] = m[j]
  404. m[j] = i
  405. }
  406. return m, {}
  407. }
  408. /*
  409. Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used.
  410. Inputs:
  411. - array: The slice to randomize
  412. Example:
  413. import "core:math/rand"
  414. import "core:fmt"
  415. shuffle_example :: proc() {
  416. data: [4]int = { 1, 2, 3, 4 }
  417. fmt.println(data) // the contents are in order
  418. rand.shuffle(data[:])
  419. fmt.println(data) // the contents have been shuffled
  420. }
  421. Possible Output:
  422. [1, 2, 3, 4]
  423. [2, 4, 3, 1]
  424. */
  425. shuffle :: proc(array: $T/[]$E, gen := context.random_generator) {
  426. n := i64(len(array))
  427. if n < 2 {
  428. return
  429. }
  430. i := n - 1
  431. for ; i > (1<<31 - 2); i -= 1 {
  432. j := int63_max(i + 1, gen)
  433. array[i], array[j] = array[j], array[i]
  434. }
  435. for ; i > 0; i -= 1 {
  436. j := int31_max(i32(i + 1), gen)
  437. array[i], array[j] = array[j], array[i]
  438. }
  439. }
  440. /*
  441. Returns a random element from the provided slice. If no generator is provided the global random number generator will be used.
  442. Inputs:
  443. - array: The slice to choose an element from
  444. Returns:
  445. - res: A random element from `array`
  446. Example:
  447. import "core:math/rand"
  448. import "core:fmt"
  449. choice_example :: proc() {
  450. data: [4]int = { 1, 2, 3, 4 }
  451. fmt.println(rand.choice(data[:]))
  452. fmt.println(rand.choice(data[:]))
  453. fmt.println(rand.choice(data[:]))
  454. fmt.println(rand.choice(data[:]))
  455. }
  456. Possible Output:
  457. 3
  458. 2
  459. 2
  460. 4
  461. */
  462. @(require_results)
  463. choice :: proc(array: $T/[]$E, gen := context.random_generator) -> (res: E) {
  464. n := i64(len(array))
  465. if n < 1 {
  466. return E{}
  467. }
  468. return array[int63_max(n, gen)]
  469. }
  470. @(require_results)
  471. choice_enum :: proc($T: typeid, gen := context.random_generator) -> T where intrinsics.type_is_enum(T) {
  472. when size_of(T) <= 8 && len(T) == cap(T) {
  473. when intrinsics.type_is_unsigned(intrinsics.type_core_type(T)) &&
  474. u64(max(T)) > u64(max(i64)) {
  475. i := uint64(gen) % u64(len(T))
  476. i += u64(min(T))
  477. return T(i)
  478. } else {
  479. i := int63_max(i64(len(T)), gen)
  480. i += i64(min(T))
  481. return T(i)
  482. }
  483. } else {
  484. values := runtime.type_info_base(type_info_of(T)).variant.(runtime.Type_Info_Enum).values
  485. return T(choice(values))
  486. }
  487. }
  488. /*
  489. Returns a random *set* bit from the provided `bit_set`.
  490. Inputs:
  491. - set: The `bit_set` to choose a random set bit from
  492. Returns:
  493. - res: The randomly selected bit, or the zero value if `ok` is `false`
  494. - ok: Whether the bit_set was not empty and thus `res` is actually a random set bit
  495. Example:
  496. import "core:math/rand"
  497. import "core:fmt"
  498. choice_bit_set_example :: proc() {
  499. Flags :: enum {
  500. A,
  501. B = 10,
  502. C,
  503. }
  504. fmt.println(rand.choice_bit_set(bit_set[Flags]{}))
  505. fmt.println(rand.choice_bit_set(bit_set[Flags]{.B}))
  506. fmt.println(rand.choice_bit_set(bit_set[Flags]{.B, .C}))
  507. fmt.println(rand.choice_bit_set(bit_set[0..<15]{5, 1, 4}))
  508. }
  509. Possible Output:
  510. A false
  511. B true
  512. C true
  513. 5 true
  514. */
  515. @(require_results)
  516. choice_bit_set :: proc(set: $T/bit_set[$E], gen := context.random_generator) -> (res: E, ok: bool) {
  517. total_set := card(set)
  518. if total_set == 0 {
  519. return {}, false
  520. }
  521. core_set := transmute(intrinsics.type_bit_set_underlying_type(T))set
  522. for target := int_max(total_set, gen); target > 0; target -= 1 {
  523. core_set &= core_set - 1
  524. }
  525. return E(intrinsics.count_trailing_zeros(core_set)), true
  526. }