diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2024-11-03 22:37:48 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2024-11-03 22:37:48 -0500 |
| commit | fc9a6f1416be514e9d26b301d05e7e347560560b (patch) | |
| tree | 7d61cc3657c36dde05135f17dbf5923cff177abf /docs | |
| parent | 52e3d3fe6f2c3e5051affe155fed364d1a5d623c (diff) | |
Add RNGs to the language
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/README.md | 1 | ||||
| -rw-r--r-- | docs/arrays.md | 12 | ||||
| -rw-r--r-- | docs/booleans.md | 24 | ||||
| -rw-r--r-- | docs/bytes.md | 25 | ||||
| -rw-r--r-- | docs/functions.md | 2 | ||||
| -rw-r--r-- | docs/integers.md | 26 | ||||
| -rw-r--r-- | docs/nums.md | 24 | ||||
| -rw-r--r-- | docs/rng.md | 248 |
8 files changed, 259 insertions, 103 deletions
diff --git a/docs/README.md b/docs/README.md index 1f636bc2..6d3567df 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,6 +29,7 @@ Information about Tomo's built-in types can be found here: - [Integers](integers.md) - [Languages](langs.md) - [Paths](paths.md) +- [Random Number Generators](rng.md) - [Sets](sets.md) - [Structs](structs.md) - [Tables](tables.md) diff --git a/docs/arrays.md b/docs/arrays.md index ee28cf3b..144bcd77 100644 --- a/docs/arrays.md +++ b/docs/arrays.md @@ -614,12 +614,13 @@ Selects a random element from the array. **Signature:** ```tomo -func random(arr: [T] -> T) +func random(arr: [T], rng: RNG = random -> T) ``` **Parameters:** - `arr`: The array from which to select a random element. +- `rng`: The [random number generator](rng.md) to use. **Returns:** A random element from the array. @@ -731,7 +732,7 @@ probabilities. **Signature:** ```tomo -func sample(arr: [T], count: Int, weights: [Num]? = ![Num] -> [T]) +func sample(arr: [T], count: Int, weights: [Num]? = ![Num], rng: RNG = random -> [T]) ``` **Parameters:** @@ -742,6 +743,7 @@ func sample(arr: [T], count: Int, weights: [Num]? = ![Num] -> [T]) values do not need to add up to any particular number, they are relative weights. If no weights are given, elements will be sampled with uniform probability. +- `rng`: The [random number generator](rng.md) to use. **Errors:** Errors will be raised if any of the following conditions occurs: @@ -769,12 +771,13 @@ Shuffles the elements of the array in place. **Signature:** ```tomo -func shuffle(arr: @[T] -> Void) +func shuffle(arr: @[T], rng: RNG = random -> Void) ``` **Parameters:** - `arr`: The mutable reference to the array to be shuffled. +- `rng`: The [random number generator](rng.md) to use. **Returns:** Nothing. @@ -793,12 +796,13 @@ Creates a new array with elements shuffled. **Signature:** ```tomo -func shuffled(arr: [T] -> [T]) +func shuffled(arr: [T], rng: RNG = random -> [T]) ``` **Parameters:** - `arr`: The array to be shuffled. +- `rng`: The [random number generator](rng.md) to use. **Returns:** A new array with shuffled elements. diff --git a/docs/booleans.md b/docs/booleans.md index 5610d863..4f44931a 100644 --- a/docs/booleans.md +++ b/docs/booleans.md @@ -35,27 +35,3 @@ func from_text(text: Text -> Bool?) >> Bool.from_text("???") = !Bool ``` - ---- - -## `random` - -**Description:** -Generates a random boolean value based on a specified probability. - -**Signature:** -```tomo -func random(p: Float = 0.5 -> Bool) -``` - -**Parameters:** - -- `p`: The probability (between `0` and `1`) of returning `yes`. Default is `0.5`. - -**Returns:** -`yes` with probability `p`, and `no` with probability `1 - p`. - -**Example:** -```tomo ->> Bool.random(70%) // yes (with 70% probability) -``` diff --git a/docs/bytes.md b/docs/bytes.md index eb733424..0b618339 100644 --- a/docs/bytes.md +++ b/docs/bytes.md @@ -9,27 +9,4 @@ integer with a `[B]` suffix, e.g. `255[B]`. # Byte Methods -## `random` - -**Description:** -Generates a random byte value in the specified range. - -**Signature:** -```tomo -func random(min: Byte = Byte.min, max: Byte = Byte.max -> Byte) -``` - -**Parameters:** - -- `min`: The minimum value to generate (inclusive). -- `max`: The maximum value to generate (inclusive). - -**Returns:** -A random byte chosen with uniform probability from within the given range -(inclusive). If `min` is greater than `max`, an error will be raised. - -**Example:** -```tomo ->> Byte.random() -= 42[B] -``` +None. diff --git a/docs/functions.md b/docs/functions.md index 174ad23a..05d84e4a 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -35,7 +35,7 @@ callsite: ``` **Note:** Default arguments are re-evaluated at the callsite for each function -call, so if your default argument is `func foo(x=Int.random(1,10) -> Int)`, then +call, so if your default argument is `func foo(x=random:int(1,10) -> Int)`, then each time you call the function without an `x` argument, it will give you a new random number. diff --git a/docs/integers.md b/docs/integers.md index 1c30aee0..5b29d5a8 100644 --- a/docs/integers.md +++ b/docs/integers.md @@ -112,32 +112,6 @@ The octal string representation of the integer. --- -## `random` - -**Description:** -Generates a random integer between the specified minimum and maximum values. - -**Signature:** -```tomo -func random(min: Int, max: Int -> Int) -``` - -**Parameters:** - -- `min`: The minimum value of the range. -- `max`: The maximum value of the range. - -**Returns:** -A random integer between `min` and `max` (inclusive). - -**Example:** -```tomo ->> Int.random(1, 100) -= 47 -``` - ---- - ## `from_text` **Description:** diff --git a/docs/nums.md b/docs/nums.md index 9072f86a..5f9b5285 100644 --- a/docs/nums.md +++ b/docs/nums.md @@ -991,30 +991,6 @@ The next representable value after `x` in the direction of `y`. --- -### `random` - -**Description:** -Generates a random floating-point number. - -**Signature:** -```tomo -func random(->Num) -``` - -**Parameters:** -None - -**Returns:** -A random floating-point number between 0 and 1. - -**Example:** -```tomo ->> Num.random() -= 0.4521 -``` - ---- - ### `rint` **Description:** diff --git a/docs/rng.md b/docs/rng.md new file mode 100644 index 00000000..9d1c94d3 --- /dev/null +++ b/docs/rng.md @@ -0,0 +1,248 @@ +# Random Number Generators (RNG) + +Tomo comes with an `RNG` type (Random Number Generator). 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,](https://en.wikipedia.org/wiki/Salsa20#ChaCha_variant) inspired by +[`arc4random` in OpenBSD.](https://man.openbsd.org/arc4random.3) + +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. +[Arrays](arrays.md) also have some methods which use RNG values: +`array:shuffle()`, `array:shuffled()`, `array:random()`, and `array:sample()`. + +## `bool` + +**Description:** +Generate a random boolean value with a given probability. + +**Signature:** +```tomo +func bool(rng: RNG, p: Num = 0.5 -> Bool) +``` + +**Parameters:** + +- `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:** +```tomo +>> random:bool() += no +>> random:bool(1.0) += yes +``` + +--- + +## `byte` + +**Description:** +Generate a random byte with uniform probability. + +**Signature:** +```tomo +func byte(rng: RNG -> Byte) +``` + +**Parameters:** + +- `rng`: The random number generator to use. + +**Returns:** +A random byte (0-255). + +**Example:** +```tomo +>> random:byte() += 103[B] +``` + +--- + +## `bytes` + +**Description:** +Generate an array of uniformly random bytes with the given length. + +**Signature:** +```tomo +func bytes(rng: RNG, count: Int -> [Byte]) +``` + +**Parameters:** + +- `rng`: The random number generator to use. +- `count`: The number of random bytes to return. + +**Returns:** +An array of length `count` random bytes with uniform random distribution (0-255). + +**Example:** +```tomo +>> random:bytes(4) += [135[B], 169[B], 103[B], 212[B]] +``` + +--- + +## `copy` + +**Description:** +Return a copy of a random number generator. This copy will be a parallel version of +the given RNG with its own internal state. + +**Signature:** +```tomo +func copy(rng: RNG -> RNG) +``` + +**Parameters:** + +- `rng`: The random number generator to copy. + +**Returns:** +A copy of the given RNG. + +**Example:** +```tomo +>> rng := RNG.new([:Byte]) +>> copy := rng:copy() + +>> rng:bytes(10) += [224[B], 102[B], 190[B], 59[B], 251[B], 50[B], 217[B], 170[B], 15[B], 221[B]] + +# The copy runs in parallel to the original RNG: +>> copy:bytes(10) += [224[B], 102[B], 190[B], 59[B], 251[B], 50[B], 217[B], 170[B], 15[B], 221[B]] +``` + +--- + +## `int`, `int64`, `int32`, `int16`, `int8` + +**Description:** +Generate a random integer value with the given range. + +**Signature:** +```tomo +func int(rng: RNG, min: Int, max: Int -> Int) +func int64(rng: RNG, min: Int64 = Int64.min, max: Int64 = Int64.max -> Int) +func int32(rng: RNG, min: Int32 = Int32.min, max: Int32 = Int32.max -> Int) +func int16(rng: RNG, min: Int16 = Int16.min, max: Int16 = Int16.max -> Int) +func int8(rng: RNG, min: Int8 = Int8.min, max: Int8 = Int8.max -> Int) +``` + +**Parameters:** + +- `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:** +```tomo +>> random:int(1, 10) += 8 +``` + +--- + +## `new` + +**Description:** +Return a new random number generator. + +**Signature:** +```tomo +func new(seed: [Byte] = (/dev/urandom):read_bytes(40) -> RNG) +``` + +**Parameters:** + +- `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:** +```tomo +>> my_rng := RNG.new([1[B], 2[B], 3[B], 4[B]]) +>> my_rng:bool() += yes +``` + +--- + +## `num`, `num32` + +**Description:** +Generate a random floating point value with the given range. + +**Signature:** +```tomo +func num(rng: RNG, min: Num = 0.0, max: Num = 1.0 -> Int) +func num32(rng: RNG, min: Num = 0.0_f32, max: Num = 1.0_f32 -> Int) +``` + +**Parameters:** + +- `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:** +```tomo +>> random:num(1, 10) += 9.512830439975572 +``` + +--- + +## `set_seed` + +**Description:** +Set the seed for an RNG. + +**Signature:** +```tomo +func set_seed(rng: RNG, seed: [Byte]) +``` + +**Parameters:** + +- `rng`: The random number generator to modify. +- `seed`: A new seed to re-seed the random number generator with. A seed length + of 40 bytes is recommended. Seed lengths of less than 40 bytes are padded + with zeroes. + +**Returns:** +Nothing. + +**Example:** +```tomo +random:set_seed((/dev/urandom):read_bytes(40)) +``` |
