pub fn bounded(
key: &DomainKey,
stream_id: u32,
ordinal: u64,
n: NonZeroU64,
) -> u64Expand description
A uniform-ish draw in [0, n) by 64-bit multiply-shift.
bounded(..) = ((x as u128 * n.get() as u128) >> 64) as u64, where x is
[assemble64] of the block at (key, stream_id, ordinal).
§This IS the contracted derivation
Its non-uniformity is below 2⁻⁴⁴ for every range this protocol reaches (class buckets ≤ 587 rows, pair spaces ≤ ~10⁵), and it is branch-free and index-pure. Contract assumption A3 records that as the derivation itself, not as an approximation of some exact-uniform alternative — so a future reader does not “correct” it into rejection sampling and change every sampled identity in the process.
Modulo is FORBIDDEN: its bias at the top of the range is real and, worse, unauditable — two implementations can both look correct and disagree. Float scaling is FORBIDDEN: a 23-bit mantissa cannot address a bucket beyond 2²⁴ without collisions.
§A zero bound is unrepresentable
n is a NonZeroU64, so bounded(.., 0) is a type error rather than a silent
constant or a fault:
use aprender_contrastive_data::rng::{bounded, derive_key};
let key = derive_key(13, "select/0");
let _ = bounded(&key, 0, 0, 0u64);The same call with a real bound compiles, which is what stops the block above from being green for an unrelated reason:
use core::num::NonZeroU64;
use aprender_contrastive_data::rng::{bounded, derive_key};
let key = derive_key(13, "select/0");
let one = NonZeroU64::new(1).expect("1 is not zero");
assert_eq!(bounded(&key, 0, 0, one), 0);