aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-11-03 22:37:48 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-11-03 22:37:48 -0500
commitfc9a6f1416be514e9d26b301d05e7e347560560b (patch)
tree7d61cc3657c36dde05135f17dbf5923cff177abf /docs
parent52e3d3fe6f2c3e5051affe155fed364d1a5d623c (diff)
Add RNGs to the language
Diffstat (limited to 'docs')
-rw-r--r--docs/README.md1
-rw-r--r--docs/arrays.md12
-rw-r--r--docs/booleans.md24
-rw-r--r--docs/bytes.md25
-rw-r--r--docs/functions.md2
-rw-r--r--docs/integers.md26
-rw-r--r--docs/nums.md24
-rw-r--r--docs/rng.md248
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))
+```