code wiki / (root) / nx_logadd_lib.nx

nx_logadd_lib.nx

buildroot/runtime/nx_logadd_lib.nx

5160 B103 linesdepth 3pulls 3 transitivereach 4 importersview sourcekind library
docsdependenciesstructsconstsfunctions

about

nx_logadd_lib.nx -- FIXED-POINT LOG-DOMAIN ARITHMETIC, no floats anywhere: the primitive a linear-chain CRF's forward-backward pass needs (log-sum-exp) and the probability it reads back (exp of a non-positive log-domain value). Scale LA_S = 1024 units per nat (Q10). la_lse(a, b) = ln(e^a + e^b) in Q10; la_exp_neg(x), x <= 0 -> a Q10 probability. The two tables are built ONCE from first principles rather than typed: e^(-1/S) in Q30 from its Taylor series (the third term is already below one unit at this scale, so the constant is exact to the last bit), the powers e^(-d/S) by recurrence, and softplus(d) = S*ln(1 + e^(-d/S)) through the estate's ONE integer logarithm (nx_intlog ilog2_1024) -- composed, never re-implemented. The horizon LA past which softplus rounds to zero is DERIVED at init by scanning the table, never declared. Minus infinity is LA_NEG_INF, the same sentinel the aspect model's Viterbi already uses, so a masked transition reads identically in both decoders. license_tier: ORIGINAL No hw writes (Rule 26). LIB.

dependencies 2 imports · 2 importers

nx_syscalls.nx nx_intlog.nx nx_logadd_lib.nx nx_absa_seq.nx nx_logadd_gate.nx

imports: nx_syscalls.nxnx_intlog.nx

imported by: nx_absa_seq.nxnx_logadd_gate.nx

structs

none

consts

13const LA_S: i64 = 1024 // Q10: units per nat
14const LA_Q30: i64 = 1073741824 // 2^30, the exp table's unit
15const LA_Q30_SHIFT: i64 = 30
16const LA_Q30_HALF: i64 = 536870912 // rounding half for a Q30 product
17const LA_Q20_SHIFT: i64 = 20
18const LA_Q20_HALF: i64 = 524288
19const LA_LN2_Q20: i64 = 726817 // ln 2 in Q20 (0.6931471806 * 2^20 = 726,817.0), turns a Q10 log2 into a Q10 ln
20const LA_LOG2_Q30_Q10: i64 = 30720 // ilog2_1024(2^30) = 30 * 1024: subtracted so ln(1+p) reads from a Q30 (1+p)
21const LA_NEG_INF: i64 = 0 - 1000000000 // log-domain minus infinity (== SP_NEG in nx_absa_seq)
22const LA_NEG_INF_GUARD: i64 = 0 - 500000000 // anything at or below this is treated as minus infinity (an -inf plus a finite)
23const LA_TABLE_CAP: i64 = 16384 // table entries; the derived horizon is ~S*ln(2S), a little under half of this
24const LA_I64_BYTES: i64 = 8
25const LA_TAYLOR_TERMS: i64 = 6 // terms of e^(-1/S) at Q30: the 3rd is already < 1 unit, six is exact by any measure

functions

34func la_exp_unit_q30() -> i64
called by 2: mainla_init
46func la_init() -> i64
77func la_horizon() -> i64 { return la_horizon_v }
called by 1: main
78func la_clamp_count() -> i64 { return la_clamps }
called by 1: main
79func la_is_neg_inf(x: i64) -> i64 { if x <= LA_NEG_INF_GUARD { return 1 } return 0 }
called by 2: sp_crf_fbla_lse
81func la_lse(a: i64, b: i64) -> i64
called by 2: sp_crf_fbmain calls 1: la_is_neg_inf
91func la_exp_neg(x: i64) -> i64
called by 2: sp_crf_fbmain
98func la_exp_neg_q30(x: i64) -> i64
called by 1: main