2
0

rand.odin 14 KB

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