Module rand

rand
Stability: Stable. The sequence a given seed produces is part of the contract — a test that pins `Rng.new(42)`'s first draws must keep passing, so the algorithm and its constants will not change under a patch release. — stable modules only change additively; this one may still change.

Non-cryptographic pseudo-random numbers — seedable, reproducible, fast (plans/STD_API_AUDIT.md §7 P0 item 7). CLEARLY SEPARATE from std/crypto/random, which is the OS entropy source: use THAT for keys, tokens and anything an adversary must not predict; use THIS for simulations, property tests, shuffles and games, where reproducibility from a seed is the point.

The generator is PCG-XSH-RR 64/32 (O'Neill, pcg-random.org) — 64-bit state, 32-bit output, period 2^64 per stream.

{ Rng, rand_range } :: import "std/rand";
rng := Rng.new(u64(42));
d6 := rng.range(i64(1) .. i64(7));   // uniform in [1, 7), reproducible
d20 := rand_range(i64(1) .. i64(21)); // the process-global generator

Stability

Stable. The sequence a given seed produces is part of the contract — a test that pins Rng.new(42)'s first draws must keep passing, so the algorithm and its constants will not change under a patch release.

Types

Rng object
Rng

Seedable PCG32 generator state.

Fields

NameTypeDescription
_st_RngState
impl(Rng, ...)
with_stream : (Rng) fn(seed : u64, stream : u64) -> Rng

A generator on an explicit stream: distinct stream values give statistically independent sequences for the same seed (the PCG initseq parameter).

Parameters

NameTypeNotes
seedu64
streamu64

Returns: Rng

new : (Rng) fn(seed : u64) -> Rng

A generator on the default stream, seeded with seed. The same seed always produces the same sequence.

Parameters

NameTypeNotes
seedu64

Returns: Rng

from_entropy : (Rng) fn() -> Rng

A generator seeded from OS entropy — unpredictable, and therefore NOT reproducible. Use new(seed) when a test needs to replay a sequence. Falls back to a fixed seed only if the platform entropy source fails, which on every supported target means the process is already doomed.

Returns: Rng

next_u32 : (Rng) fn(self : Rng) -> u32

The next 32 uniformly random bits.

Parameters

NameTypeNotes
selfRng

Returns: u32

next_u64 : (Rng) fn(self : Rng) -> u64

The next 64 uniformly random bits (two 32-bit draws).

Parameters

NameTypeNotes
selfRng

Returns: u64

next_f64 : (Rng) fn(self : Rng) -> f64

A uniform float in [0, 1) (53 bits of precision — an exact division by 2^53, not a hand-typed epsilon literal, which parsed LOW).

Parameters

NameTypeNotes
selfRng

Returns: f64

next_bool : (Rng) fn(self : Rng) -> bool

A fair coin. Reads the TOP bit, which is the best-mixed one in a PCG output word — x % 2 on the low bit is a classic weak-bit mistake.

Parameters

NameTypeNotes
selfRng

Returns: bool

next_below : (Rng) fn(self : Rng, bound : u64) -> u64

A uniform value below bound, rejection-sampled. Panics for bound == 0.

Parameters

NameTypeNotes
selfRng
boundu64

Returns: u64

range : (Rng) fn(self : Rng, r : Range(i64)) -> i64

A uniform integer in the half-open range r — write it with ..: rng.range(i64(1) .. i64(7)) for a d6. Panics if the range is empty (r.end <= r.start), like Rust's gen_range — an empty range has no value to return.

The range is a Range(i64) rather than two i64 parameters so the half-open bound is visible AT THE CALL SITE: range(1, 7) reads as either [1, 7) or [1, 7] and the caller has to remember which.

Parameters

NameTypeNotes
selfRng
rRange(i64)

Returns: i64

range_inclusive : (Rng) fn(self : Rng, r : RangeInclusive(i64)) -> i64

A uniform integer in the INCLUSIVE range rrng.range_inclusive(i64(1) ..= i64(6)). Panics if the range is empty (r.end < r.start).

A separate method rather than an overload of range: Yo has no function overloading (plans/reference/FUNCTION_OVERLOADING_POLICY.md), and the alternative — one range over a SampleRange-style trait — would put a trait on the public surface to save one word at the call site.

Parameters

NameTypeNotes
selfRng
rRangeInclusive(i64)

Returns: i64

shuffle : (Rng) fn(generic(T) self : Rng, xs : ArrayList(T)) -> unit

Fisher–Yates shuffle, in place.

Parameters

NameTypeNotes
selfRng
xsArrayList(T)

Returns: unit

choice : (Rng) fn(generic(T) self : Rng, xs : ArrayList(T)) -> Option(T)

A uniformly chosen element, or .None for an empty list.

Parameters

NameTypeNotes
selfRng
xsArrayList(T)

Returns: Option(T)

Functions

rand_u32 function
fn() -> u32

32 uniformly random bits from the process-global generator.

Returns: u32

rand_u64 function
fn() -> u64

64 uniformly random bits from the process-global generator.

Returns: u64

rand_f64 function
fn() -> f64

A uniform float in [0, 1) from the process-global generator.

Returns: f64

rand_bool function
fn() -> bool

A fair coin from the process-global generator.

Returns: bool

rand_below function
fn(bound : u64) -> u64

A uniform value below bound from the process-global generator, rejection-sampled. Panics for bound == 0.

Parameters

NameTypeNotes
boundu64

Returns: u64

rand_range function
fn(r : Range(i64)) -> i64

A uniform integer in the half-open range r, from the process-global generator — rand_range(i64(1) .. i64(7)). Panics on an empty range.

Parameters

NameTypeNotes
rRange(i64)

Returns: i64

fn(r : RangeInclusive(i64)) -> i64

A uniform integer in the INCLUSIVE range r, from the process-global generator — rand_range_inclusive(i64(1) ..= i64(6)). Panics on an empty range.

Parameters

NameTypeNotes
rRangeInclusive(i64)

Returns: i64