1pub fn matmul_f32(
4 lhs: &[f32],
5 rhs: &[f32],
6 rows: usize,
7 columns: usize,
8 reduction: usize,
9 lhs_row_stride: usize,
10 rhs_row_stride: usize,
11 transpose_lhs: bool,
12 transpose_rhs: bool,
13) -> Vec<f32> {
14 let mut out = vec![0.0f32; rows * columns];
15 for row in 0..rows {
16 for column in 0..columns {
17 let mut sum = 0.0f32;
18 for k in 0..reduction {
19 let lhs_index = if transpose_lhs {
20 k * lhs_row_stride + row
21 } else {
22 row * lhs_row_stride + k
23 };
24 let rhs_index = if transpose_rhs {
25 column * rhs_row_stride + k
26 } else {
27 k * rhs_row_stride + column
28 };
29 sum += lhs[lhs_index] * rhs[rhs_index];
30 }
31 out[row * columns + column] = sum;
32 }
33 }
34 out
35}
36
37pub fn matmul_f64(
38 lhs: &[f64],
39 rhs: &[f64],
40 rows: usize,
41 columns: usize,
42 reduction: usize,
43 lhs_row_stride: usize,
44 rhs_row_stride: usize,
45 transpose_lhs: bool,
46 transpose_rhs: bool,
47) -> Vec<f64> {
48 let mut out = vec![0.0f64; rows * columns];
49 for row in 0..rows {
50 for column in 0..columns {
51 let mut sum = 0.0f64;
52 for k in 0..reduction {
53 let lhs_index = if transpose_lhs {
54 k * lhs_row_stride + row
55 } else {
56 row * lhs_row_stride + k
57 };
58 let rhs_index = if transpose_rhs {
59 column * rhs_row_stride + k
60 } else {
61 k * rhs_row_stride + column
62 };
63 sum += lhs[lhs_index] * rhs[rhs_index];
64 }
65 out[row * columns + column] = sum;
66 }
67 }
68 out
69}
70
71pub fn bmm_f32(
72 lhs: &[f32],
73 rhs: &[f32],
74 batch: usize,
75 rows: usize,
76 columns: usize,
77 reduction: usize,
78 lhs_batch_stride: usize,
79 lhs_row_stride: usize,
80 rhs_batch_stride: usize,
81 rhs_row_stride: usize,
82 transpose_lhs: bool,
83 transpose_rhs: bool,
84) -> Vec<f32> {
85 let mut out = vec![0.0f32; batch * rows * columns];
86 for batch_index in 0..batch {
87 for row in 0..rows {
88 for column in 0..columns {
89 let mut sum = 0.0f32;
90 for k in 0..reduction {
91 let lhs_index = if transpose_lhs {
92 batch_index * lhs_batch_stride + k * lhs_row_stride + row
93 } else {
94 batch_index * lhs_batch_stride + row * lhs_row_stride + k
95 };
96 let rhs_index = if transpose_rhs {
97 batch_index * rhs_batch_stride + column * rhs_row_stride + k
98 } else {
99 batch_index * rhs_batch_stride + k * rhs_row_stride + column
100 };
101 sum += lhs[lhs_index] * rhs[rhs_index];
102 }
103 out[batch_index * rows * columns + row * columns + column] = sum;
104 }
105 }
106 }
107 out
108}
109
110pub fn masked_bmm_f32(
111 lhs: &[f32],
112 rhs: &[f32],
113 initial_out: &[f32],
114 masked_rows: &[i32],
115 batch: usize,
116 rows: usize,
117 columns: usize,
118 reduction: usize,
119 lhs_batch_stride: usize,
120 lhs_row_stride: usize,
121 rhs_batch_stride: usize,
122 rhs_row_stride: usize,
123 transpose_lhs: bool,
124 transpose_rhs: bool,
125) -> Vec<f32> {
126 let mut out = initial_out.to_vec();
127 for batch_index in 0..batch {
128 let valid_rows = masked_rows[batch_index].clamp(0, rows as i32) as usize;
129 for row in 0..valid_rows {
130 for column in 0..columns {
131 let mut sum = 0.0f32;
132 for k in 0..reduction {
133 let lhs_index = if transpose_lhs {
134 batch_index * lhs_batch_stride + k * lhs_row_stride + row
135 } else {
136 batch_index * lhs_batch_stride + row * lhs_row_stride + k
137 };
138 let rhs_index = if transpose_rhs {
139 batch_index * rhs_batch_stride + column * rhs_row_stride + k
140 } else {
141 batch_index * rhs_batch_stride + k * rhs_row_stride + column
142 };
143 sum += lhs[lhs_index] * rhs[rhs_index];
144 }
145 out[batch_index * rows * columns + row * columns + column] = sum;
146 }
147 }
148 }
149 out
150}
151
152pub fn ragged_bmm_f32(
153 lhs: &[f32],
154 rhs: &[f32],
155 row_indptr: &[i32],
156 batch: usize,
157 total_rows: usize,
158 columns: usize,
159 reduction: usize,
160 lhs_row_stride: usize,
161 rhs_batch_stride: usize,
162 rhs_row_stride: usize,
163 transpose_lhs: bool,
164 transpose_rhs: bool,
165) -> Vec<f32> {
166 let mut out = vec![0.0f32; total_rows * columns];
167 for batch_index in 0..batch {
168 let row_start = row_indptr[batch_index] as usize;
169 let row_end = row_indptr[batch_index + 1] as usize;
170 for global_row in row_start..row_end {
171 for column in 0..columns {
172 let mut sum = 0.0f32;
173 for k in 0..reduction {
174 let lhs_index = if transpose_lhs {
175 k * lhs_row_stride + global_row
176 } else {
177 global_row * lhs_row_stride + k
178 };
179 let rhs_index = if transpose_rhs {
180 batch_index * rhs_batch_stride + column * rhs_row_stride + k
181 } else {
182 batch_index * rhs_batch_stride + k * rhs_row_stride + column
183 };
184 sum += lhs[lhs_index] * rhs[rhs_index];
185 }
186 out[global_row * columns + column] = sum;
187 }
188 }
189 }
190 out
191}
192
193pub fn group_gemm_f32(
194 lhs: &[f32],
195 rhs: &[f32],
196 rows: &[i32],
197 columns: &[i32],
198 reductions: &[i32],
199 lhs_offsets: &[i32],
200 rhs_offsets: &[i32],
201 output_offsets: &[i32],
202 output_len: usize,
203 transpose_rhs: bool,
204) -> Vec<f32> {
205 let mut out = vec![0.0f32; output_len];
206 for group in 0..rows.len() {
207 let group_rows = rows[group] as usize;
208 let group_columns = columns[group] as usize;
209 let group_reduction = reductions[group] as usize;
210 let lhs_base = lhs_offsets[group] as usize;
211 let rhs_base = rhs_offsets[group] as usize;
212 let output_base = output_offsets[group] as usize;
213 for row in 0..group_rows {
214 for column in 0..group_columns {
215 let mut sum = 0.0f32;
216 for k in 0..group_reduction {
217 let lhs_index = lhs_base + row * group_reduction + k;
218 let rhs_index = if transpose_rhs {
219 rhs_base + column * group_reduction + k
220 } else {
221 rhs_base + k * group_columns + column
222 };
223 sum += lhs[lhs_index] * rhs[rhs_index];
224 }
225 out[output_base + row * group_columns + column] = sum;
226 }
227 }
228 }
229 out
230}
231
232pub fn grouped_gemm_f32(
238 input: &[f32],
239 weights: &[f32],
240 m_sizes: &[i32],
241 gather_indices: &[i32],
242 total_tokens: usize,
243 columns: usize,
244 reduction: usize,
245 input_row_stride: usize,
246 weight_expert_stride: usize,
247 weight_row_stride: usize,
248 output_row_stride: usize,
249 permute_input: bool,
250 permute_output: bool,
251 top_k: usize,
252) -> Vec<f32> {
253 let mut out = vec![0.0f32; total_tokens * output_row_stride];
254 let mut token_start = 0usize;
255 for (expert, m_size) in m_sizes.iter().copied().enumerate() {
256 let expert_tokens = m_size as usize;
257 for local_row in 0..expert_tokens {
258 let sorted_row = token_start + local_row;
259 let gathered_row = gather_indices[sorted_row] as usize;
260 let input_row = if permute_input {
261 gathered_row / top_k
262 } else {
263 sorted_row
264 };
265 let output_row = if permute_output {
266 gathered_row
267 } else {
268 sorted_row
269 };
270 for column in 0..columns {
271 let mut sum = 0.0f32;
272 for k in 0..reduction {
273 let input_index = input_row * input_row_stride + k;
274 let weight_index =
275 expert * weight_expert_stride + column * weight_row_stride + k;
276 sum += input[input_index] * weights[weight_index];
277 }
278 out[output_row * output_row_stride + column] = sum;
279 }
280 }
281 token_start += expert_tokens;
282 }
283 out
284}
285#[cfg(feature = "dtype-f8")]
286
287pub fn ragged_block_scaled_bmm_f32(
288 lhs: &[u8],
289 rhs: &[u8],
290 lhs_scale: &[f32],
291 rhs_scale: &[f32],
292 row_indptr: &[i32],
293 batch: usize,
294 total_rows: usize,
295 columns: usize,
296 reduction: usize,
297 scale_block: usize,
298 lhs_scale_row_stride: usize,
299 rhs_scale_batch_stride: usize,
300 rhs_scale_row_stride: usize,
301) -> Vec<f32> {
302 let mut out = vec![0.0f32; total_rows * columns];
303 for batch_index in 0..batch {
304 let row_start = row_indptr[batch_index] as usize;
305 let row_end = row_indptr[batch_index + 1] as usize;
306 for global_row in row_start..row_end {
307 for column in 0..columns {
308 let mut sum = 0.0f32;
309 for k in 0..reduction {
310 let scale_k = k / scale_block;
311 let lhs_index = global_row * reduction + k;
312 let rhs_index = batch_index * columns * reduction + column * reduction + k;
313 let lhs_scale_index = global_row * lhs_scale_row_stride + scale_k;
314 let rhs_scale_index = batch_index * rhs_scale_batch_stride
315 + (column / scale_block) * rhs_scale_row_stride
316 + scale_k;
317 sum += f8e4m3_value(lhs[lhs_index])
318 * f8e4m3_value(rhs[rhs_index])
319 * lhs_scale[lhs_scale_index]
320 * rhs_scale[rhs_scale_index];
321 }
322 out[global_row * columns + column] = sum;
323 }
324 }
325 }
326 out
327}
328
329#[cfg(feature = "dtype-f8")]
330pub fn f8e4m3_value(value: u8) -> f32 {
331 let sign = if value & 0x80 == 0 { 1.0 } else { -1.0 };
332 let exponent = (value >> 3) & 0x0f;
333 let mantissa = value & 0x07;
334 if exponent == 0x0f && mantissa == 0x07 {
335 f32::NAN
336 } else if exponent == 0 {
337 if mantissa == 0 {
338 sign * 0.0
339 } else {
340 sign * (mantissa as f32 / 8.0) * 2f32.powi(-6)
341 }
342 } else {
343 sign * (1.0 + mantissa as f32 / 8.0) * 2f32.powi(exponent as i32 - 7)
344 }
345}
346
347pub fn bmm_f64(
348 lhs: &[f64],
349 rhs: &[f64],
350 batch: usize,
351 rows: usize,
352 columns: usize,
353 reduction: usize,
354 lhs_batch_stride: usize,
355 lhs_row_stride: usize,
356 rhs_batch_stride: usize,
357 rhs_row_stride: usize,
358 transpose_lhs: bool,
359 transpose_rhs: bool,
360) -> Vec<f64> {
361 let mut out = vec![0.0f64; batch * rows * columns];
362 for batch_index in 0..batch {
363 for row in 0..rows {
364 for column in 0..columns {
365 let mut sum = 0.0f64;
366 for k in 0..reduction {
367 let lhs_index = if transpose_lhs {
368 batch_index * lhs_batch_stride + k * lhs_row_stride + row
369 } else {
370 batch_index * lhs_batch_stride + row * lhs_row_stride + k
371 };
372 let rhs_index = if transpose_rhs {
373 batch_index * rhs_batch_stride + column * rhs_row_stride + k
374 } else {
375 batch_index * rhs_batch_stride + k * rhs_row_stride + column
376 };
377 sum += lhs[lhs_index] * rhs[rhs_index];
378 }
379 out[batch_index * rows * columns + row * columns + column] = sum;
380 }
381 }
382 }
383 out
384}