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