code wiki / _hdl_build / nx_power_iter.nx
nx_power_iter.nx source
↩ module page · 64 lines · 2679 B
1// nx_power_iter.nx -- the team's GENERAL integer power-iteration ability (the bits-up core of truncated
2// SVD, the most-urgent MISSING gap the team's own gap-scan named, toward S-class semantic retrieval).
3// Power iteration finds the DOMINANT eigenvector of a symmetric matrix: v <- M v, renormalized, repeats
4// to the top eigen-direction; the eigenvalue is the inf-norm ratio. Integer fixed-point only (scale
5// 1000), no floats -- so it runs anywhere the team deploys. This is a GENERAL ability: it reduces ANY
6// matrix (e.g. the PPMI co-occurrence gram) to a dense embedding direction; the team applies it, Claude
7// does not hand-solve instances. Triangulated against a float reference (numpy eig). license_tier: ORIGINAL
8
9import "nx_syscalls.nx"
10
11const PI_SCALE: i64 = 1000 // fixed-point scale for the eigenvector (inf-norm normalized to 1000)
12
13// out = M * v, where M is nn x nn row-major, integers.
14func pi_matvec(M: *i64, v: *i64, nn: i64, out: *i64) -> i64 {
15 var i: i64 = 0
16 while i < nn {
17 var acc: i64 = 0; var j: i64 = 0
18 while j < nn { acc = acc + M[i * nn + j] * v[j]; j = j + 1 }
19 out[i] = acc
20 i = i + 1
21 }
22 return 0
23}
24
25// the inf-norm: max |v[i]| (normalization without a sqrt -- keeps it integer + cheap).
26func pi_absmax(v: *i64, nn: i64) -> i64 {
27 var m: i64 = 0; var i: i64 = 0
28 while i < nn { var a: i64 = v[i]; if a < 0 { a = 0 - a } if a > m { m = a } i = i + 1 }
29 return m
30}
31
32// K iterations of power iteration; out = dominant eigenvector, inf-norm-scaled to PI_SCALE. (M symmetric)
33func pi_iterate(M: *i64, nn: i64, K: i64, out: *i64) -> i64 {
34 var i: i64 = 0
35 while i < nn { out[i] = PI_SCALE; i = i + 1 } // start v = [1000, 1000, ...]
36 let tmp: *i64 = sys_mmap(nn * 8 + 64) as *i64
37 var k: i64 = 0
38 while k < K {
39 pi_matvec(M, out, nn, tmp)
40 let am: i64 = pi_absmax(tmp, nn)
41 if am == 0 { k = K } else {
42 i = 0
43 while i < nn { out[i] = (tmp[i] * PI_SCALE) / am; i = i + 1 }
44 }
45 k = k + 1
46 }
47 return 0
48}
49
50// the dominant eigenvalue in milli-units: |M v|_inf / |v|_inf (v is scaled so |v|_inf = PI_SCALE).
51func pi_eigenvalue_milli(M: *i64, v: *i64, nn: i64) -> i64 {
52 let tmp: *i64 = sys_mmap(nn * 8 + 64) as *i64
53 pi_matvec(M, v, nn, tmp)
54 let mv: i64 = pi_absmax(tmp, nn)
55 let vv: i64 = pi_absmax(v, nn)
56 if vv == 0 { return 0 }
57 return (mv * PI_SCALE) / vv
58}
59
60// the ratio v[a]/v[b] in milli (the eigen-direction signature, for triangulation against a reference).
61func pi_ratio_milli(v: *i64, a: i64, b: i64) -> i64 {
62 if v[b] == 0 { return 0 }
63 return (v[a] * PI_SCALE) / v[b]
64}