Skip to main content

poulpy_hal/oep/
hal_impl.rs

1#![allow(clippy::too_many_arguments)]
2
3use crate::{
4    layouts::{
5        Backend, Module, NoiseInfos, ScalarZnxBackendMut, ScalarZnxBackendRef, ScratchArena, VecZnxBackendMut, VecZnxBackendRef,
6        VecZnxBigBackendMut,
7    },
8    source::Source,
9};
10
11/// Module construction extension point.
12///
13/// # Safety
14/// Implementations must return a module handle that is valid for the backend
15/// and ring degree, and uphold the backend safety contract.
16pub unsafe trait HalModuleImpl<BE: Backend>: Backend {
17    /// Backend-specific construction parameters.
18    ///
19    /// Host backends leave this at `()`. A device backend names here whatever
20    /// [`Self::new`] cannot express, a device ordinal above all: with `new`
21    /// alone, a module on a multi-GPU host lands on whatever the driver calls
22    /// the default device, which is not necessarily the one the operator means.
23    type Config: Default = ();
24
25    #[allow(clippy::new_ret_no_self)]
26    fn new(n: u64) -> Module<BE>;
27
28    /// Constructs a module under an explicit [`Self::Config`].
29    ///
30    /// Defaults to ignoring the configuration, which is correct for any backend
31    /// that leaves `Config = ()`. A backend declaring a real `Config` must
32    /// override this, and should keep `new` equivalent to
33    /// `new_with(n, Config::default())`.
34    #[allow(clippy::new_ret_no_self)]
35    fn new_with(n: u64, _config: Self::Config) -> Module<BE> {
36        Self::new(n)
37    }
38}
39
40/// Coefficient-domain `VecZnx` extension point.
41///
42/// # Safety
43/// Implementations must uphold the backend safety contract for layout access,
44/// aliasing, scratch usage, and arithmetic correctness.
45pub unsafe trait HalVecZnxImpl<BE: Backend>: Backend {
46    fn vec_znx_zero_backend(module: &Module<BE>, res: &mut VecZnxBackendMut<'_, BE>, res_col: usize);
47
48    fn scalar_znx_fill_ternary_hw_backend(
49        module: &Module<BE>,
50        res: &mut ScalarZnxBackendMut<'_, BE>,
51        res_col: usize,
52        hw: usize,
53        seed: [u8; 32],
54    );
55
56    fn scalar_znx_fill_ternary_prob_backend(
57        module: &Module<BE>,
58        res: &mut ScalarZnxBackendMut<'_, BE>,
59        res_col: usize,
60        prob: f64,
61        seed: [u8; 32],
62    );
63
64    fn scalar_znx_fill_binary_hw_backend(
65        module: &Module<BE>,
66        res: &mut ScalarZnxBackendMut<'_, BE>,
67        res_col: usize,
68        hw: usize,
69        seed: [u8; 32],
70    );
71
72    fn scalar_znx_fill_binary_prob_backend(
73        module: &Module<BE>,
74        res: &mut ScalarZnxBackendMut<'_, BE>,
75        res_col: usize,
76        prob: f64,
77        seed: [u8; 32],
78    );
79
80    fn scalar_znx_fill_binary_block_backend(
81        module: &Module<BE>,
82        res: &mut ScalarZnxBackendMut<'_, BE>,
83        res_col: usize,
84        block_size: usize,
85        seed: [u8; 32],
86    );
87
88    fn vec_znx_hadamard_product_scalar_znx_backend(
89        module: &Module<BE>,
90        res: &mut VecZnxBigBackendMut<'_, BE>,
91        res_col: usize,
92        a: &VecZnxBackendRef<'_, BE>,
93        a_col: usize,
94        b: &ScalarZnxBackendRef<'_, BE>,
95        b_col: usize,
96    );
97
98    fn vec_znx_normalize_tmp_bytes_backend(module: &Module<BE>) -> usize;
99
100    #[allow(clippy::too_many_arguments)]
101    fn vec_znx_normalize_backend(
102        module: &Module<BE>,
103        res: &mut VecZnxBackendMut<'_, BE>,
104        res_base2k: usize,
105        res_k: usize,
106        res_offset: i64,
107        res_col: usize,
108        a: &VecZnxBackendRef<'_, BE>,
109        a_base2k: usize,
110        a_col: usize,
111        scratch: &mut ScratchArena<'_, BE>,
112    );
113
114    fn vec_znx_normalize_assign_backend(
115        module: &Module<BE>,
116        base2k: usize,
117        k: usize,
118        a: &mut VecZnxBackendMut<'_, BE>,
119        a_col: usize,
120        scratch: &mut ScratchArena<'_, BE>,
121    );
122
123    fn vec_znx_normalize_coeff_assign_backend(
124        module: &Module<BE>,
125        base2k: usize,
126        a: &mut VecZnxBackendMut<'_, BE>,
127        a_col: usize,
128        a_coeff: usize,
129        scratch: &mut ScratchArena<'_, BE>,
130    );
131
132    #[allow(clippy::too_many_arguments)]
133    fn vec_znx_normalize_coeff_backend(
134        module: &Module<BE>,
135        res: &mut VecZnxBackendMut<'_, BE>,
136        res_base2k: usize,
137        res_offset: i64,
138        res_col: usize,
139        a: &VecZnxBackendRef<'_, BE>,
140        a_base2k: usize,
141        a_col: usize,
142        a_coeff: usize,
143        scratch: &mut ScratchArena<'_, BE>,
144    );
145
146    fn vec_znx_add_into_backend(
147        module: &Module<BE>,
148        res: &mut VecZnxBackendMut<'_, BE>,
149        res_col: usize,
150        a: &VecZnxBackendRef<'_, BE>,
151        a_col: usize,
152        b: &VecZnxBackendRef<'_, BE>,
153        b_col: usize,
154    );
155
156    fn vec_znx_add_assign_backend(
157        module: &Module<BE>,
158        res: &mut VecZnxBackendMut<'_, BE>,
159        res_col: usize,
160        a: &VecZnxBackendRef<'_, BE>,
161        a_col: usize,
162    );
163
164    #[allow(clippy::too_many_arguments)]
165    fn vec_znx_add_const_into_backend(
166        module: &Module<BE>,
167        res: &mut VecZnxBackendMut<'_, BE>,
168        res_col: usize,
169        a: &VecZnxBackendRef<'_, BE>,
170        a_col: usize,
171        cnst: &VecZnxBackendRef<'_, BE>,
172        cnst_col: usize,
173        cnst_coeff: usize,
174        res_limb: usize,
175        res_coeff: usize,
176    );
177
178    fn vec_znx_add_const_assign_backend(
179        module: &Module<BE>,
180        res: &mut VecZnxBackendMut<'_, BE>,
181        res_col: usize,
182        cnst: &VecZnxBackendRef<'_, BE>,
183        cnst_col: usize,
184        cnst_coeff: usize,
185        res_limb: usize,
186        res_coeff: usize,
187    );
188
189    #[allow(clippy::too_many_arguments)]
190    fn vec_znx_add_scalar_into_backend(
191        module: &Module<BE>,
192        res: &mut VecZnxBackendMut<'_, BE>,
193        res_col: usize,
194        a: &ScalarZnxBackendRef<'_, BE>,
195        a_col: usize,
196        b: &VecZnxBackendRef<'_, BE>,
197        b_col: usize,
198        b_limb: usize,
199    );
200
201    fn vec_znx_add_scalar_assign_backend(
202        module: &Module<BE>,
203        res: &mut VecZnxBackendMut<'_, BE>,
204        res_col: usize,
205        res_limb: usize,
206        a: &ScalarZnxBackendRef<'_, BE>,
207        a_col: usize,
208    );
209
210    fn vec_znx_sub_backend(
211        module: &Module<BE>,
212        res: &mut VecZnxBackendMut<'_, BE>,
213        res_col: usize,
214        a: &VecZnxBackendRef<'_, BE>,
215        a_col: usize,
216        b: &VecZnxBackendRef<'_, BE>,
217        b_col: usize,
218    );
219
220    fn vec_znx_sub_assign_backend(
221        module: &Module<BE>,
222        res: &mut VecZnxBackendMut<'_, BE>,
223        res_col: usize,
224        a: &VecZnxBackendRef<'_, BE>,
225        a_col: usize,
226    );
227
228    fn vec_znx_sub_negate_assign_backend(
229        module: &Module<BE>,
230        res: &mut VecZnxBackendMut<'_, BE>,
231        res_col: usize,
232        a: &VecZnxBackendRef<'_, BE>,
233        a_col: usize,
234    );
235
236    #[allow(clippy::too_many_arguments)]
237    fn vec_znx_sub_scalar_backend(
238        module: &Module<BE>,
239        res: &mut VecZnxBackendMut<'_, BE>,
240        res_col: usize,
241        a: &ScalarZnxBackendRef<'_, BE>,
242        a_col: usize,
243        b: &VecZnxBackendRef<'_, BE>,
244        b_col: usize,
245        b_limb: usize,
246    );
247
248    fn vec_znx_sub_scalar_assign_backend(
249        module: &Module<BE>,
250        res: &mut VecZnxBackendMut<'_, BE>,
251        res_col: usize,
252        res_limb: usize,
253        a: &ScalarZnxBackendRef<'_, BE>,
254        a_col: usize,
255    );
256
257    fn vec_znx_negate_backend(
258        module: &Module<BE>,
259        res: &mut VecZnxBackendMut<'_, BE>,
260        res_col: usize,
261        a: &VecZnxBackendRef<'_, BE>,
262        a_col: usize,
263    );
264
265    fn vec_znx_negate_assign_backend(module: &Module<BE>, a: &mut VecZnxBackendMut<'_, BE>, a_col: usize);
266
267    fn vec_znx_rsh_tmp_bytes_backend(module: &Module<BE>) -> usize;
268
269    fn vec_znx_rsh_backend(
270        module: &Module<BE>,
271        base2k: usize,
272        k: usize,
273        res: &mut VecZnxBackendMut<'_, BE>,
274        res_col: usize,
275        a: &VecZnxBackendRef<'_, BE>,
276        a_col: usize,
277        scratch: &mut ScratchArena<'_, BE>,
278    );
279
280    fn vec_znx_rsh_coeff_backend(
281        module: &Module<BE>,
282        base2k: usize,
283        k: usize,
284        res: &mut VecZnxBackendMut<'_, BE>,
285        res_col: usize,
286        a: &VecZnxBackendRef<'_, BE>,
287        a_col: usize,
288        a_coeff: usize,
289        scratch: &mut ScratchArena<'_, BE>,
290    );
291
292    fn vec_znx_rsh_add_into_backend(
293        module: &Module<BE>,
294        base2k: usize,
295        k: usize,
296        res: &mut VecZnxBackendMut<'_, BE>,
297        res_col: usize,
298        a: &VecZnxBackendRef<'_, BE>,
299        a_col: usize,
300        scratch: &mut ScratchArena<'_, BE>,
301    );
302
303    fn vec_znx_rsh_add_coeff_into_backend(
304        module: &Module<BE>,
305        base2k: usize,
306        k: usize,
307        res: &mut VecZnxBackendMut<'_, BE>,
308        res_col: usize,
309        a: &VecZnxBackendRef<'_, BE>,
310        a_col: usize,
311        a_coeff: usize,
312        res_coeff: usize,
313        scratch: &mut ScratchArena<'_, BE>,
314    );
315
316    fn vec_znx_rsh_sub_coeff_into_backend(
317        module: &Module<BE>,
318        base2k: usize,
319        k: usize,
320        res: &mut VecZnxBackendMut<'_, BE>,
321        res_col: usize,
322        a: &VecZnxBackendRef<'_, BE>,
323        a_col: usize,
324        a_coeff: usize,
325        res_coeff: usize,
326        scratch: &mut ScratchArena<'_, BE>,
327    );
328
329    fn vec_znx_lsh_tmp_bytes_backend(module: &Module<BE>) -> usize;
330
331    fn vec_znx_lsh_backend(
332        module: &Module<BE>,
333        base2k: usize,
334        k: usize,
335        res: &mut VecZnxBackendMut<'_, BE>,
336        res_col: usize,
337        a: &VecZnxBackendRef<'_, BE>,
338        a_col: usize,
339        scratch: &mut ScratchArena<'_, BE>,
340    );
341
342    fn vec_znx_lsh_coeff_backend(
343        module: &Module<BE>,
344        base2k: usize,
345        k: usize,
346        res: &mut VecZnxBackendMut<'_, BE>,
347        res_col: usize,
348        a: &VecZnxBackendRef<'_, BE>,
349        a_col: usize,
350        a_coeff: usize,
351        scratch: &mut ScratchArena<'_, BE>,
352    );
353
354    fn vec_znx_lsh_add_into_backend(
355        module: &Module<BE>,
356        base2k: usize,
357        k: usize,
358        res: &mut VecZnxBackendMut<'_, BE>,
359        res_col: usize,
360        a: &VecZnxBackendRef<'_, BE>,
361        a_col: usize,
362        scratch: &mut ScratchArena<'_, BE>,
363    );
364
365    fn vec_znx_lsh_add_coeff_into_backend(
366        module: &Module<BE>,
367        base2k: usize,
368        k: usize,
369        res: &mut VecZnxBackendMut<'_, BE>,
370        res_col: usize,
371        a: &VecZnxBackendRef<'_, BE>,
372        a_col: usize,
373        a_coeff: usize,
374        scratch: &mut ScratchArena<'_, BE>,
375    );
376
377    fn vec_znx_lsh_add_coeff_to_coeff_backend(
378        module: &Module<BE>,
379        base2k: usize,
380        k: usize,
381        res: &mut VecZnxBackendMut<'_, BE>,
382        res_col: usize,
383        a: &VecZnxBackendRef<'_, BE>,
384        a_col: usize,
385        a_coeff: usize,
386        res_coeff: usize,
387        scratch: &mut ScratchArena<'_, BE>,
388    );
389
390    fn vec_znx_lsh_sub_coeff_to_coeff_backend(
391        module: &Module<BE>,
392        base2k: usize,
393        k: usize,
394        res: &mut VecZnxBackendMut<'_, BE>,
395        res_col: usize,
396        a: &VecZnxBackendRef<'_, BE>,
397        a_col: usize,
398        a_coeff: usize,
399        res_coeff: usize,
400        scratch: &mut ScratchArena<'_, BE>,
401    );
402
403    fn vec_znx_lsh_sub_backend(
404        module: &Module<BE>,
405        base2k: usize,
406        k: usize,
407        res: &mut VecZnxBackendMut<'_, BE>,
408        res_col: usize,
409        a: &VecZnxBackendRef<'_, BE>,
410        a_col: usize,
411        scratch: &mut ScratchArena<'_, BE>,
412    );
413
414    fn vec_znx_rsh_sub_backend(
415        module: &Module<BE>,
416        base2k: usize,
417        k: usize,
418        res: &mut VecZnxBackendMut<'_, BE>,
419        res_col: usize,
420        a: &VecZnxBackendRef<'_, BE>,
421        a_col: usize,
422        scratch: &mut ScratchArena<'_, BE>,
423    );
424
425    fn vec_znx_rsh_assign_backend(
426        module: &Module<BE>,
427        base2k: usize,
428        k: usize,
429        a: &mut VecZnxBackendMut<'_, BE>,
430        a_col: usize,
431        scratch: &mut ScratchArena<'_, BE>,
432    );
433
434    fn vec_znx_lsh_assign_backend(
435        module: &Module<BE>,
436        base2k: usize,
437        k: usize,
438        a: &mut VecZnxBackendMut<'_, BE>,
439        a_col: usize,
440        scratch: &mut ScratchArena<'_, BE>,
441    );
442
443    fn vec_znx_rotate_backend(
444        module: &Module<BE>,
445        k: i64,
446        res: &mut VecZnxBackendMut<'_, BE>,
447        res_col: usize,
448        a: &VecZnxBackendRef<'_, BE>,
449        a_col: usize,
450    );
451
452    fn vec_znx_rotate_assign_tmp_bytes_backend(module: &Module<BE>) -> usize;
453
454    fn vec_znx_rotate_assign_backend(
455        module: &Module<BE>,
456        k: i64,
457        a: &mut VecZnxBackendMut<'_, BE>,
458        a_col: usize,
459        scratch: &mut ScratchArena<'_, BE>,
460    );
461
462    fn vec_znx_automorphism_backend(
463        module: &Module<BE>,
464        k: i64,
465        res: &mut VecZnxBackendMut<'_, BE>,
466        res_col: usize,
467        a: &VecZnxBackendRef<'_, BE>,
468        a_col: usize,
469    );
470
471    fn vec_znx_automorphism_assign_tmp_bytes_backend(module: &Module<BE>) -> usize;
472
473    fn vec_znx_automorphism_assign_backend(
474        module: &Module<BE>,
475        k: i64,
476        res: &mut VecZnxBackendMut<'_, BE>,
477        res_col: usize,
478        scratch: &mut ScratchArena<'_, BE>,
479    );
480
481    #[allow(clippy::too_many_arguments)]
482    fn vec_znx_automorphism_rotate_backend(
483        module: &Module<BE>,
484        p: i64,
485        k: i64,
486        res: &mut VecZnxBackendMut<'_, BE>,
487        res_col: usize,
488        a: &VecZnxBackendRef<'_, BE>,
489        a_col: usize,
490    );
491
492    fn vec_znx_mul_xp_minus_one_backend(
493        module: &Module<BE>,
494        k: i64,
495        res: &mut VecZnxBackendMut<'_, BE>,
496        res_col: usize,
497        a: &VecZnxBackendRef<'_, BE>,
498        a_col: usize,
499    );
500
501    fn vec_znx_mul_xp_minus_one_assign_tmp_bytes_backend(module: &Module<BE>) -> usize;
502
503    fn vec_znx_mul_xp_minus_one_assign_backend(
504        module: &Module<BE>,
505        k: i64,
506        res: &mut VecZnxBackendMut<'_, BE>,
507        res_col: usize,
508        scratch: &mut ScratchArena<'_, BE>,
509    );
510
511    fn vec_znx_split_ring_tmp_bytes_backend(module: &Module<BE>) -> usize;
512
513    fn vec_znx_split_ring_backend(
514        module: &Module<BE>,
515        res: &mut [VecZnxBackendMut<'_, BE>],
516        res_col: usize,
517        a: &VecZnxBackendRef<'_, BE>,
518        a_col: usize,
519        scratch: &mut ScratchArena<'_, BE>,
520    );
521
522    fn vec_znx_merge_rings_tmp_bytes_backend(module: &Module<BE>) -> usize;
523
524    fn vec_znx_merge_rings_backend(
525        module: &Module<BE>,
526        res: &mut VecZnxBackendMut<'_, BE>,
527        res_col: usize,
528        a: &[VecZnxBackendRef<'_, BE>],
529        a_col: usize,
530        scratch: &mut ScratchArena<'_, BE>,
531    );
532
533    fn vec_znx_switch_ring_backend(
534        module: &Module<BE>,
535        res: &mut VecZnxBackendMut<'_, BE>,
536        res_col: usize,
537        a: &VecZnxBackendRef<'_, BE>,
538        a_col: usize,
539    );
540
541    fn vec_znx_copy_backend(
542        module: &Module<BE>,
543        res: &mut VecZnxBackendMut<'_, BE>,
544        res_col: usize,
545        a: &VecZnxBackendRef<'_, BE>,
546        a_col: usize,
547    );
548
549    fn vec_znx_transpose_backend(module: &Module<BE>, res: &mut VecZnxBackendMut<'_, BE>, a: &VecZnxBackendRef<'_, BE>);
550
551    fn vec_znx_copy_range_backend(
552        module: &Module<BE>,
553        res: &mut VecZnxBackendMut<'_, BE>,
554        res_col: usize,
555        res_limb: usize,
556        res_offset: usize,
557        a: &VecZnxBackendRef<'_, BE>,
558        a_col: usize,
559        a_limb: usize,
560        a_offset: usize,
561        len: usize,
562    );
563
564    fn vec_znx_extract_coeff_backend(
565        module: &Module<BE>,
566        res: &mut VecZnxBackendMut<'_, BE>,
567        res_col: usize,
568        a: &VecZnxBackendRef<'_, BE>,
569        a_col: usize,
570        a_coeff: usize,
571    );
572
573    fn vec_znx_fill_uniform_backend(
574        module: &Module<BE>,
575        base2k: usize,
576        k: usize,
577        res: &mut VecZnxBackendMut<'_, BE>,
578        res_col: usize,
579        seed: [u8; 32],
580    );
581
582    fn vec_znx_fill_normal_backend(
583        module: &Module<BE>,
584        res_base2k: usize,
585        res: &mut VecZnxBackendMut<'_, BE>,
586        res_col: usize,
587        noise_infos: NoiseInfos,
588        seed: [u8; 32],
589    );
590
591    fn vec_znx_add_normal_backend(
592        module: &Module<BE>,
593        res_base2k: usize,
594        res: &mut VecZnxBackendMut<'_, BE>,
595        res_col: usize,
596        noise_infos: NoiseInfos,
597        seed: [u8; 32],
598    );
599}
600
601/// Big-coefficient `VecZnxBig` extension point.
602///
603/// # Safety
604/// Implementations must uphold the backend safety contract for backend-native
605/// accumulator layouts and arithmetic correctness.
606pub unsafe trait HalVecZnxBigImpl<BE: Backend>: Backend {
607    fn vec_znx_big_from_small_backend(
608        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
609        res_col: usize,
610        a: &VecZnxBackendRef<'_, BE>,
611        a_col: usize,
612    );
613
614    fn vec_znx_big_add_normal_backend(
615        module: &Module<BE>,
616        res_base2k: usize,
617        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
618        res_col: usize,
619        noise_infos: NoiseInfos,
620        seed: [u8; 32],
621    );
622
623    fn vec_znx_big_add_normal(
624        module: &Module<BE>,
625        res_base2k: usize,
626        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
627        res_col: usize,
628        noise_infos: NoiseInfos,
629        source: &mut Source,
630    ) {
631        Self::vec_znx_big_add_normal_backend(module, res_base2k, res, res_col, noise_infos, source.new_seed());
632    }
633
634    fn vec_znx_big_add_into(
635        module: &Module<BE>,
636        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
637        res_col: usize,
638        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
639        a_col: usize,
640        b: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
641        b_col: usize,
642    );
643
644    fn vec_znx_big_add_assign(
645        module: &Module<BE>,
646        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
647        res_col: usize,
648        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
649        a_col: usize,
650    );
651
652    fn vec_znx_big_add_small_into_backend(
653        module: &Module<BE>,
654        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
655        res_col: usize,
656        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
657        a_col: usize,
658        b: &VecZnxBackendRef<'_, BE>,
659        b_col: usize,
660    );
661
662    fn vec_znx_big_add_small_assign(
663        module: &Module<BE>,
664        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
665        res_col: usize,
666        a: &VecZnxBackendRef<'_, BE>,
667        a_col: usize,
668    );
669
670    fn vec_znx_big_sub(
671        module: &Module<BE>,
672        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
673        res_col: usize,
674        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
675        a_col: usize,
676        b: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
677        b_col: usize,
678    );
679
680    fn vec_znx_big_sub_assign(
681        module: &Module<BE>,
682        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
683        res_col: usize,
684        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
685        a_col: usize,
686    );
687
688    fn vec_znx_big_sub_negate_assign(
689        module: &Module<BE>,
690        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
691        res_col: usize,
692        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
693        a_col: usize,
694    );
695
696    fn vec_znx_big_sub_small_a_backend(
697        module: &Module<BE>,
698        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
699        res_col: usize,
700        a: &VecZnxBackendRef<'_, BE>,
701        a_col: usize,
702        b: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
703        b_col: usize,
704    );
705
706    fn vec_znx_big_sub_small_assign(
707        module: &Module<BE>,
708        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
709        res_col: usize,
710        a: &VecZnxBackendRef<'_, BE>,
711        a_col: usize,
712    );
713
714    fn vec_znx_big_sub_small_b_backend(
715        module: &Module<BE>,
716        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
717        res_col: usize,
718        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
719        a_col: usize,
720        b: &VecZnxBackendRef<'_, BE>,
721        b_col: usize,
722    );
723
724    fn vec_znx_big_sub_small_negate_assign(
725        module: &Module<BE>,
726        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
727        res_col: usize,
728        a: &VecZnxBackendRef<'_, BE>,
729        a_col: usize,
730    );
731
732    fn vec_znx_big_inner_sum_backend(
733        module: &Module<BE>,
734        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
735        res_col: usize,
736        res_coeff: usize,
737        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
738        a_col: usize,
739    );
740
741    fn vec_znx_big_col_weighted_sum(
742        module: &Module<BE>,
743        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
744        res_col: usize,
745        a: &VecZnxBackendRef<'_, BE>,
746        weights: &ScalarZnxBackendRef<'_, BE>,
747        weights_col: usize,
748        cols: usize,
749        coeffs: usize,
750    );
751
752    fn vec_znx_scalar_product(
753        module: &Module<BE>,
754        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
755        res_col: usize,
756        a: &VecZnxBackendRef<'_, BE>,
757        a_col: usize,
758        b: &ScalarZnxBackendRef<'_, BE>,
759        b_col: usize,
760    );
761
762    fn vec_znx_big_negate(
763        module: &Module<BE>,
764        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
765        res_col: usize,
766        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
767        a_col: usize,
768    );
769
770    fn vec_znx_big_negate_assign(module: &Module<BE>, a: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>, a_col: usize);
771
772    fn vec_znx_big_normalize_tmp_bytes(module: &Module<BE>) -> usize;
773
774    #[allow(clippy::too_many_arguments)]
775    fn vec_znx_big_normalize(
776        module: &Module<BE>,
777        res: &mut VecZnxBackendMut<'_, BE>,
778        res_base2k: usize,
779        res_k: usize,
780        res_offset: i64,
781        res_col: usize,
782        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
783        a_base2k: usize,
784        a_col: usize,
785        scratch: &mut ScratchArena<'_, BE>,
786    );
787
788    fn vec_znx_big_automorphism(
789        module: &Module<BE>,
790        k: i64,
791        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
792        res_col: usize,
793        a: &crate::layouts::VecZnxBigBackendRef<'_, BE>,
794        a_col: usize,
795    );
796
797    fn vec_znx_big_automorphism_assign_tmp_bytes(module: &Module<BE>) -> usize;
798
799    fn vec_znx_big_automorphism_assign(
800        module: &Module<BE>,
801        k: i64,
802        a: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
803        a_col: usize,
804        scratch: &mut ScratchArena<'_, BE>,
805    );
806}
807
808/// Prepared / DFT-domain `VecZnxDft` extension point.
809///
810/// # Safety
811/// Implementations must uphold the backend safety contract for prepared-domain
812/// layouts, transforms, and arithmetic correctness.
813pub unsafe trait HalVecZnxDftImpl<BE: Backend>: Backend {
814    fn vec_znx_dft_apply(
815        module: &Module<BE>,
816        step: usize,
817        offset: usize,
818        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
819        res_col: usize,
820        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
821        a_col: usize,
822    );
823
824    fn vec_znx_idft_apply_tmp_bytes(module: &Module<BE>) -> usize;
825
826    fn vec_znx_idft_apply(
827        module: &Module<BE>,
828        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
829        res_col: usize,
830        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
831        a_col: usize,
832        scratch: &mut ScratchArena<'_, BE>,
833    );
834
835    fn vec_znx_idft_apply_tmpa(
836        module: &Module<BE>,
837        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
838        res_col: usize,
839        a: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
840        a_col: usize,
841    );
842
843    fn vec_znx_idft_normalize_consume_tmp_bytes(module: &Module<BE>, res_size: usize, a_size: usize) -> usize;
844
845    /// `res[res_col] = normalize(idft(a[a_col]) + addend)`, clobbering `a[a_col]`.
846    #[allow(clippy::too_many_arguments)]
847    fn vec_znx_idft_normalize_consume(
848        module: &Module<BE>,
849        res: &mut crate::layouts::VecZnxBackendMut<'_, BE>,
850        res_base2k: usize,
851        res_k: usize,
852        res_col: usize,
853        a: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
854        a_col: usize,
855        a_base2k: usize,
856        addend: Option<(&crate::layouts::VecZnxBackendRef<'_, BE>, usize)>,
857        scratch: &mut ScratchArena<'_, BE>,
858    );
859
860    fn vec_znx_dft_add_into(
861        module: &Module<BE>,
862        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
863        res_col: usize,
864        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
865        a_col: usize,
866        b: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
867        b_col: usize,
868    );
869
870    fn vec_znx_dft_add_scaled_assign(
871        module: &Module<BE>,
872        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
873        res_col: usize,
874        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
875        a_col: usize,
876        a_scale: i64,
877    );
878
879    fn vec_znx_dft_add_assign(
880        module: &Module<BE>,
881        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
882        res_col: usize,
883        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
884        a_col: usize,
885    );
886
887    fn vec_znx_dft_sub(
888        module: &Module<BE>,
889        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
890        res_col: usize,
891        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
892        a_col: usize,
893        b: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
894        b_col: usize,
895    );
896
897    fn vec_znx_dft_sub_assign(
898        module: &Module<BE>,
899        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
900        res_col: usize,
901        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
902        a_col: usize,
903    );
904
905    fn vec_znx_dft_sub_negate_assign(
906        module: &Module<BE>,
907        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
908        res_col: usize,
909        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
910        a_col: usize,
911    );
912
913    fn vec_znx_dft_copy(
914        module: &Module<BE>,
915        step: usize,
916        offset: usize,
917        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
918        res_col: usize,
919        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
920        a_col: usize,
921    );
922
923    fn vec_znx_dft_zero(module: &Module<BE>, res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>, res_col: usize);
924
925    /// Backend-specific automorphism plan (e.g. a `Fft64AutomorphismPlan`
926    /// for FFT64 backends, a pure-permutation plan for NTT backends).
927    type AutomorphismPlan: Send + Sync;
928
929    fn vec_znx_dft_automorphism_plan(module: &Module<BE>, p: i64) -> Self::AutomorphismPlan;
930
931    fn vec_znx_dft_automorphism_with_plan(
932        module: &Module<BE>,
933        plan: &Self::AutomorphismPlan,
934        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
935        res_col: usize,
936        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
937        a_col: usize,
938    );
939
940    /// `res[res_col] += automorphism(a[a_col])` over `min(res.size(), a.size())` limbs;
941    /// res limbs beyond that are left untouched.
942    fn vec_znx_dft_automorphism_add_with_plan(
943        module: &Module<BE>,
944        plan: &Self::AutomorphismPlan,
945        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
946        res_col: usize,
947        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
948        a_col: usize,
949    );
950}
951
952/// Scalar-vector product family extension point.
953///
954/// # Safety
955/// Implementations must uphold the backend safety contract for prepared
956/// polynomial layouts and arithmetic correctness.
957pub unsafe trait HalSvpImpl<BE: Backend>: Backend {
958    fn svp_prepare(
959        module: &Module<BE>,
960        res: &mut crate::layouts::SvpPPolBackendMut<'_, BE>,
961        res_col: usize,
962        a: &ScalarZnxBackendRef<'_, BE>,
963        a_col: usize,
964    );
965
966    fn svp_ppol_copy_backend(
967        module: &Module<BE>,
968        res: &mut crate::layouts::SvpPPolBackendMut<'_, BE>,
969        res_col: usize,
970        a: &crate::layouts::SvpPPolBackendRef<'_, BE>,
971        a_col: usize,
972    );
973
974    fn svp_apply_dft(
975        module: &Module<BE>,
976        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
977        res_col: usize,
978        a: &crate::layouts::SvpPPolBackendRef<'_, BE>,
979        a_col: usize,
980        b: &crate::layouts::VecZnxBackendRef<'_, BE>,
981        b_col: usize,
982    );
983
984    fn svp_apply_dft_to_dft(
985        module: &Module<BE>,
986        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
987        res_col: usize,
988        a: &crate::layouts::SvpPPolBackendRef<'_, BE>,
989        a_col: usize,
990        b: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
991        b_col: usize,
992    );
993
994    fn svp_apply_dft_to_dft_assign(
995        module: &Module<BE>,
996        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
997        res_col: usize,
998        a: &crate::layouts::SvpPPolBackendRef<'_, BE>,
999        a_col: usize,
1000    );
1001}
1002
1003/// Vector-matrix product family extension point.
1004///
1005/// # Safety
1006/// Implementations must uphold the backend safety contract for prepared matrix
1007/// layouts, scratch usage, and arithmetic correctness.
1008pub unsafe trait HalVmpImpl<BE: Backend>: Backend {
1009    fn vmp_prepare_tmp_bytes(module: &Module<BE>, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize;
1010
1011    fn vmp_prepare(
1012        module: &Module<BE>,
1013        res: &mut crate::layouts::VmpPMatBackendMut<'_, BE>,
1014        a: &crate::layouts::MatZnxBackendRef<'_, BE>,
1015        scratch: &mut ScratchArena<'_, BE>,
1016    );
1017
1018    #[allow(clippy::too_many_arguments)]
1019    fn vmp_apply_dft_tmp_bytes(
1020        module: &Module<BE>,
1021        res_size: usize,
1022        a_size: usize,
1023        b_rows: usize,
1024        b_cols_in: usize,
1025        b_cols_out: usize,
1026        b_size: usize,
1027    ) -> usize;
1028
1029    fn vmp_apply_dft<R>(
1030        module: &Module<BE>,
1031        res: &mut R,
1032        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1033        b: &crate::layouts::VmpPMatBackendRef<'_, BE>,
1034        scratch: &mut ScratchArena<'_, BE>,
1035    ) where
1036        R: crate::layouts::VecZnxDftToBackendMut<BE>;
1037
1038    #[allow(clippy::too_many_arguments)]
1039    fn vmp_apply_dft_to_dft_tmp_bytes(
1040        module: &Module<BE>,
1041        res_size: usize,
1042        a_size: usize,
1043        b_rows: usize,
1044        b_cols_in: usize,
1045        b_cols_out: usize,
1046        b_size: usize,
1047    ) -> usize;
1048
1049    fn vmp_apply_dft_to_dft(
1050        module: &Module<BE>,
1051        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1052        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
1053        b: &crate::layouts::VmpPMatBackendRef<'_, BE>,
1054        limb_offset: usize,
1055        scratch: &mut ScratchArena<'_, BE>,
1056    );
1057
1058    #[allow(clippy::too_many_arguments)]
1059    fn vmp_apply_dft_to_dft_accumulate_tmp_bytes(
1060        module: &Module<BE>,
1061        res_size: usize,
1062        a_size: usize,
1063        b_rows: usize,
1064        b_cols_in: usize,
1065        b_cols_out: usize,
1066        b_size: usize,
1067    ) -> usize;
1068
1069    fn vmp_apply_dft_to_dft_accumulate(
1070        module: &Module<BE>,
1071        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1072        a: &crate::layouts::VecZnxDftBackendRef<'_, BE>,
1073        b: &crate::layouts::VmpPMatBackendRef<'_, BE>,
1074        limb_offset: usize,
1075        scratch: &mut ScratchArena<'_, BE>,
1076    );
1077
1078    fn vmp_extract_selected_rows(
1079        module: &Module<BE>,
1080        res: &mut crate::layouts::VmpPMatBackendMut<'_, BE>,
1081        a: &crate::layouts::VmpPMatBackendRef<'_, BE>,
1082        first_row: usize,
1083        row_step: usize,
1084    );
1085
1086    fn vmp_zero(module: &Module<BE>, res: &mut crate::layouts::VmpPMatBackendMut<'_, BE>);
1087}
1088
1089/// Convolution family extension point.
1090///
1091/// # Safety
1092/// Implementations must uphold the backend safety contract for prepared matrix
1093/// layouts, scratch usage, and arithmetic correctness.
1094pub unsafe trait HalConvolutionImpl<BE: Backend>: Backend {
1095    fn cnv_prepare_left_tmp_bytes(module: &Module<BE>, res_size: usize, a_size: usize) -> usize;
1096
1097    fn cnv_prepare_left(
1098        module: &Module<BE>,
1099        res: &mut crate::layouts::CnvPVecLBackendMut<'_, BE>,
1100        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1101        mask: i64,
1102        scratch: &mut ScratchArena<'_, BE>,
1103    );
1104
1105    fn cnv_prepare_right_tmp_bytes(module: &Module<BE>, res_size: usize, a_size: usize) -> usize;
1106
1107    fn cnv_prepare_right(
1108        module: &Module<BE>,
1109        res: &mut crate::layouts::CnvPVecRBackendMut<'_, BE>,
1110        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1111        mask: i64,
1112        scratch: &mut ScratchArena<'_, BE>,
1113    );
1114
1115    fn cnv_apply_dft_tmp_bytes(module: &Module<BE>, cnv_offset: usize, res_size: usize, a_size: usize, b_size: usize) -> usize;
1116
1117    fn cnv_by_const_apply_tmp_bytes(
1118        module: &Module<BE>,
1119        cnv_offset: usize,
1120        res_size: usize,
1121        a_size: usize,
1122        b_size: usize,
1123    ) -> usize;
1124
1125    #[allow(clippy::too_many_arguments)]
1126    fn cnv_by_const_apply(
1127        module: &Module<BE>,
1128        cnv_offset: usize,
1129        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
1130        res_col: usize,
1131        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1132        a_col: usize,
1133        b: &crate::layouts::VecZnxBackendRef<'_, BE>,
1134        b_col: usize,
1135        b_coeff: usize,
1136        scratch: &mut ScratchArena<'_, BE>,
1137    );
1138
1139    /// `res[res_col] +=` the [`Self::cnv_by_const_apply`] result; limbs the
1140    /// convolution would zero-fill are left untouched.
1141    #[allow(clippy::too_many_arguments)]
1142    fn cnv_by_const_apply_add(
1143        module: &Module<BE>,
1144        cnv_offset: usize,
1145        res: &mut crate::layouts::VecZnxBigBackendMut<'_, BE>,
1146        res_col: usize,
1147        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1148        a_col: usize,
1149        b: &crate::layouts::VecZnxBackendRef<'_, BE>,
1150        b_col: usize,
1151        b_coeff: usize,
1152        scratch: &mut ScratchArena<'_, BE>,
1153    );
1154
1155    #[allow(clippy::too_many_arguments)]
1156    fn cnv_apply_dft(
1157        module: &Module<BE>,
1158        cnv_offset: usize,
1159        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1160        res_col: usize,
1161        a: &crate::layouts::CnvPVecLBackendRef<'_, BE>,
1162        a_col: usize,
1163        b: &crate::layouts::CnvPVecRBackendRef<'_, BE>,
1164        b_col: usize,
1165        scratch: &mut ScratchArena<'_, BE>,
1166    );
1167
1168    // Lazy convolution used by glwe_mul_plain; defaults delegate to the eager path.
1169    fn cnv_prepare_left_lazy_tmp_bytes(module: &Module<BE>, res_size: usize, a_size: usize) -> usize {
1170        Self::cnv_prepare_left_tmp_bytes(module, res_size, a_size)
1171    }
1172
1173    fn cnv_prepare_left_lazy(
1174        module: &Module<BE>,
1175        res: &mut crate::layouts::CnvPVecLBackendMut<'_, BE>,
1176        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1177        mask: i64,
1178        scratch: &mut ScratchArena<'_, BE>,
1179    ) {
1180        Self::cnv_prepare_left(module, res, a, mask, scratch);
1181    }
1182
1183    fn cnv_prepare_right_lazy_tmp_bytes(module: &Module<BE>, res_size: usize, a_size: usize) -> usize {
1184        Self::cnv_prepare_right_tmp_bytes(module, res_size, a_size)
1185    }
1186
1187    fn cnv_prepare_right_lazy(
1188        module: &Module<BE>,
1189        res: &mut crate::layouts::CnvPVecRBackendMut<'_, BE>,
1190        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1191        mask: i64,
1192        scratch: &mut ScratchArena<'_, BE>,
1193    ) {
1194        Self::cnv_prepare_right(module, res, a, mask, scratch);
1195    }
1196
1197    fn cnv_apply_dft_lazy_tmp_bytes(
1198        module: &Module<BE>,
1199        cnv_offset: usize,
1200        res_size: usize,
1201        a_size: usize,
1202        b_size: usize,
1203    ) -> usize {
1204        Self::cnv_apply_dft_tmp_bytes(module, cnv_offset, res_size, a_size, b_size)
1205    }
1206
1207    #[allow(clippy::too_many_arguments)]
1208    fn cnv_apply_dft_lazy(
1209        module: &Module<BE>,
1210        cnv_offset: usize,
1211        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1212        res_col: usize,
1213        a: &crate::layouts::CnvPVecLBackendRef<'_, BE>,
1214        a_col: usize,
1215        b: &crate::layouts::CnvPVecRBackendRef<'_, BE>,
1216        b_col: usize,
1217        scratch: &mut ScratchArena<'_, BE>,
1218    ) {
1219        Self::cnv_apply_dft(module, cnv_offset, res, res_col, a, a_col, b, b_col, scratch);
1220    }
1221
1222    #[allow(clippy::too_many_arguments)]
1223    fn cnv_apply_dft_accumulate(
1224        module: &Module<BE>,
1225        cnv_offset: usize,
1226        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1227        res_col: usize,
1228        a: &crate::layouts::CnvPVecLBackendRef<'_, BE>,
1229        a_col: usize,
1230        b: &crate::layouts::CnvPVecRBackendRef<'_, BE>,
1231        b_col: usize,
1232        scratch: &mut ScratchArena<'_, BE>,
1233    );
1234
1235    /// Returns scratch bytes required for [`HalConvolutionImpl::cnv_accumulate_dft`].
1236    ///
1237    /// The default sizes the per-term fallback (one `cnv_apply_dft` /
1238    /// `cnv_apply_dft_accumulate` scratch). Backends with a fused kernel should
1239    /// override both methods together.
1240    fn cnv_accumulate_dft_tmp_bytes(
1241        module: &Module<BE>,
1242        cnv_offset: usize,
1243        res_size: usize,
1244        a_size: usize,
1245        b_size: usize,
1246    ) -> usize {
1247        Self::cnv_apply_dft_tmp_bytes(module, cnv_offset, res_size, a_size, b_size)
1248    }
1249
1250    /// Computes `res[res_col] = Σ_t a_t ⊛ b_t` (overwriting).
1251    ///
1252    /// The default implementation overwrites with the first term
1253    /// (`cnv_apply_dft`, which also zeroes the limbs past the convolution
1254    /// bound) and folds the remaining terms with `cnv_apply_dft_accumulate`.
1255    /// Backends should override it with a fused kernel that keeps the lazy
1256    /// accumulators live across terms.
1257    fn cnv_accumulate_dft<'a>(
1258        module: &Module<BE>,
1259        cnv_offset: usize,
1260        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1261        res_col: usize,
1262        terms: &[crate::layouts::CnvDftAccTerm<'a, BE>],
1263        scratch: &mut ScratchArena<'_, BE>,
1264    ) where
1265        BE: HalVecZnxDftImpl<BE> + 'a,
1266    {
1267        if terms.is_empty() {
1268            <BE as HalVecZnxDftImpl<BE>>::vec_znx_dft_zero(module, res, res_col);
1269            return;
1270        }
1271        for (idx, term) in terms.iter().enumerate() {
1272            if idx == 0 {
1273                Self::cnv_apply_dft(
1274                    module, cnv_offset, res, res_col, &term.a, term.a_col, &term.b, term.b_col, scratch,
1275                );
1276            } else {
1277                Self::cnv_apply_dft_accumulate(
1278                    module, cnv_offset, res, res_col, &term.a, term.a_col, &term.b, term.b_col, scratch,
1279                );
1280            }
1281        }
1282    }
1283
1284    fn cnv_pairwise_apply_dft_tmp_bytes(
1285        module: &Module<BE>,
1286        cnv_offset: usize,
1287        res_size: usize,
1288        a_size: usize,
1289        b_size: usize,
1290    ) -> usize;
1291
1292    #[allow(clippy::too_many_arguments)]
1293    fn cnv_pairwise_apply_dft(
1294        module: &Module<BE>,
1295        cnv_offset: usize,
1296        res: &mut crate::layouts::VecZnxDftBackendMut<'_, BE>,
1297        res_col: usize,
1298        a: &crate::layouts::CnvPVecLBackendRef<'_, BE>,
1299        b: &crate::layouts::CnvPVecRBackendRef<'_, BE>,
1300        i: usize,
1301        j: usize,
1302        scratch: &mut ScratchArena<'_, BE>,
1303    );
1304
1305    fn cnv_prepare_self_tmp_bytes(module: &Module<BE>, res_size: usize, a_size: usize) -> usize;
1306
1307    fn cnv_prepare_self(
1308        module: &Module<BE>,
1309        left: &mut crate::layouts::CnvPVecLBackendMut<'_, BE>,
1310        right: &mut crate::layouts::CnvPVecRBackendMut<'_, BE>,
1311        a: &crate::layouts::VecZnxBackendRef<'_, BE>,
1312        mask: i64,
1313        scratch: &mut ScratchArena<'_, BE>,
1314    );
1315}