Skip to main content

poulpy_cpu_ref/fft64/
znx.rs

1//! Single ring element (`Z[X]/(X^n+1)`) arithmetic for [`FFT64Ref`](crate::FFT64Ref).
2//!
3//! Implements the `Znx*` traits from `crate::reference::znx`, covering
4//! coefficient-wise addition, subtraction, negation, power-of-two multiplication,
5//! Galois automorphisms (`X -> X^k`), rotation, ring switching, and multi-step
6//! normalization (carry propagation across a base-2^k decomposition).
7//!
8//! These traits are **not** OEP traits (they are not `unsafe trait`) because the
9//! `Znx` operations work on plain `&[i64]` slices with a single canonical memory
10//! layout shared across all backends.
11//!
12//! Every implementation delegates directly to the corresponding `_ref` function
13//! and is marked `#[inline(always)]` to eliminate call overhead.
14
15use crate::reference::znx::{
16    ZnxAdd, ZnxAddAssign, ZnxAutomorphism, ZnxCopy, ZnxExtractDigitAddMul, ZnxMulAddPowerOfTwo, ZnxMulPowerOfTwo,
17    ZnxMulPowerOfTwoAssign, ZnxNegate, ZnxNegateAssign, ZnxNormalizeDigit, ZnxNormalizeFinalStep, ZnxNormalizeFinalStepAssign,
18    ZnxNormalizeFinalStepSub, ZnxNormalizeFirstStep, ZnxNormalizeFirstStepAssign, ZnxNormalizeFirstStepCarryOnly,
19    ZnxNormalizeMiddleStep, ZnxNormalizeMiddleStepAssign, ZnxNormalizeMiddleStepCarryOnly, ZnxNormalizeMiddleStepSub, ZnxRotate,
20    ZnxSub, ZnxSubAssign, ZnxSubNegateAssign, ZnxSwitchRing, ZnxZero, znx_add_assign_ref, znx_add_ref, znx_automorphism_ref,
21    znx_copy_ref, znx_extract_digit_addmul_ref, znx_mul_add_power_of_two_ref, znx_mul_power_of_two_assign_ref,
22    znx_mul_power_of_two_ref, znx_negate_assign_ref, znx_negate_ref, znx_normalize_digit_ref,
23    znx_normalize_final_step_assign_ref, znx_normalize_final_step_ref, znx_normalize_final_step_sub_ref,
24    znx_normalize_first_step_assign_ref, znx_normalize_first_step_carry_only_ref, znx_normalize_first_step_ref,
25    znx_normalize_middle_step_assign_ref, znx_normalize_middle_step_carry_only_ref, znx_normalize_middle_step_ref,
26    znx_normalize_middle_step_sub_ref, znx_rotate, znx_sub_assign_ref, znx_sub_negate_assign_ref, znx_sub_ref,
27    znx_switch_ring_ref, znx_zero_ref,
28};
29
30use super::FFT64Ref;
31
32impl ZnxAdd for FFT64Ref {
33    #[inline(always)]
34    fn znx_add(res: &mut [i64], a: &[i64], b: &[i64]) {
35        znx_add_ref(res, a, b);
36    }
37}
38
39impl ZnxAddAssign for FFT64Ref {
40    #[inline(always)]
41    fn znx_add_assign(res: &mut [i64], a: &[i64]) {
42        znx_add_assign_ref(res, a);
43    }
44}
45
46impl ZnxSub for FFT64Ref {
47    #[inline(always)]
48    fn znx_sub(res: &mut [i64], a: &[i64], b: &[i64]) {
49        znx_sub_ref(res, a, b);
50    }
51}
52
53impl ZnxSubAssign for FFT64Ref {
54    #[inline(always)]
55    fn znx_sub_assign(res: &mut [i64], a: &[i64]) {
56        znx_sub_assign_ref(res, a);
57    }
58}
59
60impl ZnxSubNegateAssign for FFT64Ref {
61    #[inline(always)]
62    fn znx_sub_negate_assign(res: &mut [i64], a: &[i64]) {
63        znx_sub_negate_assign_ref(res, a);
64    }
65}
66
67impl ZnxMulAddPowerOfTwo for FFT64Ref {
68    #[inline(always)]
69    fn znx_muladd_power_of_two(k: i64, res: &mut [i64], a: &[i64]) {
70        znx_mul_add_power_of_two_ref(k, res, a);
71    }
72}
73
74impl ZnxMulPowerOfTwo for FFT64Ref {
75    #[inline(always)]
76    fn znx_mul_power_of_two(k: i64, res: &mut [i64], a: &[i64]) {
77        znx_mul_power_of_two_ref(k, res, a);
78    }
79}
80
81impl ZnxMulPowerOfTwoAssign for FFT64Ref {
82    #[inline(always)]
83    fn znx_mul_power_of_two_assign(k: i64, res: &mut [i64]) {
84        znx_mul_power_of_two_assign_ref(k, res);
85    }
86}
87
88impl ZnxAutomorphism for FFT64Ref {
89    #[inline(always)]
90    fn znx_automorphism(p: i64, res: &mut [i64], a: &[i64]) {
91        znx_automorphism_ref(p, res, a);
92    }
93}
94
95impl ZnxCopy for FFT64Ref {
96    #[inline(always)]
97    fn znx_copy(res: &mut [i64], a: &[i64]) {
98        znx_copy_ref(res, a);
99    }
100}
101
102impl ZnxNegate for FFT64Ref {
103    #[inline(always)]
104    fn znx_negate(res: &mut [i64], src: &[i64]) {
105        znx_negate_ref(res, src);
106    }
107}
108
109impl ZnxNegateAssign for FFT64Ref {
110    #[inline(always)]
111    fn znx_negate_assign(res: &mut [i64]) {
112        znx_negate_assign_ref(res);
113    }
114}
115
116impl ZnxRotate for FFT64Ref {
117    #[inline(always)]
118    fn znx_rotate(p: i64, res: &mut [i64], src: &[i64]) {
119        znx_rotate::<Self>(p, res, src);
120    }
121}
122
123impl ZnxZero for FFT64Ref {
124    #[inline(always)]
125    fn znx_zero(res: &mut [i64]) {
126        znx_zero_ref(res);
127    }
128}
129
130impl ZnxSwitchRing for FFT64Ref {
131    #[inline(always)]
132    fn znx_switch_ring(res: &mut [i64], a: &[i64]) {
133        znx_switch_ring_ref(res, a);
134    }
135}
136
137impl ZnxNormalizeFirstStep for FFT64Ref {
138    #[inline(always)]
139    fn znx_normalize_first_step<const OVERWRITE: bool>(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
140        znx_normalize_first_step_ref::<OVERWRITE>(base2k, lsh, x, a, carry);
141    }
142}
143
144impl ZnxNormalizeMiddleStep for FFT64Ref {
145    #[inline(always)]
146    fn znx_normalize_middle_step<const OVERWRITE: bool>(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
147        znx_normalize_middle_step_ref::<OVERWRITE>(base2k, lsh, x, a, carry);
148    }
149}
150
151impl ZnxNormalizeFinalStep for FFT64Ref {
152    #[inline(always)]
153    fn znx_normalize_final_step<const OVERWRITE: bool>(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
154        znx_normalize_final_step_ref::<OVERWRITE>(base2k, lsh, x, a, carry);
155    }
156}
157
158impl ZnxNormalizeMiddleStepSub for FFT64Ref {
159    #[inline(always)]
160    fn znx_normalize_middle_step_sub(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
161        znx_normalize_middle_step_sub_ref(base2k, lsh, x, a, carry);
162    }
163}
164
165impl ZnxNormalizeFinalStepSub for FFT64Ref {
166    #[inline(always)]
167    fn znx_normalize_final_step_sub(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
168        znx_normalize_final_step_sub_ref(base2k, lsh, x, a, carry);
169    }
170}
171
172impl ZnxNormalizeFinalStepAssign for FFT64Ref {
173    #[inline(always)]
174    fn znx_normalize_final_step_assign(base2k: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) {
175        znx_normalize_final_step_assign_ref(base2k, lsh, x, carry);
176    }
177}
178
179impl ZnxNormalizeFirstStepCarryOnly for FFT64Ref {
180    #[inline(always)]
181    fn znx_normalize_first_step_carry_only(base2k: usize, lsh: usize, x: &[i64], carry: &mut [i64]) {
182        znx_normalize_first_step_carry_only_ref(base2k, lsh, x, carry);
183    }
184}
185
186impl ZnxNormalizeFirstStepAssign for FFT64Ref {
187    #[inline(always)]
188    fn znx_normalize_first_step_assign(base2k: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) {
189        znx_normalize_first_step_assign_ref(base2k, lsh, x, carry);
190    }
191}
192
193impl ZnxNormalizeMiddleStepCarryOnly for FFT64Ref {
194    #[inline(always)]
195    fn znx_normalize_middle_step_carry_only(base2k: usize, lsh: usize, x: &[i64], carry: &mut [i64]) {
196        znx_normalize_middle_step_carry_only_ref(base2k, lsh, x, carry);
197    }
198}
199
200impl ZnxNormalizeMiddleStepAssign for FFT64Ref {
201    #[inline(always)]
202    fn znx_normalize_middle_step_assign(base2k: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) {
203        znx_normalize_middle_step_assign_ref(base2k, lsh, x, carry);
204    }
205}
206
207impl ZnxExtractDigitAddMul for FFT64Ref {
208    #[inline(always)]
209    fn znx_extract_digit_addmul(base2k: usize, lsh: usize, res: &mut [i64], src: &mut [i64]) {
210        znx_extract_digit_addmul_ref(base2k, lsh, res, src);
211    }
212}
213
214impl ZnxNormalizeDigit for FFT64Ref {
215    #[inline(always)]
216    fn znx_normalize_digit(base2k: usize, res: &mut [i64], src: &mut [i64]) {
217        znx_normalize_digit_ref(base2k, res, src);
218    }
219}