code wiki / (root) / sketch_freq_directions.nx

sketch_freq_directions.nx

buildroot/runtime/sketch_freq_directions.nx

14195 B463 linesdepth 4pulls 6 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 3 imports · 3 importers

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

imports: syscalls.nxsketch_types.nxnx_vecmath.nx

imported by: nx_lowrank_kv_gate.nxsketch_freq_directions_test.nxsketch_freq_directions_vs_topnorm_bench.nx

structs

59struct FreqDir

consts

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

functions

73func nx_fd_alloc(l: i64, d: i64) -> *FreqDir
105func nx_fd_isqrt(x: i64) -> i64 { return vm_isqrt(x) }
107func nx_fd_abs(x: i64) -> i64
114func nx_fd_b_get(fd: *FreqDir, r: i64, c: i64) -> i64
118func nx_fd_b_set(fd: *FreqDir, r: i64, c: i64, v: i64) -> i64
123func nx_fd_row_norm_sq(fd: *FreqDir, r: i64) -> i64
134func nx_fd_empty_row_index(fd: *FreqDir) -> i64
149func nx_fd_dot(a: *i64, b: *i64, n: i64) -> i64
159func nx_fd_vnorm_sq(v: *i64, n: i64) -> i64
163func nx_fd_vscale(v: *i64, n: i64, factor_q14: i64) -> i64
172func nx_fd_vsub_scaled(target: *i64, source: *i64, n: i64, factor_q14: i64) -> i64
181func nx_fd_vnormalize(v: *i64, n: i64) -> i64
198func nx_fd_matvec_Bv(fd: *FreqDir, v: *i64, out: *i64) -> i64
213func nx_fd_matvec_Btw(fd: *FreqDir, w: *i64, out: *i64) -> i64
234func nx_fd_basis_get(fd: *FreqDir, idx: i64, c: i64) -> i64
238func nx_fd_basis_set(fd: *FreqDir, idx: i64, c: i64, v: i64) -> i64
244func nx_fd_deflate(fd: *FreqDir, v: *i64, found: i64) -> i64
268func nx_fd_power_one(fd: *FreqDir, found_idx: i64, init_idx: i64) -> i64
341func nx_fd_shrink(fd: *FreqDir) -> i64
378func nx_fd_add_row(fd: *FreqDir, row: *i64, n: i64) -> i64
421func nx_fd_top_sigma_sq(fd: *FreqDir) -> i64
435func nx_fd_total_rows(fd: *FreqDir) -> i64
439func nx_fd_memory_bytes(fd: *FreqDir) -> i64
450func nx_fd_rel_err_ppb(l: i64) -> i64
456func nx_fd_query_top(fd: *FreqDir) -> *ApproxI64