v / vlib / rand / rand.v
813 lines · 704 sloc · 25.54 KB · 8a36fe3fd82b73666e9d0d9e8294c59cced1b268
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4@[has_globals]
5module rand
6
7import math.bits
8import rand.config
9import rand.wyrand
10import time
11
12// PRNG is a common interface for all PRNGs that can be used seamlessly with the rand modules's API.
13// It defines all the methods that a PRNG (in the vlib or custom made) must
14// implement in order to ensure that _all_ functions can be used with the generator.
15pub interface PRNG {
16mut:
17 seed(seed_data []u32)
18 u8() u8
19 u16() u16
20 u32() u32
21 u64() u64
22 block_size() int
23 free()
24}
25
26// default_rng is used by the module level public APIs like rand.u8() etc.
27__global default_rng &PRNG
28
29// new_default returns a new instance of the default RNG. If the seed is not provided, the current time will be used to seed the instance.
30@[manualfree]
31pub fn new_default(config_ config.PRNGConfigStruct) &PRNG {
32 mut rng := &wyrand.WyRandRNG{}
33 rng.seed(config_.seed_)
34 unsafe { config_.seed_.free() }
35 return &PRNG(rng)
36}
37
38// get_current_rng returns the PRNG instance currently in use. If it is not changed, it will be an instance of wyrand.WyRandRNG.
39pub fn get_current_rng() &PRNG {
40 return default_rng
41}
42
43// set_rng changes the default RNG from wyrand.WyRandRNG (or whatever the last RNG was).
44// Note that this new RNG must be seeded manually with a constant seed or the
45// `seed.time_seed_array()` method. Also, it is recommended to store the old RNG in a variable and
46// should be restored if work with the custom RNG is complete. It is not necessary to restore if the
47// program terminates soon afterwards.
48pub fn set_rng(rng &PRNG) {
49 default_rng = unsafe { rng }
50}
51
52// seed sets the given array of `u32` values as the seed for the `default_rng`.
53// Note: the default_rng is already seeded with a *time dependent value*,
54// so if you just need some randomness, for a game/simulation, and you do not need
55// reproducibility, just use it, without calling rand.seed() to do explicit seeding.
56// The default_rng is an instance of WyRandRNG which takes 2 u32 values.
57// When using a custom RNG, make sure to use the correct number of u32s.
58pub fn seed(seed []u32) {
59 default_rng.seed(seed)
60}
61
62// bytes returns a buffer of `bytes_needed` random bytes
63@[inline]
64pub fn (mut rng PRNG) bytes(bytes_needed int) ![]u8 {
65 if bytes_needed < 0 {
66 return error('can not read < 0 random bytes')
67 }
68
69 mut buffer := []u8{len: bytes_needed}
70 read_internal(mut rng, mut buffer)
71
72 return buffer
73}
74
75// read fills in `buf` with a maximum of `buf.len` random bytes.
76pub fn (mut rng PRNG) read(mut buf []u8) {
77 read_internal(mut rng, mut buf)
78}
79
80// i32n returns a uniformly distributed pseudorandom 32-bit signed positive `i32` in range `[0, max)`.
81@[inline]
82pub fn (mut rng PRNG) i32n(max i32) !i32 {
83 return i32(rng.intn(max)!)
84}
85
86// u32n returns a uniformly distributed pseudorandom 32-bit unsigned positive `u32` in range `[0, max)`.
87@[inline]
88pub fn (mut rng PRNG) u32n(max u32) !u32 {
89 if max == 0 {
90 return error('max must be positive integer')
91 }
92 // Owing to the pigeon-hole principle, we can't simply do
93 // val := rng.u32() % max.
94 // It'll wreck the properties of the distribution unless
95 // max evenly divides 2^32. So we divide evenly to
96 // the closest power of two. Then we loop until we find
97 // an int in the required range
98 bit_len := bits.len_32(max)
99 if _unlikely_(bit_len == 32) {
100 for {
101 value := rng.u32()
102 if value < max {
103 return value
104 }
105 }
106 } else {
107 mask := if _unlikely_(bit_len == 31) {
108 u32(0x7FFFFFFF)
109 } else {
110 (u32(1) << (bit_len + 1)) - 1
111 }
112 for {
113 value := rng.u32() & mask
114 if value < max {
115 return value
116 }
117 }
118 }
119 return u32(0)
120}
121
122// u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`.
123@[inline]
124pub fn (mut rng PRNG) u64n(max u64) !u64 {
125 if max == 0 {
126 return error('max must be positive integer')
127 }
128 bit_len := bits.len_64(max)
129 if _unlikely_(bit_len == 64) {
130 for {
131 value := rng.u64()
132 if value < max {
133 return value
134 }
135 }
136 } else {
137 mask := if _unlikely_(bit_len == 63) {
138 u64(0x7FFFFFFFFFFFFFFF)
139 } else {
140 (u64(1) << (bit_len + 1)) - 1
141 }
142 for {
143 value := rng.u64() & mask
144 if value < max {
145 return value
146 }
147 }
148 }
149 return u64(0)
150}
151
152// u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`.
153@[inline]
154pub fn (mut rng PRNG) u32_in_range(min u32, max u32) !u32 {
155 if max <= min {
156 return error('max must be greater than min')
157 }
158 return min + rng.u32n(max - min)!
159}
160
161// u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`.
162@[inline]
163pub fn (mut rng PRNG) u64_in_range(min u64, max u64) !u64 {
164 if max <= min {
165 return error('max must be greater than min')
166 }
167 return min + rng.u64n(max - min)!
168}
169
170// i8 returns a (possibly negative) pseudorandom 8-bit `i8`.
171@[inline]
172pub fn (mut rng PRNG) i8() i8 {
173 return i8(rng.u8())
174}
175
176// i16 returns a (possibly negative) pseudorandom 16-bit `i16`.
177@[inline]
178pub fn (mut rng PRNG) i16() i16 {
179 return i16(rng.u16())
180}
181
182// i32 returns a (possibly negative) pseudorandom 32-bit `i32`.
183@[inline]
184pub fn (mut rng PRNG) i32() i32 {
185 return i32(rng.u32())
186}
187
188// int returns a (possibly negative) pseudorandom 32-bit `int`.
189@[inline]
190pub fn (mut rng PRNG) int() int {
191 return int(rng.u32())
192}
193
194// i64 returns a (possibly negative) pseudorandom 64-bit `i64`.
195@[inline]
196pub fn (mut rng PRNG) i64() i64 {
197 return i64(rng.u64())
198}
199
200// int31 returns a positive pseudorandom 31-bit `int`.
201@[inline]
202pub fn (mut rng PRNG) int31() int {
203 return int(rng.u32() & u32(0x7FFFFFFF)) // Set the 32nd bit to 0.
204}
205
206// int63 returns a positive pseudorandom 63-bit `i64`.
207@[inline]
208pub fn (mut rng PRNG) int63() i64 {
209 return i64(rng.u64() & u64(0x7FFFFFFFFFFFFFFF)) // Set the 64th bit to 0.
210}
211
212// intn returns a pseudorandom `int` in range `[0, max)`.
213@[inline]
214pub fn (mut rng PRNG) intn(max int) !int {
215 if max <= 0 {
216 return error('max has to be positive.')
217 }
218 return int(rng.u32n(u32(max))!)
219}
220
221// i64n returns a pseudorandom int that lies in `[0, max)`.
222@[inline]
223pub fn (mut rng PRNG) i64n(max i64) !i64 {
224 if max <= 0 {
225 return error('max has to be positive.')
226 }
227 return i64(rng.u64n(u64(max))!)
228}
229
230// int_in_range returns a pseudorandom `int` in range `[min, max)`.
231@[inline]
232pub fn (mut rng PRNG) int_in_range(min int, max int) !int {
233 if max <= min {
234 return error('max must be greater than min')
235 }
236 // This supports negative ranges like [-10, -5) because the difference is positive
237 return min + rng.intn(max - min)!
238}
239
240// int_in_range returns a pseudorandom `int` in range `[min, max)`.
241@[inline]
242pub fn (mut rng PRNG) i32_in_range(min i32, max i32) !i32 {
243 if max <= min {
244 return error('max must be greater than min')
245 }
246 // This supports negative ranges like [-10, -5) because the difference is positive
247 return min + i32(rng.intn(max - min)!)
248}
249
250// i64_in_range returns a pseudorandom `i64` in range `[min, max)`.
251@[inline]
252pub fn (mut rng PRNG) i64_in_range(min i64, max i64) !i64 {
253 if max <= min {
254 return error('max must be greater than min')
255 }
256 return min + rng.i64n(max - min)!
257}
258
259// smallest mantissa with exponent 0 (un normalized)
260const reciprocal_2_23rd = 1.0 / f64(u32(1) << 23)
261const reciprocal_2_52nd = 1.0 / f64(u64(1) << 52)
262const ieee754_mantissa_f32_mask = (u32(1) << 23) - 1 // 23 bits for f32
263const ieee754_mantissa_f64_mask = (u64(1) << 52) - 1 // 52 bits for f64
264
265// f32 returns a pseudorandom `f32` value in range `[0, 1)`
266// using rng.u32() multiplied by an f64 constant.
267@[inline]
268pub fn (mut rng PRNG) f32() f32 {
269 return f32((rng.u32() >> 9) * reciprocal_2_23rd)
270}
271
272// f32cp returns a pseudorandom `f32` value in range `[0, 1)`
273// with full precision (mantissa random between 0 and 1
274// and the exponent varies as well.)
275// See https://allendowney.com/research/rand/ for background on the method.
276@[inline]
277pub fn (mut rng PRNG) f32cp() f32 {
278 mut x := rng.u32()
279 mut exp := u32(126)
280 mut mask := u32(1) << 31
281
282 // check if prng returns 0; rare but keep looking for precision
283 if _unlikely_(x == 0) {
284 x = rng.u32()
285 exp -= 31
286 }
287 // count leading one bits and scale exponent accordingly
288 for {
289 if x & mask != 0 {
290 mask >>= 1
291 exp -= 1
292 } else {
293 break
294 }
295 }
296 // if we used any high-order mantissa bits; replace x
297 if exp < (126 - 8) {
298 x = rng.u32()
299 }
300
301 // Assumes little-endian IEEE floating point.
302 x = (exp << 23) | (x >> 8) & ieee754_mantissa_f32_mask
303 return bits.f32_from_bits(x)
304}
305
306// f64 returns a pseudorandom `f64` value in range `[0, 1)`
307// using rng.u64() multiplied by a constant.
308@[inline]
309pub fn (mut rng PRNG) f64() f64 {
310 return f64((rng.u64() >> 12) * reciprocal_2_52nd)
311}
312
313// f64cp returns a pseudorandom `f64` value in range `[0, 1)`
314// with full precision (mantissa random between 0 and 1
315// and the exponent varies as well.)
316// See https://allendowney.com/research/rand/ for background on the method.
317@[inline]
318pub fn (mut rng PRNG) f64cp() f64 {
319 mut x := rng.u64()
320 mut exp := u64(1022)
321 mut mask := u64(1) << 63
322 mut bitcount := u32(0)
323
324 // check if prng returns 0; unlikely.
325 if _unlikely_(x == 0) {
326 x = rng.u64()
327 exp -= 31
328 }
329 // count leading one bits and scale exponent accordingly
330 for {
331 if x & mask != 0 {
332 mask >>= 1
333 bitcount += 1
334 } else {
335 break
336 }
337 }
338 exp -= bitcount
339 if bitcount > 11 {
340 x = rng.u64()
341 }
342 x = (exp << 52) | (x & ieee754_mantissa_f64_mask)
343 return bits.f64_from_bits(x)
344}
345
346// f32n returns a pseudorandom `f32` value in range `[0, max]`.
347@[inline]
348pub fn (mut rng PRNG) f32n(max f32) !f32 {
349 if max < 0 {
350 return error('max has to be non-negative.')
351 }
352 return rng.f32() * max
353}
354
355// f64n returns a pseudorandom `f64` value in range `[0, max]`.
356@[inline]
357pub fn (mut rng PRNG) f64n(max f64) !f64 {
358 if max < 0 {
359 return error('max has to be non-negative.')
360 }
361 return rng.f64() * max
362}
363
364// f32_in_range returns a pseudorandom `f32` in range `[min, max]`.
365@[inline]
366pub fn (mut rng PRNG) f32_in_range(min f32, max f32) !f32 {
367 if max < min {
368 return error('max must be greater than or equal to min')
369 }
370 return min + rng.f32n(max - min)!
371}
372
373// i64_in_range returns a pseudorandom `i64` in range `[min, max]`.
374@[inline]
375pub fn (mut rng PRNG) f64_in_range(min f64, max f64) !f64 {
376 if max < min {
377 return error('max must be greater than or equal to min')
378 }
379 return min + rng.f64n(max - min)!
380}
381
382// ulid generates an unique lexicographically sortable identifier.
383// See https://github.com/ulid/spec .
384// Note: ULIDs can leak timing information, if you make them public, because
385// you can infer the rate at which some resource is being created, like
386// users or business transactions.
387// (https://news.ycombinator.com/item?id=14526173)
388pub fn (mut rng PRNG) ulid() string {
389 return internal_ulid_at_millisecond(mut rng, u64(time.utc().unix_milli()))
390}
391
392// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_milli`.
393pub fn (mut rng PRNG) ulid_at_millisecond(unix_time_milli u64) string {
394 return internal_ulid_at_millisecond(mut rng, unix_time_milli)
395}
396
397// string_from_set returns a string of length `len` containing random characters sampled from the given `charset`.
398pub fn (mut rng PRNG) string_from_set(charset string, len int) string {
399 return internal_string_from_set(mut rng, charset, len)
400}
401
402// string returns a string of length `len` containing random characters in range `[a-zA-Z]`.
403pub fn (mut rng PRNG) string(len int) string {
404 return internal_string_from_set(mut rng, english_letters, len)
405}
406
407// hex returns a hexadecimal number of length `len` containing random characters in range `[a-f0-9]`.
408pub fn (mut rng PRNG) hex(len int) string {
409 return internal_string_from_set(mut rng, hex_chars, len)
410}
411
412// ascii returns a random string of the printable ASCII characters with length `len`.
413pub fn (mut rng PRNG) ascii(len int) string {
414 return internal_string_from_set(mut rng, ascii_chars, len)
415}
416
417// fill_buffer_from_set fills the mutable `buf` with random characters from the given `charset`
418@[inline]
419pub fn (mut rng PRNG) fill_buffer_from_set(charset string, mut buf []u8) {
420 internal_fill_buffer_from_set(mut rng, charset, mut buf)
421}
422
423// bernoulli returns true with a probability p. Note that 0 <= p <= 1.
424pub fn (mut rng PRNG) bernoulli(p f64) !bool {
425 if p < 0 || p > 1 {
426 return error('${p} is not a valid probability value.')
427 }
428 return rng.f64() <= p
429}
430
431// normal returns a normally distributed pseudorandom f64 with mean `mu` and standard deviation `sigma`.
432// By default, `mu` is 0.0 and `sigma` is 1.0.
433// NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
434pub fn (mut rng PRNG) normal(conf config.NormalConfigStruct) !f64 {
435 x, _ := rng.normal_pair(conf)!
436 return x
437}
438
439// normal_pair returns a pair of normally distributed pseudorandom f64 with mean `mu` and standard deviation `sigma`.
440// By default, `mu` is 0.0 and `sigma` is 1.0.
441pub fn (mut rng PRNG) normal_pair(conf config.NormalConfigStruct) !(f64, f64) {
442 if conf.sigma <= 0 {
443 return error('Standard deviation must be positive')
444 }
445 // This is an implementation of the Marsaglia polar method
446 // See: https://doi.org/10.1137%2F1006063
447 // Also: https://en.wikipedia.org/wiki/Marsaglia_polar_method
448 for {
449 u := rng.f64_in_range(-1, 1) or { 0.0 }
450 v := rng.f64_in_range(-1, 1) or { 0.0 }
451
452 s := u * u + v * v
453 if s >= 1 || s == 0 {
454 continue
455 }
456 t := msqrt(-2 * mlog(s) / s)
457 x := conf.mu + conf.sigma * t * u
458 y := conf.mu + conf.sigma * t * v
459 return x, y
460 }
461 return error('Implementation error. Please file an issue.')
462}
463
464// binomial returns the number of successful trials out of n when the probability of success for each trial is p.
465pub fn (mut rng PRNG) binomial(n int, p f64) !int {
466 if p < 0 || p > 1 {
467 return error('${p} is not a valid probability value.')
468 }
469 mut count := 0
470 for _ in 0 .. n {
471 if rng.bernoulli(p)! {
472 count++
473 }
474 }
475 return count
476}
477
478// exponential returns an exponentially distributed random number with the rate parameter lambda.
479// It is expected that lambda is positive.
480pub fn (mut rng PRNG) exponential(lambda f64) f64 {
481 if lambda <= 0 {
482 panic('The rate (lambda) must be positive.')
483 }
484 // Use the inverse transform sampling method
485 return -mlog(rng.f64()) / lambda
486}
487
488// shuffle randomly permutates the elements in `a`. The range for shuffling is
489// optional and the entire array is shuffled by default. Leave the end as 0 to
490// shuffle all elements until the end.
491@[direct_array_access]
492pub fn (mut rng PRNG) shuffle[T](mut a []T, config_ config.ShuffleConfigStruct) ! {
493 config_.validate_for(a)!
494 new_end := if config_.end == 0 { a.len } else { config_.end }
495
496 // We implement the Fisher-Yates shuffle:
497 // https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm
498
499 for i in config_.start .. new_end - 1 {
500 x := rng.int_in_range(i, new_end) or { i }
501 // swap
502 a_i := a[i]
503 a[i] = a[x]
504 a[x] = a_i
505 }
506}
507
508// shuffle_clone returns a random permutation of the elements in `a`.
509// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
510pub fn (mut rng PRNG) shuffle_clone[T](a []T, config_ config.ShuffleConfigStruct) ![]T {
511 mut res := a.clone()
512 rng.shuffle[T](mut res, config_)!
513 return res
514}
515
516// choose samples k elements from the array without replacement.
517// This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
518// Note that if the array has repeating elements, then the sample may have repeats as well.
519pub fn (mut rng PRNG) choose[T](array []T, k int) ![]T {
520 n := array.len
521 if k > n {
522 return error('Cannot choose ${k} elements without replacement from a ${n}-element array.')
523 }
524 mut results := []T{len: k}
525 mut indices := []int{len: n, init: index}
526 rng.shuffle[int](mut indices)!
527 for i in 0 .. k {
528 results[i] = array[indices[i]]
529 }
530 return results
531}
532
533// element returns a random element from the given array.
534// Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform.
535pub fn (mut rng PRNG) element[T](array []T) !T {
536 if array.len == 0 {
537 return error('Cannot choose an element from an empty array.')
538 }
539 return array[rng.intn(array.len)!]
540}
541
542// sample samples k elements from the array with replacement.
543// This means the elements can repeat and the size of the sample may exceed the size of the array.
544pub fn (mut rng PRNG) sample[T](array []T, k int) []T {
545 mut results := []T{len: k}
546 for i in 0 .. k {
547 results[i] = array[rng.intn(array.len) or { 0 }]
548 }
549 return results
550}
551
552// u8 returns a uniformly distributed pseudorandom 8-bit unsigned positive `u8`.
553pub fn u8() u8 {
554 return default_rng.u8()
555}
556
557// u16 returns a uniformly distributed pseudorandom 16-bit unsigned positive `u16`.
558pub fn u16() u16 {
559 return default_rng.u16()
560}
561
562// u32 returns a uniformly distributed `u32` in range `[0, 2³²)`.
563pub fn u32() u32 {
564 return default_rng.u32()
565}
566
567// u64 returns a uniformly distributed `u64` in range `[0, 2⁶⁴)`.
568pub fn u64() u64 {
569 return default_rng.u64()
570}
571
572// u32n returns a uniformly distributed pseudorandom 32-bit signed positive `u32` in range `[0, max)`.
573pub fn u32n(max u32) !u32 {
574 return default_rng.u32n(max)
575}
576
577// u64n returns a uniformly distributed pseudorandom 64-bit signed positive `u64` in range `[0, max)`.
578pub fn u64n(max u64) !u64 {
579 return default_rng.u64n(max)
580}
581
582// u32_in_range returns a uniformly distributed pseudorandom 32-bit unsigned `u32` in range `[min, max)`.
583pub fn u32_in_range(min u32, max u32) !u32 {
584 return default_rng.u32_in_range(min, max)
585}
586
587// u64_in_range returns a uniformly distributed pseudorandom 64-bit unsigned `u64` in range `[min, max)`.
588pub fn u64_in_range(min u64, max u64) !u64 {
589 return default_rng.u64_in_range(min, max)
590}
591
592// i8 returns a uniformly distributed pseudorandom 8-bit signed (possibly negative) `i8`.
593pub fn i8() i8 {
594 return default_rng.i8()
595}
596
597// i16 returns a uniformly distributed pseudorandom 16-bit signed (possibly negative) `i16`.
598pub fn i16() i16 {
599 return default_rng.i16()
600}
601
602// i32 returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) `i32`.
603pub fn i32() i32 {
604 return default_rng.i32()
605}
606
607// int returns a uniformly distributed pseudorandom 32-bit signed (possibly negative) `int`.
608pub fn int() int {
609 return default_rng.int()
610}
611
612// i32n returns a uniformly distributed pseudorandom 32-bit signed positive `i32` in range `[0, max)`.
613pub fn i32n(max i32) !i32 {
614 return default_rng.i32n(max)
615}
616
617// intn returns a uniformly distributed pseudorandom 32-bit signed positive `int` in range `[0, max)`.
618pub fn intn(max int) !int {
619 return default_rng.intn(max)
620}
621
622// int_in_range returns a uniformly distributed pseudorandom 32-bit signed int in range `[min, max)`.
623// Both `min` and `max` can be negative, but we must have `min < max`.
624pub fn int_in_range(min int, max int) !int {
625 return default_rng.int_in_range(min, max)
626}
627
628// int_in_range returns a uniformly distributed pseudorandom 32-bit signed int in range `[min, max)`.
629// Both `min` and `max` can be negative, but we must have `min < max`.
630pub fn i32_in_range(min i32, max i32) !i32 {
631 return default_rng.i32_in_range(min, max)
632}
633
634// int31 returns a uniformly distributed pseudorandom 31-bit signed positive `int`.
635pub fn int31() int {
636 return default_rng.int31()
637}
638
639// i64 returns a uniformly distributed pseudorandom 64-bit signed (possibly negative) `i64`.
640pub fn i64() i64 {
641 return default_rng.i64()
642}
643
644// i64n returns a uniformly distributed pseudorandom 64-bit signed positive `i64` in range `[0, max)`.
645pub fn i64n(max i64) !i64 {
646 return default_rng.i64n(max)
647}
648
649// i64_in_range returns a uniformly distributed pseudorandom 64-bit signed `i64` in range `[min, max)`.
650pub fn i64_in_range(min i64, max i64) !i64 {
651 return default_rng.i64_in_range(min, max)
652}
653
654// int63 returns a uniformly distributed pseudorandom 63-bit signed positive `i64`.
655pub fn int63() i64 {
656 return default_rng.int63()
657}
658
659// f32 returns a uniformly distributed 32-bit floating point in range `[0, 1)`.
660pub fn f32() f32 {
661 return default_rng.f32()
662}
663
664// f32cp returns a uniformly distributed 32-bit floating point in range `[0, 1)` with full precision mantissa.
665pub fn f32cp() f32 {
666 return default_rng.f32cp()
667}
668
669// f64 returns a uniformly distributed 64-bit floating point in range `[0, 1)`.
670pub fn f64() f64 {
671 return default_rng.f64()
672}
673
674// f64 returns a uniformly distributed 64-bit floating point in range `[0, 1)` with full precision mantissa.
675pub fn f64cp() f64 {
676 return default_rng.f64cp()
677}
678
679// f32n returns a uniformly distributed 32-bit floating point in range `[0, max)`.
680pub fn f32n(max f32) !f32 {
681 return default_rng.f32n(max)
682}
683
684// f64n returns a uniformly distributed 64-bit floating point in range `[0, max)`.
685pub fn f64n(max f64) !f64 {
686 return default_rng.f64n(max)
687}
688
689// f32_in_range returns a uniformly distributed 32-bit floating point in range `[min, max)`.
690pub fn f32_in_range(min f32, max f32) !f32 {
691 return default_rng.f32_in_range(min, max)
692}
693
694// f64_in_range returns a uniformly distributed 64-bit floating point in range `[min, max)`.
695pub fn f64_in_range(min f64, max f64) !f64 {
696 return default_rng.f64_in_range(min, max)
697}
698
699// bytes returns a buffer of `bytes_needed` random bytes.
700pub fn bytes(bytes_needed int) ![]u8 {
701 return default_rng.bytes(bytes_needed)
702}
703
704// read fills in `buf` a maximum of `buf.len` random bytes.
705pub fn read(mut buf []u8) {
706 read_internal(mut default_rng, mut buf)
707}
708
709const english_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
710const hex_chars = '0123456789abcdef'
711const ascii_chars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz{|}~'
712
713// ulid generates an unique lexicographically sortable identifier.
714// See https://github.com/ulid/spec .
715// Note: ULIDs can leak timing information, if you make them public, because
716// you can infer the rate at which some resource is being created, like
717// users or business transactions.
718// (https://news.ycombinator.com/item?id=14526173)
719pub fn ulid() string {
720 return default_rng.ulid()
721}
722
723// ulid_at_millisecond does the same as `ulid` but takes a custom Unix millisecond timestamp via `unix_milli`.
724pub fn ulid_at_millisecond(unix_time_milli u64) string {
725 return default_rng.ulid_at_millisecond(unix_time_milli)
726}
727
728// string_from_set returns a string of length `len` containing random characters sampled from the given `charset`.
729pub fn string_from_set(charset string, len int) string {
730 return default_rng.string_from_set(charset, len)
731}
732
733// fill_buffer_from_set fills the array `buf` with random characters sampled from the given `charset`
734@[inline]
735pub fn fill_buffer_from_set(charset string, mut buf []u8) {
736 default_rng.fill_buffer_from_set(charset, mut buf)
737}
738
739// string returns a string of length `len` containing random characters in range `[a-zA-Z]`.
740pub fn string(len int) string {
741 return string_from_set(english_letters, len)
742}
743
744// hex returns a hexadecimal number of length `len` containing random characters in range `[a-f0-9]`.
745pub fn hex(len int) string {
746 return string_from_set(hex_chars, len)
747}
748
749// ascii returns a random string of the printable ASCII characters with length `len`.
750pub fn ascii(len int) string {
751 return string_from_set(ascii_chars, len)
752}
753
754// shuffle randomly permutates the elements in `a`.
755// The range for shuffling is optional and the entire array is shuffled by default.
756// Leave the end as 0 to shuffle all elements until the end.
757pub fn shuffle[T](mut a []T, config_ config.ShuffleConfigStruct) ! {
758 default_rng.shuffle[T](mut a, config_)!
759}
760
761// shuffle_clone returns a random permutation of the elements in `a`.
762// The permutation is done on a fresh clone of `a`, so `a` remains unchanged.
763pub fn shuffle_clone[T](a []T, config_ config.ShuffleConfigStruct) ![]T {
764 return default_rng.shuffle_clone[T](a, config_)
765}
766
767// choose samples k elements from the array without replacement.
768// This means the indices cannot repeat and it restricts the sample size to be less than or equal to the size of the given array.
769// Note that if the array has repeating elements, then the sample may have repeats as well.
770pub fn choose[T](array []T, k int) ![]T {
771 return default_rng.choose[T](array, k)
772}
773
774// element returns a random element from the given array.
775// Note that all the positions in the array have an equal chance of being selected. This means that if the array has repeating elements, then the probability of selecting a particular element is not uniform.
776pub fn element[T](array []T) !T {
777 return default_rng.element[T](array)
778}
779
780// sample samples k elements from the array with replacement.
781// This means the elements can repeat and the size of the sample may exceed the size of the array.
782pub fn sample[T](array []T, k int) []T {
783 return default_rng.sample[T](array, k)
784}
785
786// bernoulli returns true with a probability p. Note that 0 <= p <= 1.
787pub fn bernoulli(p f64) !bool {
788 return default_rng.bernoulli(p)
789}
790
791// normal returns a normally distributed pseudorandom f64 with mean `mu` and standard deviation `sigma`.
792// By default, `mu` is 0.0 and `sigma` is 1.0.
793// NOTE: Use normal_pair() instead if you're generating a lot of normal variates.
794pub fn normal(config_ config.NormalConfigStruct) !f64 {
795 return default_rng.normal(config_)
796}
797
798// normal_pair returns a pair of normally distributed pseudorandom f64 with mean `mu` and standard deviation `sigma`.
799// By default, `mu` is 0.0 and `sigma` is 1.0.
800pub fn normal_pair(config_ config.NormalConfigStruct) !(f64, f64) {
801 return default_rng.normal_pair(config_)
802}
803
804// binomial returns the number of successful trials out of n when the probability of success for each trial is p.
805pub fn binomial(n int, p f64) !int {
806 return default_rng.binomial(n, p)
807}
808
809// exponential returns an exponentially distributed random number with the rate parameter `lambda`.
810// It is expected that lambda is positive.
811pub fn exponential(lambda f64) f64 {
812 return default_rng.exponential(lambda)
813}
814