nx_sketch_reservoir.nx
buildroot/runtime/nx_sketch_reservoir.nx
about
sketch_reservoir.nx -- Vitter reservoir sampling + quantile.
Vitter 1985 "Random Sampling with a Reservoir." Algorithm R:
maintain a cap-element reservoir. For the i-th input value
(1-indexed):
- if i <= cap: items[i-1] = value
- else: draw j uniformly from [1, i]; if j <= cap,
items[j-1] = value (else discard)
At end of stream, items[] holds a UNIFORMLY RANDOM sample of
the input. Per-quantile estimation: sort items, look up the
floor(p * n_items)-th value. Hoeffding bound on quantile from
k samples: error ~ sqrt(ln(1/delta) / (2k)) ~ 1/sqrt(k) at fixed
delta. We declare 1/sqrt(cap) as the rank_error envelope.
OPENS TWO ROADMAP AXES SIMULTANEOUSLY:
- Sampling family (Vitter / VarOpt -- DataSketches ships both;
this is the first axis primitive)
- Quantile family (rank_error envelope; T-Digest / KLL ship
this same family with tighter bounds; reservoir is the
SIMPLEST sample-based quantile)
LCG-based PRNG for deterministic reproducibility. Per the
lossless-language discipline (doc 20): randomized sketches MUST
declare their RNG state in the typed envelope so two runs with
the same seed produce bit-identical output.
dependencies 2 imports · 0 importers
imports: nx_syscalls.nxnx_sketch_types.nx
imported by: nobody (leaf or entry point)
structs
| 45 | struct Reservoir |
consts
| 37 | const NX_RES_CAP_MIN: i64 = 4 |
| 38 | const NX_RES_CAP_MAX: i64 = 1000000 |
| 41 | const NX_RES_LCG_A: i64 = 1103515245 |
| 42 | const NX_RES_LCG_C: i64 = 12345 |
| 43 | const NX_RES_LCG_MOD: i64 = 0x7FFFFFFF |
functions
| 53 | func nx_reservoir_alloc(cap: i64, seed: i64) -> *Reservoir calls 1: sys_mmap |
| 68 | func nx_reservoir_rng_next(r: *Reservoir) -> i64 called by 1: nx_reservoir_rng_below |
| 75 | func nx_reservoir_rng_below(r: *Reservoir, n: i64) -> i64 |
| 80 | func nx_reservoir_add(r: *Reservoir, value: i64) -> i64 calls 1: nx_reservoir_rng_below |
| 97 | func nx_reservoir_sort(r: *Reservoir) -> i64 |
| 127 | func nx_reservoir_quantile(r: *Reservoir, p_milli: i64) -> i64 |
| 138 | func nx_reservoir_rank(r: *Reservoir, value: i64) -> i64 calls 1: nx_reservoir_sort |
| 165 | func nx_reservoir_rank_error_ppb(cap: i64) -> i64 called by 1: nx_reservoir_query_quantile |
| 175 | func nx_reservoir_query_quantile(r: *Reservoir, p_milli: i64) -> *ApproxI64 |
| 186 | func nx_reservoir_memory_bytes(r: *Reservoir) -> i64 |