code wiki / (root) / nx_rope.nx

nx_rope.nx

buildroot/runtime/nx_rope.nx

9664 B269 linesdepth 5pulls 6 transitivereach 24 importersview sourcekind tool
docsdependenciesstructsconstsfunctions

about

nx_rope.nx -- Rotary Position Embeddings (Su et al. 2021). Position-encoding primitive for modern transformers. Replaces sinusoidal-absolute (Vaswani 2017) and learned-absolute encoding with a multiplicative rotation that injects RELATIVE position into attention scores. RoPE has been adopted by every modern decoder- only LLM: Llama 1/2/3, Mistral, Mixtral, Qwen, Phi-3, Gemma Z-Image / Flux / Stable Diffusion 3 attention Mamba state-space hybrid layers Per the no-skipping cardinal: composes the just-shipped `nx_trig.nx` for cos/sin and `nx_root.nx` for inverse-frequency precompute. No skipping, no inlining trig; full bits-up. ===== Math ======================================================= For a query/key vector q of dimension d (d must be even), pair adjacent dimensions (2i, 2i+1). Each pair has its own frequency theta_i = 1 / base^(2i/d) where base = 10000 (Su's published recommendation). For position m, the rotation angle for pair i is angle_{m,i} = m * theta_i radians. The 2D rotation: q'[2i] = q[2i] * cos(angle_{m,i}) - q[2i+1] * sin(angle_{m,i}) q'[2i+1] = q[2i] * sin(angle_{m,i}) + q[2i+1] * cos(angle_{m,i}) This is a 2x2 orthogonal rotation -- norm-preserving by construction. When Q'K^T is computed downstream, the dot product gains a position-dependent term that depends ONLY on the relative position (m_q - m_k), not the absolute positions. That's the key RoPE property. ===== Inverse-frequency precompute ============================== theta_i = base^(-2i/d) for i in [0, d/2). Computing base^(-2i/d) in i64 + Q10:

dependencies 5 imports · 3 importers

nx_syscalls.nx nx_tier.nx nx_loop.nx nx_root.nx nx_trig.nx nx_rope.nx nx_gguf_load_block.nx nx_gguf_load_block_test.nx nx_transformer_block.nx

imports: nx_syscalls.nxnx_tier.nxnx_loop.nxnx_root.nxnx_trig.nx

imported by: nx_gguf_load_block.nxnx_gguf_load_block_test.nxnx_transformer_block.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main sys_mmap nx_rope_compute_inv_freq nx_nth_root_q14 nx_pow_q14 nx_rope_apply_vector nx_cos_rad_q10 nx_cos_turn_q10 sys_mmap ↻ _nx_trig_reduce _nx_cos_q1_table nx_rad_to_turn_q10 nx_sin_rad_q10 nx_sin_turn_q10 nx_cos_turn_q10 ↻ nx_rad_to_turn_q10 ↻ nx_rope_verdict_is_valid

structs

none

consts

75const NX_ROPE_Q10: nx_int = 1024
76const NX_ROPE_Q14_ONE: nx_int = 16384
77const NX_ROPE_BASE: nx_int = 10000
81const NX_ROPE_OK: nx_int = 0
82const NX_ROPE_ERR_ODD_DIM: nx_int = 1
83const NX_ROPE_ERR_BAD_DIM: nx_int = 2
84const NX_ROPE_ERR_BAD_BASE: nx_int = 3
85const NX_ROPE_N_VERDICTS: nx_int = 4

functions

87func nx_rope_verdict_is_valid(v: nx_int) -> nx_int
called by 1: main
105func nx_rope_compute_inv_freq(d: nx_int, base: nx_int, out_inv_freq: *i64) -> nx_int
139func nx_rope_apply_vector(x: *i64, d: nx_int, position: nx_int,
172func nx_rope_apply_batch(x: *i64, n_tokens: nx_int, d: nx_int,
203func main() -> i64