2022-01-05 19:06:08 +03:00
|
|
|
# Description
|
2020-06-09 16:06:07 +03:00
|
|
|
|
|
|
|
The V `rand` module provides two main ways in which users can generate pseudorandom numbers:
|
|
|
|
|
2022-05-09 17:59:20 +03:00
|
|
|
## Direct Access Through The `rand` Module
|
|
|
|
|
|
|
|
```
|
|
|
|
// Import the rand module
|
|
|
|
import rand
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
// Optionally seed the default generator
|
2023-01-19 16:21:47 +03:00
|
|
|
rand.seed([u32(3223878742), 1732001562])
|
2022-05-09 17:59:20 +03:00
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
// Use the top-level functions
|
2022-10-20 22:14:33 +03:00
|
|
|
rand.u32n(100)!
|
2022-05-09 17:59:20 +03:00
|
|
|
rand.int() // among others ...
|
|
|
|
```
|
|
|
|
|
|
|
|
## Through A Generator Of Choice
|
|
|
|
|
|
|
|
```
|
|
|
|
// Import the rand module
|
|
|
|
import rand
|
|
|
|
import rand.seed
|
|
|
|
|
|
|
|
// Import the module of the generator you want to use
|
|
|
|
import rand.pcg32
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
// Initialise the generator struct (note the `mut`)
|
|
|
|
mut rng := &rand.PRNG(pcg32.PCG32RNG{})
|
|
|
|
|
|
|
|
// Optionally seed the generator
|
|
|
|
rng.seed(seed.time_seed_array(pcg32.seed_len))
|
|
|
|
|
|
|
|
...
|
|
|
|
|
|
|
|
// Use functions of your choice
|
2022-10-20 22:14:33 +03:00
|
|
|
rng.u32n(100)!
|
2022-05-09 17:59:20 +03:00
|
|
|
rng.int() // among others ...
|
|
|
|
```
|
|
|
|
|
|
|
|
## More Information
|
2020-06-09 16:06:07 +03:00
|
|
|
|
2021-03-21 20:36:17 +03:00
|
|
|
You can change the default generator to a different one. The only requirement is that
|
|
|
|
the generator must implement the `PRNG` interface. See `get_current_rng()` and `set_rng()`.
|
|
|
|
|
|
|
|
**Note:** The global PRNG is not thread safe. It is recommended to use separate generators for
|
2022-05-09 17:59:20 +03:00
|
|
|
separate threads in multi-threaded applications.
|
2021-03-21 20:36:17 +03:00
|
|
|
|
2022-05-09 17:59:20 +03:00
|
|
|
There are only a few extra functions that are defined only in this top-level `rand` module.
|
|
|
|
Otherwise, there is feature parity between the generator functions and the top-level functions.
|
2021-03-21 20:36:17 +03:00
|
|
|
|
2020-06-09 16:06:07 +03:00
|
|
|
# General Background
|
|
|
|
|
2022-01-05 19:06:08 +03:00
|
|
|
A PRNG is a Pseudo Random Number Generator.
|
|
|
|
Computers cannot generate truly random numbers without an external source of noise or entropy.
|
|
|
|
We can use algorithms to generate sequences of seemingly random numbers,
|
2023-01-19 16:21:47 +03:00
|
|
|
but their outputs will always be deterministic, according to the seed values.
|
|
|
|
|
|
|
|
This is often useful for simulations that need the same starting seeds.
|
|
|
|
You may be debugging a program and want to restart it with the same
|
|
|
|
seeds, or you want to verify a working program is still
|
|
|
|
operating identically after compiler or operating system updates.
|
2020-06-09 16:06:07 +03:00
|
|
|
|
2022-01-05 19:06:08 +03:00
|
|
|
If you need truly random numbers that are going to be used for cryptography,
|
2020-11-18 20:28:28 +03:00
|
|
|
use the `crypto.rand` module.
|
2020-06-09 16:06:07 +03:00
|
|
|
|
2021-03-21 20:36:17 +03:00
|
|
|
# Seeding Functions
|
2020-06-09 16:06:07 +03:00
|
|
|
|
2023-01-19 16:21:47 +03:00
|
|
|
All the generators are initialized with time-based seeds.
|
2021-03-21 20:36:17 +03:00
|
|
|
The helper functions publicly available in `rand.seed` module are:
|
2020-06-09 16:06:07 +03:00
|
|
|
|
|
|
|
1. `time_seed_array()` - returns a `[]u32` that can be directly plugged into the `seed()` functions.
|
2020-11-18 20:28:28 +03:00
|
|
|
2. `time_seed_32()` and `time_seed_64()` - 32-bit and 64-bit values respectively
|
2022-05-09 17:59:20 +03:00
|
|
|
that are generated from the current time.
|
2020-06-09 16:06:07 +03:00
|
|
|
|
2023-01-19 16:21:47 +03:00
|
|
|
When composing your own seeds, use "typical" u32 numbers, not small numbers. This
|
|
|
|
is especially important for PRNGs with large state, such as `mt19937`. You can create
|
|
|
|
random unsigned integers with openssl `rand` or with `v repl` as follows:
|
|
|
|
|
|
|
|
```
|
|
|
|
$ openssl rand -hex 4
|
|
|
|
e3655862
|
|
|
|
$ openssl rand -hex 4
|
|
|
|
97c4b1db
|
|
|
|
$ v repl
|
|
|
|
>>> import rand
|
|
|
|
>>> [rand.u32(),rand.u32()]
|
|
|
|
[2132382944, 2443871665]
|
|
|
|
```
|
|
|
|
|
2020-06-09 16:06:07 +03:00
|
|
|
# Caveats
|
|
|
|
|
2020-11-18 20:28:28 +03:00
|
|
|
Note that the `sys.SysRNG` struct (in the C backend) uses `C.srand()` which sets the seed globally.
|
2022-01-05 19:06:08 +03:00
|
|
|
Consequently, all instances of the RNG will be affected.
|
|
|
|
This problem does not arise for the other RNGs.
|
2020-11-18 20:28:28 +03:00
|
|
|
A workaround (if you _must_ use the libc RNG) is to:
|
2020-06-09 16:06:07 +03:00
|
|
|
|
|
|
|
1. Seed the first instance.
|
|
|
|
2. Generate all values required.
|
|
|
|
3. Seed the second instance.
|
|
|
|
4. Generate all values required.
|
|
|
|
5. And so on...
|
2020-12-27 21:06:17 +03:00
|
|
|
|
|
|
|
# Notes
|
|
|
|
|
2022-05-09 17:59:20 +03:00
|
|
|
Please note that [math interval](<https://en.wikipedia.org/wiki/Interval_(mathematics)#Including_or_excluding_endpoints>) notation is used throughout
|
2020-12-27 21:06:17 +03:00
|
|
|
the function documentation to denote what numbers ranges include.
|
2022-01-05 19:06:08 +03:00
|
|
|
An example of `[0, max)` thus denotes a range with all posible values
|
2020-12-27 21:06:17 +03:00
|
|
|
between `0` and `max` **including** 0 but **excluding** `max`.
|