code wiki / (root) / sketch_freq_directions.nx

sketch_freq_directions.nx

buildroot/runtime/sketch_freq_directions.nx

14489 B477 linesdepth 4pulls 4 transitivereach 3 importersview sourcekind sketch/demotopic sketch
docsdependenciesstructsconstsfunctions

about

sketch_freq_directions.nx -- Liberty 2013 Frequent Directions sketch. Streaming low-rank matrix approximation. Given a stream of input rows in R^d, maintain a sketch matrix B in R^(l x d) (l << n) such that B^T B approximates A^T A to within an additive error bound based on the tail singular values: || A^T A - B^T B ||_F <= || A - A_k ||_F^2 / (l - k) where A_k is the best rank-k approximation of A. Direct matrix-valued analog of Misra-Gries frequency counting (Liberty's own framing in the 2013 STOC paper). ALGORITHM: For each input row x in R^d: 1. If any row of B is "empty" (all zeros) -> copy x into it. 2. Else -> shrink: a. Compute SVD: B = U Σ V^T b. delta := σ_l^2 (smallest singular value squared) c. Shrunk singular values: σ_i'^2 := max(0, σ_i^2 - delta) d. B := diag(sqrt(σ_i'^2)) V^T -- by construction the last row has σ_l' = 0 (empty) e. Copy x into the now-empty row. SVD WITHOUT f64 (the technical chokepoint -- see queued roadmap 2026-05-10): This reference impl uses POWER ITERATION with DEFLATION in Q14 fixed-point. Bounded to l <= 4, d <= 8 for this version -- convergence guarantee at small sizes is reliable; for larger matrices the accumulated round-off in Q14 degrades the shrink quality. v2 will swap in fixed-point Jacobi or bidiagonal + QR for arbitrary size. MATURITY = REFERENCE_IMPL with EXPLICIT size limits. Substrate callers requesting larger l or d get NX_FD_ERR_TOO_BIG at alloc. COMPOSITION: - Complements sketch_kmeans1d (clustering family) for streaming dimensionality reduction before clustering. - Complements sketch_correlation for streaming low-rank

dependencies 2 imports · 3 importers

syscalls.nx sketch_types.nx sketch_freq_directions.nx nx_lowrank_kv_gate.nx sketch_freq_directions_test.nx sketch_freq_directions_vs_topnorm_

imports: syscalls.nxsketch_types.nx

imported by: nx_lowrank_kv_gate.nxsketch_freq_directions_test.nxsketch_freq_directions_vs_topnorm_bench.nx

structs

58struct FreqDir

consts

48const NX_FD_Q14: i64 = 16384
49const NX_FD_L_MAX: i64 = 4
50const NX_FD_D_MAX: i64 = 8
51const NX_FD_POWER_ITERS: i64 = 32
52const NX_FD_POWER_TOL_Q14: i64 = 1 // 1/16384 ~ 6e-5 convergence
54const NX_FD_OK: i64 = 0
55const NX_FD_ERR_TOO_BIG: i64 = -1
56const NX_FD_ERR_DIM_MISMATCH: i64 = -2

functions

72func nx_fd_alloc(l: i64, d: i64) -> *FreqDir
called by 3: kv_run_casemainmain
104func nx_fd_isqrt(x: i64) -> i64
121func nx_fd_abs(x: i64) -> i64
called by 1: nx_fd_power_one
128func nx_fd_b_get(fd: *FreqDir, r: i64, c: i64) -> i64
132func nx_fd_b_set(fd: *FreqDir, r: i64, c: i64, v: i64) -> i64
137func nx_fd_row_norm_sq(fd: *FreqDir, r: i64) -> i64
148func nx_fd_empty_row_index(fd: *FreqDir) -> i64
called by 2: nx_fd_add_rowmain calls 1: nx_fd_row_norm_sq
163func nx_fd_dot(a: *i64, b: *i64, n: i64) -> i64
called by 1: nx_fd_vnorm_sq
173func nx_fd_vnorm_sq(v: *i64, n: i64) -> i64
177func nx_fd_vscale(v: *i64, n: i64, factor_q14: i64) -> i64
called by 1: nx_fd_vnormalize
186func nx_fd_vsub_scaled(target: *i64, source: *i64, n: i64, factor_q14: i64) -> i64
195func nx_fd_vnormalize(v: *i64, n: i64) -> i64
212func nx_fd_matvec_Bv(fd: *FreqDir, v: *i64, out: *i64) -> i64
called by 1: nx_fd_power_one calls 1: nx_fd_b_get
227func nx_fd_matvec_Btw(fd: *FreqDir, w: *i64, out: *i64) -> i64
called by 1: nx_fd_power_one calls 1: nx_fd_b_get
248func nx_fd_basis_get(fd: *FreqDir, idx: i64, c: i64) -> i64
252func nx_fd_basis_set(fd: *FreqDir, idx: i64, c: i64, v: i64) -> i64
called by 1: nx_fd_power_one
258func nx_fd_deflate(fd: *FreqDir, v: *i64, found: i64) -> i64
called by 1: nx_fd_power_one calls 1: nx_fd_basis_get
282func nx_fd_power_one(fd: *FreqDir, found_idx: i64, init_idx: i64) -> i64
355func nx_fd_shrink(fd: *FreqDir) -> i64
392func nx_fd_add_row(fd: *FreqDir, row: *i64, n: i64) -> i64
435func nx_fd_top_sigma_sq(fd: *FreqDir) -> i64
449func nx_fd_total_rows(fd: *FreqDir) -> i64
called by 1: main
453func nx_fd_memory_bytes(fd: *FreqDir) -> i64
464func nx_fd_rel_err_ppb(l: i64) -> i64
called by 1: nx_fd_query_top
470func nx_fd_query_top(fd: *FreqDir) -> *ApproxI64