code wiki / (root) / nx_vecmath_slerp_candidate_t181.nx

nx_vecmath_slerp_candidate_t181.nx

buildroot/runtime/nx_vecmath_slerp_candidate_t181.nx

23422 B497 linesdepth 1pulls 1 transitivereach 1 importersview sourcekind librarytopic vecmath
docsdependenciesstructsconstsfunctions

about

nx_vecmath.nx -- THE SHARED INTEGER LINEAR-ALGEBRA FOUNDATION (PG2, procgen.plan, 2026-08-24). WHY THIS EXISTS, MEASURED NOT ASSERTED: before this file the estate's entire shared math foundation was nx_itrig.nx at 1151 bytes -- it_sin4096 and it_cos4096 and nothing else. Every consumer above it re-rolled its own primitives: nx_gsplat carries gs_isqrt AND a private exp-LUT, nx_bodybench carries a private acos LUT. Three duplicate rulers for two operations. Worse, with no quaternion type nx_gsplat's gs_set_aniso had to settle for a normal-plus-tangent SURFEL where full 3D gaussian covariance needs quaternion-plus-3-axis scale -- a capability ceiling caused by a missing primitive, not by a design choice. SCALE IS DERIVED, NOT PICKED: VM_ONE = 4096 because that is already the estate's unit. nx_itrig emits fx4096 and measures angles in rad*4096; nx_vmd decodes quaternions at V_SCALE_ROT = 4096. Adopting any other scale would have made this file a converter instead of a foundation. Every other constant here is either derived from VM_ONE arithmetically or carries its derivation on its own line. COMPOSES THE INCUMBENT: sine and cosine come from nx_itrig by import. This file does NOT re-derive Taylor coefficients. VM_PI and VM_PI2 restate nx_itrig's angle constants because NishiLang const scope does not cross the import, so nx_vecmath_gate carries a tooth that FAILS if the two ever disagree -- a guarded duplicate, not a silent one. NO HEAP, NO LOCAL ARRAYS, NO ALLOCATION ANYWHERE. Every routine works in scalar locals and writes through caller-owned pointers. Two reasons, both estate law: this is hot-loop code and allocating in a hot loop is a measured defect; and the estate's only allocation idiom is sys_mmap, which a pure math lib must not need. Every routine that could alias its output with an input reads all operands into locals FIRST. ALL INTEGER. The language has no float type, so every result here is bit-exact and reproducible by construction. license_tier: ORIGINAL

dependencies 1 imports · 1 importers

nx_itrig.nx nx_vecmath_slerp_candidate_t18 nx_vecmath_slerp_gate_t181.nx

imports: nx_itrig.nx

imported by: nx_vecmath_slerp_gate_t181.nx

structs

none

consts

31const VM_ONE: i64 = 4096 // fixed-point unit. DERIVED: nx_itrig fx4096 and nx_vmd V_SCALE_ROT.
32const VM_PI: i64 = 12868 // round(PI * VM_ONE). Guarded by tooth pi-agrees-with-itrig.
33const VM_PI2: i64 = 6434 // round(PI/2 * VM_ONE)
34const VM_TAU: i64 = 25736 // 2 * VM_PI
40const VM_ATAN_KN: i64 = 9
41const VM_ATAN_KD: i64 = 32
48const VM_SLERP_PARALLEL: i64 = 4095 // VM_ONE - 1
50const VM_V3: i64 = 3
51const VM_M3: i64 = 9
105const VM_CAP_Q: i64 = 256
162const VM_F32_MANT_MASK: i64 = 8388607 // 2^23 - 1
163const VM_F32_IMPLICIT: i64 = 8388608 // 2^23
164const VM_F32_EXP_BIAS: i64 = 127
165const VM_F32_MANT_BITS: i64 = 23
166const VM_F32_EXP_MASK: i64 = 255
167const VM_F32_SHIFT_MAX: i64 = 62 // a shift at or beyond this cannot be represented in i64
469const VM_Q30:i64=1073741824
470const VM_Q30_BITS:i64=30

functions

53func vm_one() -> i64 { return VM_ONE }
54func vm_pi() -> i64 { return VM_PI }
55func vm_pi2() -> i64 { return VM_PI2 }
56func vm_tau() -> i64 { return VM_TAU }
60func vm_abs(v: i64) -> i64 { if v < 0 { return 0 - v } return v }
61func vm_sgn(v: i64) -> i64 { if v > 0 { return 1 } if v < 0 { return 0 - 1 } return 0 }
62func vm_min(a: i64, b: i64) -> i64 { if a < b { return a } return b }
63func vm_max(a: i64, b: i64) -> i64 { if a > b { return a } return b }
64func vm_clamp(v: i64, lo: i64, hi: i64) -> i64 { if v < lo { return lo } if v > hi { return hi } return v }
called by 2: vm_acosvm_asin
68func vm_isqrt(v: i64) -> i64
84func vm_sqrt_fx(v: i64) -> i64
called by 2: vm_v3_lenvm_q_len calls 1: vm_isqrt
106func vm_capsule_push(px: i64, py: i64, pz: i64,
calls 1: vm_isqrt
169func vm_f32_to_int(bits: i64, scale: i64) -> i64
187func vm_int_to_f32(v: i64, scale: i64) -> i64
203func vm_mul_fx(a: i64, b: i64) -> i64 { return a * b / VM_ONE }
204func vm_div_fx(a: i64, b: i64) -> i64 { if b == 0 { return 0 } return a * VM_ONE / b }
206func vm_sin(a: i64) -> i64 { return it_sin4096(a) }
called by 2: vm_q_from_axisvm_q_slerp calls 1: it_sin4096
207func vm_cos(a: i64) -> i64 { return it_cos4096(a) }
called by 1: vm_q_from_axis calls 1: it_cos4096
211func vm_tan(a: i64) -> i64
218func vm_atan_core(z: i64) -> i64
called by 1: vm_atan2
227func vm_atan2(y: i64, x: i64) -> i64
called by 2: vm_acosvm_asin calls 2: vm_absvm_atan_core
245func vm_acos(c0: i64) -> i64
called by 1: vm_q_slerp calls 3: vm_clampvm_isqrtvm_atan2
253func vm_asin(s0: i64) -> i64
263func vm_v3_set(o: *i64, x: i64, y: i64, z: i64) -> i64 { o[0] = x; o[1] = y; o[2] = z; return 0 }
264func vm_v3_copy(o: *i64, a: *i64) -> i64 { o[0] = a[0]; o[1] = a[1]; o[2] = a[2]; return 0 }
265func vm_v3_add(o: *i64, a: *i64, b: *i64) -> i64 { o[0] = a[0]+b[0]; o[1] = a[1]+b[1]; o[2] = a[2]+b[2]; return 0 }
266func vm_v3_sub(o: *i64, a: *i64, b: *i64) -> i64 { o[0] = a[0]-b[0]; o[1] = a[1]-b[1]; o[2] = a[2]-b[2]; return 0 }
267func vm_v3_scale(o: *i64, a: *i64, s: i64) -> i64 { o[0] = a[0]*s/VM_ONE; o[1] = a[1]*s/VM_ONE; o[2] = a[2]*s/VM_ONE; return 0 }
269func vm_v3_dot(a: *i64, b: *i64) -> i64 { return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) / VM_ONE }
272func vm_v3_cross(o: *i64, a: *i64, b: *i64) -> i64
281func vm_v3_len2(a: *i64) -> i64 { return (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]) / VM_ONE }
called by 1: vm_v3_len
282func vm_v3_len(a: *i64) -> i64 { return vm_sqrt_fx(vm_v3_len2(a)) }
286func vm_v3_norm(o: *i64, a: *i64) -> i64
calls 1: vm_v3_len
300func vm_q_ident(o: *i64) -> i64 { o[0] = 0; o[1] = 0; o[2] = 0; o[3] = VM_ONE; return 0 }
301func vm_q_copy(o: *i64, a: *i64) -> i64 { o[0]=a[0]; o[1]=a[1]; o[2]=a[2]; o[3]=a[3]; return 0 }
302func vm_q_conj(o: *i64, a: *i64) -> i64
306func vm_q_len(a: *i64) -> i64
called by 2: vm_q_normvm_q_to_m3 calls 1: vm_sqrt_fx
310func vm_q_norm(o: *i64, a: *i64) -> i64
called by 1: vm_q_slerp calls 2: vm_q_lenvm_q_ident
322func vm_q_mul(o: *i64, a: *i64, b: *i64) -> i64
333func vm_q_from_axis(o: *i64, axis: *i64, angle: i64) -> i64
349func vm_q_rotate_v3(o: *i64, q: *i64, v: *i64) -> i64
365func vm_q_slerp(o: *i64, a: *i64, b: *i64, t: i64) -> i64
389func vm_m3_ident(o: *i64) -> i64
called by 1: vm_q_to_m3
397func vm_m3_mul(o: *i64, a: *i64, b: *i64) -> i64
416func vm_m3_mulv(o: *i64, m: *i64, v: *i64) -> i64
424func vm_m3_transpose(o: *i64, m: *i64) -> i64
435func vm_q_to_m3(o: *i64, q: *i64) -> i64
459func vm_q_scale_to_m3(o: *i64, q: *i64, sx: i64, sy: i64, sz: i64) -> i64
calls 1: vm_q_to_m3
471func vm_q_norm_q30(a:*i64,out:*i64,tolerance:i64)->i64
called by 1: vm_q_slerp_q30 calls 2: vm_isqrtvm_abs
478func vm_q_slerp_q30(a:*i64,b:*i64,t:i64,tolerance:i64,out:*i64,scratch:*i64)->i64
called by 1: main calls 2: vm_q_norm_q30vm_isqrt