code / tomo-random

Lines568 Tomo238 C174 Markdown156
(193 lines)

Random Number Generators (RNG)

This library provides an RNG type (Random Number Generator) for Tomo. This type represents a self-contained piece of data that encapsulates the state of a relatively fast and relatively secure pseudo-random number generator. The current implementation is based on the ChaCha20 stream cipher, inspired by arc4random in OpenBSD.

An RNG object can be used for deterministic, repeatable generation of pseudorandom numbers (for example, to be used in a video game for creating seeded levels). The default random number generator for Tomo is called random and is, by default, initialized with random data from the operating system when a Tomo program launches.

RNG Functions

This documentation provides details on RNG functions available in the API. Lists also have some methods which use RNG values: list.shuffle(), list.shuffled(), list.random(), and list.sample().

Usage

Put this in your modules.ini:

[random]
version=v1.2
git=https://github.com/bruce-hill/tomo-random

Then either use the default RNG (seeded from OS random sources each run):

use random

func main()
    >> random.int(1, 100)
    
    my_rng := RandomNumberGenerator.new()
    >> my_rng.int(1, 100)
    
    my_list := ["A", "B", "C"]
    >> my_list.random(func(lo, hi:Int64) my_rng.int64(lo, hi))

bool

Generate a random boolean value with a given probability.

func bool(rng: RandomNumberGenerator, p: Num = 0.5 -> Bool)
  • rng: The random number generator to use.
  • p: The probability of returning a yes value. Values less than zero and NaN values are treated as equal to zero and values larger than zero are treated as equal to one.

Returns:
yes with probability p and no with probability 1-p.

Example:

>> random.bool()
= no
>> random.bool(1.0)
= yes

byte

Generate a random byte with uniform probability.

func byte(rng: RandomNumberGenerator -> Byte)
  • rng: The random number generator to use.

Returns:
A random byte (0-255).

Example:

>> random.byte()
= 103[B]

bytes

Generate a list of uniformly random bytes with the given length.

func bytes(rng: RandomNumberGenerator, count: Int -> [Byte])
  • rng: The random number generator to use.
  • count: The number of random bytes to return.

Returns:
A list of length count random bytes with uniform random distribution (0-255).

Example:

>> random.bytes(4)
= [135[B], 169[B], 103[B], 212[B]]

int, int64, int32, int16, int8

Generate a random integer value with the given range.

func int(rng: RandomNumberGenerator, min: Int, max: Int -> Int)
func int64(rng: RandomNumberGenerator, min: Int64 = Int64.min, max: Int64 = Int64.max -> Int)
func int32(rng: RandomNumberGenerator, min: Int32 = Int32.min, max: Int32 = Int32.max -> Int)
func int16(rng: RandomNumberGenerator, min: Int16 = Int16.min, max: Int16 = Int16.max -> Int)
func int8(rng: RandomNumberGenerator, min: Int8 = Int8.min, max: Int8 = Int8.max -> Int)
  • rng: The random number generator to use.
  • min: The minimum value to be returned.
  • max: The maximum value to be returned.

Returns:
An integer uniformly chosen from the range [min, max] (inclusive). If min is greater than max, an error will be raised.

Example:

>> random.int(1, 10)
= 8

new

Return a new random number generator.

func new(seed: [Byte] = (/dev/urandom).read_bytes(40)! -> RandomNumberGenerator)
  • seed: The seed use for the random number generator. A seed length of 40 bytes is recommended. Seed lengths of less than 40 bytes are padded with zeroes.

Returns:
A new random number generator.

Example:

>> my_rng := RandomNumberGenerator.new([1[B], 2[B], 3[B], 4[B]])
>> my_rng.bool()
= yes

num, num32

Generate a random floating point value with the given range.

func num(rng: RandomNumberGenerator, min: Num = 0.0, max: Num = 1.0 -> Int)
func num32(rng: RandomNumberGenerator, min: Num = 0.0_f32, max: Num = 1.0_f32 -> Int)
  • rng: The random number generator to use.
  • min: The minimum value to be returned.
  • max: The maximum value to be returned.

Returns:
A floating point number uniformly chosen from the range [min, max] (inclusive). If min is greater than max, an error will be raised.

Example:

>> random.num(1, 10)
= 9.512830439975572
1 # Random Number Generators (RNG)
3 This library provides an `RNG` type (Random Number Generator) for
4 [Tomo](https://tomo.bruce-hill.com). This type represents a self-contained
5 piece of data that encapsulates the state of a relatively fast and relatively
6 secure pseudo-random number generator. The current implementation is based on
7 the [ChaCha20 stream
8 cipher,](https://en.wikipedia.org/wiki/Salsa20#ChaCha_variant) inspired by
9 [`arc4random` in OpenBSD.](https://man.openbsd.org/arc4random.3)
11 An `RNG` object can be used for deterministic, repeatable generation of
12 pseudorandom numbers (for example, to be used in a video game for creating
13 seeded levels). The default random number generator for Tomo is called `random`
14 and is, by default, initialized with random data from the operating system when
15 a Tomo program launches.
17 ## RNG Functions
19 This documentation provides details on RNG functions available in the API.
20 Lists also have some methods which use RNG values:
21 `list.shuffle()`, `list.shuffled()`, `list.random()`, and `list.sample()`.
23 - [`func bool(rng: RandomNumberGenerator, p: Num = 0.5 -> Bool)`](#bool)
24 - [`func byte(rng: RandomNumberGenerator -> Byte)`](#byte)
25 - [`func bytes(rng: RandomNumberGenerator, count: Int -> [Byte])`](#bytes)
26 - [`func int(rng: RandomNumberGenerator, min: Int, max: Int -> Int)`](#int-int64-int32-int16-int8)
27 - [`func new(seed: [Byte] = (/dev/urandom).read_bytes(40)! -> RandomNumberGenerator)`](#new)
28 - [`func num(rng: RandomNumberGenerator, min: Num = 0.0, max: Num = 1.0 -> Num)`](#num-num32)
30 ## Usage
32 Put this in your modules.ini:
34 ```
35 [random]
36 version=v1.2
37 git=https://github.com/bruce-hill/tomo-random
38 ```
40 Then either use the default RNG (seeded from OS random sources each run):
42 ```
43 use random
45 func main()
46 >> random.int(1, 100)
48 my_rng := RandomNumberGenerator.new()
49 >> my_rng.int(1, 100)
51 my_list := ["A", "B", "C"]
52 >> my_list.random(func(lo, hi:Int64) my_rng.int64(lo, hi))
53 ```
55 -------------
57 ### `bool`
58 Generate a random boolean value with a given probability.
60 ```tomo
61 func bool(rng: RandomNumberGenerator, p: Num = 0.5 -> Bool)
62 ```
64 - `rng`: The random number generator to use.
65 - `p`: The probability of returning a `yes` value. Values less than zero and
66 `NaN` values are treated as equal to zero and values larger than zero are
67 treated as equal to one.
69 **Returns:**
70 `yes` with probability `p` and `no` with probability `1-p`.
72 **Example:**
73 ```tomo
74 >> random.bool()
75 = no
76 >> random.bool(1.0)
77 = yes
78 ```
80 ---
82 ### `byte`
83 Generate a random byte with uniform probability.
85 ```tomo
86 func byte(rng: RandomNumberGenerator -> Byte)
87 ```
89 - `rng`: The random number generator to use.
91 **Returns:**
92 A random byte (0-255).
94 **Example:**
95 ```tomo
96 >> random.byte()
97 = 103[B]
98 ```
100 ---
102 ### `bytes`
103 Generate a list of uniformly random bytes with the given length.
105 ```tomo
106 func bytes(rng: RandomNumberGenerator, count: Int -> [Byte])
107 ```
109 - `rng`: The random number generator to use.
110 - `count`: The number of random bytes to return.
112 **Returns:**
113 A list of length `count` random bytes with uniform random distribution (0-255).
115 **Example:**
116 ```tomo
117 >> random.bytes(4)
118 = [135[B], 169[B], 103[B], 212[B]]
119 ```
121 ---
123 ### `int`, `int64`, `int32`, `int16`, `int8`
124 Generate a random integer value with the given range.
126 ```tomo
127 func int(rng: RandomNumberGenerator, min: Int, max: Int -> Int)
128 func int64(rng: RandomNumberGenerator, min: Int64 = Int64.min, max: Int64 = Int64.max -> Int)
129 func int32(rng: RandomNumberGenerator, min: Int32 = Int32.min, max: Int32 = Int32.max -> Int)
130 func int16(rng: RandomNumberGenerator, min: Int16 = Int16.min, max: Int16 = Int16.max -> Int)
131 func int8(rng: RandomNumberGenerator, min: Int8 = Int8.min, max: Int8 = Int8.max -> Int)
132 ```
134 - `rng`: The random number generator to use.
135 - `min`: The minimum value to be returned.
136 - `max`: The maximum value to be returned.
138 **Returns:**
139 An integer uniformly chosen from the range `[min, max]` (inclusive). If `min`
140 is greater than `max`, an error will be raised.
142 **Example:**
143 ```tomo
144 >> random.int(1, 10)
145 = 8
146 ```
148 ---
150 ### `new`
151 Return a new random number generator.
153 ```tomo
154 func new(seed: [Byte] = (/dev/urandom).read_bytes(40)! -> RandomNumberGenerator)
155 ```
157 - `seed`: The seed use for the random number generator. A seed length of 40
158 bytes is recommended. Seed lengths of less than 40 bytes are padded with
159 zeroes.
161 **Returns:**
162 A new random number generator.
164 **Example:**
165 ```tomo
166 >> my_rng := RandomNumberGenerator.new([1[B], 2[B], 3[B], 4[B]])
167 >> my_rng.bool()
168 = yes
169 ```
171 ---
173 ### `num`, `num32`
174 Generate a random floating point value with the given range.
176 ```tomo
177 func num(rng: RandomNumberGenerator, min: Num = 0.0, max: Num = 1.0 -> Int)
178 func num32(rng: RandomNumberGenerator, min: Num = 0.0_f32, max: Num = 1.0_f32 -> Int)
179 ```
181 - `rng`: The random number generator to use.
182 - `min`: The minimum value to be returned.
183 - `max`: The maximum value to be returned.
185 **Returns:**
186 A floating point number uniformly chosen from the range `[min, max]`
187 (inclusive). If `min` is greater than `max`, an error will be raised.
189 **Example:**
190 ```tomo
191 >> random.num(1, 10)
192 = 9.512830439975572
193 ```