rlx_ir/ops/
axial_rope2d.rs1use crate::{Graph, NodeId, Op};
8
9pub fn apply_axial_rope2d(
11 x: &[f32],
12 num_heads: usize,
13 n_tokens: usize,
14 head_dim: usize,
15 end_x: usize,
16 end_y: usize,
17 theta: f32,
18 repeat_factor: usize,
19) -> Vec<f32> {
20 debug_assert!(head_dim.is_multiple_of(4));
21 let half = head_dim / 2;
22 let q4 = head_dim / 4;
23 let spatial = end_x * end_y;
24 let repeat = repeat_factor.max(1);
25 debug_assert_eq!(n_tokens, spatial * repeat);
26
27 let mut freqs = vec![0f32; q4];
28 for i in 0..q4 {
29 freqs[i] = 1.0 / theta.powf((4 * i) as f32 / head_dim as f32);
30 }
31 let mut cs_x = vec![0f32; spatial * q4];
32 let mut sn_x = vec![0f32; spatial * q4];
33 let mut cs_y = vec![0f32; spatial * q4];
34 let mut sn_y = vec![0f32; spatial * q4];
35 for pos in 0..spatial {
36 let tx = (pos % end_x) as f32;
37 let ty = (pos / end_x) as f32;
38 for c in 0..q4 {
39 let ax = tx * freqs[c];
40 let ay = ty * freqs[c];
41 cs_x[pos * q4 + c] = ax.cos();
42 sn_x[pos * q4 + c] = ax.sin();
43 cs_y[pos * q4 + c] = ay.cos();
44 sn_y[pos * q4 + c] = ay.sin();
45 }
46 }
47 let mut cos_x = vec![0f32; n_tokens * q4];
48 let mut sin_x = vec![0f32; n_tokens * q4];
49 let mut cos_y = vec![0f32; n_tokens * q4];
50 let mut sin_y = vec![0f32; n_tokens * q4];
51 for tok in 0..n_tokens {
52 let pos = tok / repeat;
53 for c in 0..q4 {
54 cos_x[tok * q4 + c] = cs_x[pos * q4 + c];
55 sin_x[tok * q4 + c] = sn_x[pos * q4 + c];
56 cos_y[tok * q4 + c] = cs_y[pos * q4 + c];
57 sin_y[tok * q4 + c] = sn_y[pos * q4 + c];
58 }
59 }
60
61 let hs = num_heads * head_dim;
63 let mut out = x.to_vec();
64 for tok in 0..n_tokens {
65 for h in 0..num_heads {
66 let base = tok * hs + h * head_dim;
67 for c in 0..q4 {
68 let ix0 = base + 2 * c;
69 let ix1 = base + 2 * c + 1;
70 let x0 = out[ix0];
71 let x1 = out[ix1];
72 let co = cos_x[tok * q4 + c];
73 let si = sin_x[tok * q4 + c];
74 out[ix0] = x0 * co - x1 * si;
75 out[ix1] = x0 * si + x1 * co;
76 }
77 for c in 0..q4 {
78 let ix0 = base + half + 2 * c;
79 let ix1 = base + half + 2 * c + 1;
80 let x0 = out[ix0];
81 let x1 = out[ix1];
82 let co = cos_y[tok * q4 + c];
83 let si = sin_y[tok * q4 + c];
84 out[ix0] = x0 * co - x1 * si;
85 out[ix1] = x0 * si + x1 * co;
86 }
87 }
88 }
89 out
90}
91
92impl Graph {
93 pub fn axial_rope2d(
95 &mut self,
96 x: NodeId,
97 end_x: usize,
98 end_y: usize,
99 head_dim: usize,
100 num_heads: usize,
101 theta: f32,
102 repeat_factor: usize,
103 ) -> NodeId {
104 let s = crate::shape::unary_shape(self.shape(x));
105 self.push(
106 Op::AxialRope2d {
107 end_x,
108 end_y,
109 head_dim,
110 num_heads,
111 theta,
112 repeat_factor,
113 },
114 vec![x],
115 s,
116 None,
117 )
118 }
119}