WAM (wam v0.2.0)
Copy MarkdownWalker's Alias Method for weighted random sampling in O(1).
The probability table
probs[i] is the probability of keeping bucket i, so a draw reads
if rng < probs[i], do: i, else: aliases[i]with rng expected in [0, 1).
This orientation is what makes a weight of 0 unreachable by construction
rather than merely improbable. A zero-weight atom is always paired away, so its
probs entry is exactly 0.0, and rng < 0.0 is false for any rng >= 0 —
the guarantee holds whatever the generator's upper bound turns out to be and
whatever a caller passes. Code that mutes content by giving it a weight of 0
can rely on that.
Reading a slot without drawing is at/3, not get/4 with a sentinel rng.
Summary
Functions
Reads the value stored at index, without drawing.
Types
@type t() :: %WAM{ aliases: tuple(), probs: tuple(), size: non_neg_integer(), values: tuple() }
Functions
@spec at(t(), non_neg_integer(), term()) :: term()
@spec fetch(t(), non_neg_integer(), float()) :: {:ok, term()} | {:error, :invalid_index}
@spec fetch_at(t(), non_neg_integer()) :: {:ok, term()} | {:error, :invalid_index}
Reads the value stored at index, without drawing.
Use this instead of calling get/4 with an rng chosen to defeat the alias —
that trick depends on how probs is oriented and breaks silently when it changes.
@spec get(t(), non_neg_integer(), float(), term()) :: term()
@spec index(t(), non_neg_integer(), float()) :: {:ok, non_neg_integer()} | {:error, :invalid_index}