arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-hal/src/reference/fft64/vec_znx_dft.rs
poulpy-hal/src/reference/fft64/vec_znx_dft.rsRaw
  1use bytemuck::cast_slice_mut;
  2
  3use crate::{
  4    layouts::{
  5        Backend, Data, VecZnx, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef, ZnxInfos,
  6        ZnxView, ZnxViewMut,
  7    },
  8    reference::{
  9        fft64::reim::{
 10            ReimAdd, ReimAddInplace, ReimCopy, ReimDFTExecute, ReimFFTTable, ReimFromZnx, ReimIFFTTable, ReimNegate,
 11            ReimNegateInplace, ReimSub, ReimSubInplace, ReimSubNegateInplace, ReimToZnx, ReimToZnxInplace, ReimZero,
 12        },
 13        znx::ZnxZero,
 14    },
 15};
 16
 17pub fn vec_znx_dft_add<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
 18where
 19    BE: Backend<ScalarPrep = f64> + ReimAdd + ReimCopy + ReimZero,
 20    R: VecZnxDftToMut<BE>,
 21    A: VecZnxDftToRef<BE>,
 22    B: VecZnxDftToRef<BE>,
 23{
 24    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
 25    let a: VecZnxDft<&[u8], BE> = a.to_ref();
 26    let b: VecZnxDft<&[u8], BE> = b.to_ref();
 27
 28    #[cfg(debug_assertions)]
 29    {
 30        assert_eq!(a.n(), res.n());
 31        assert_eq!(b.n(), res.n());
 32    }
 33
 34    let res_size: usize = res.size();
 35    let a_size: usize = a.size();
 36    let b_size: usize = b.size();
 37
 38    if a_size <= b_size {
 39        let sum_size: usize = a_size.min(res_size);
 40        let cpy_size: usize = b_size.min(res_size);
 41
 42        for j in 0..sum_size {
 43            BE::reim_add(res.at_mut(res_col, j), a.at(a_col, j), b.at(b_col, j));
 44        }
 45
 46        for j in sum_size..cpy_size {
 47            BE::reim_copy(res.at_mut(res_col, j), b.at(b_col, j));
 48        }
 49
 50        for j in cpy_size..res_size {
 51            BE::reim_zero(res.at_mut(res_col, j));
 52        }
 53    } else {
 54        let sum_size: usize = b_size.min(res_size);
 55        let cpy_size: usize = a_size.min(res_size);
 56
 57        for j in 0..sum_size {
 58            BE::reim_add(res.at_mut(res_col, j), a.at(a_col, j), b.at(b_col, j));
 59        }
 60
 61        for j in sum_size..cpy_size {
 62            BE::reim_copy(res.at_mut(res_col, j), a.at(a_col, j));
 63        }
 64
 65        for j in cpy_size..res_size {
 66            BE::reim_zero(res.at_mut(res_col, j));
 67        }
 68    }
 69}
 70
 71pub fn vec_znx_dft_add_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
 72where
 73    BE: Backend<ScalarPrep = f64> + ReimAddInplace,
 74    R: VecZnxDftToMut<BE>,
 75    A: VecZnxDftToRef<BE>,
 76{
 77    let a: VecZnxDft<&[u8], BE> = a.to_ref();
 78    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
 79
 80    #[cfg(debug_assertions)]
 81    {
 82        assert_eq!(a.n(), res.n());
 83    }
 84
 85    let res_size: usize = res.size();
 86    let a_size: usize = a.size();
 87
 88    let sum_size: usize = a_size.min(res_size);
 89
 90    for j in 0..sum_size {
 91        BE::reim_add_inplace(res.at_mut(res_col, j), a.at(a_col, j));
 92    }
 93}
 94
 95pub fn vec_znx_dft_copy<R, A, BE>(step: usize, offset: usize, res: &mut R, res_col: usize, a: &A, a_col: usize)
 96where
 97    BE: Backend<ScalarPrep = f64> + ReimCopy + ReimZero,
 98    R: VecZnxDftToMut<BE>,
 99    A: VecZnxDftToRef<BE>,
100{
101    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
102    let a: VecZnxDft<&[u8], BE> = a.to_ref();
103
104    #[cfg(debug_assertions)]
105    {
106        assert_eq!(res.n(), a.n())
107    }
108
109    let steps: usize = a.size().div_ceil(step);
110    let min_steps: usize = res.size().min(steps);
111
112    (0..min_steps).for_each(|j| {
113        let limb: usize = offset + j * step;
114        if limb < a.size() {
115            BE::reim_copy(res.at_mut(res_col, j), a.at(a_col, limb));
116        }
117    });
118    (min_steps..res.size()).for_each(|j| {
119        BE::reim_zero(res.at_mut(res_col, j));
120    })
121}
122
123pub fn vec_znx_dft_apply<R, A, BE>(
124    table: &ReimFFTTable<f64>,
125    step: usize,
126    offset: usize,
127    res: &mut R,
128    res_col: usize,
129    a: &A,
130    a_col: usize,
131) where
132    BE: Backend<ScalarPrep = f64> + ReimDFTExecute<ReimFFTTable<f64>, f64> + ReimFromZnx + ReimZero,
133    R: VecZnxDftToMut<BE>,
134    A: VecZnxToRef,
135{
136    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
137    let a: VecZnx<&[u8]> = a.to_ref();
138
139    #[cfg(debug_assertions)]
140    {
141        assert!(step > 0);
142        assert_eq!(table.m() << 1, res.n());
143        assert_eq!(a.n(), res.n());
144    }
145
146    let a_size: usize = a.size();
147    let res_size: usize = res.size();
148
149    let steps: usize = a_size.div_ceil(step);
150    let min_steps: usize = res_size.min(steps);
151
152    for j in 0..min_steps {
153        let limb = offset + j * step;
154        if limb < a_size {
155            BE::reim_from_znx(res.at_mut(res_col, j), a.at(a_col, limb));
156            BE::reim_dft_execute(table, res.at_mut(res_col, j));
157        }
158    }
159
160    (min_steps..res.size()).for_each(|j| {
161        BE::reim_zero(res.at_mut(res_col, j));
162    });
163}
164
165pub fn vec_znx_idft_apply<R, A, BE>(table: &ReimIFFTTable<f64>, res: &mut R, res_col: usize, a: &A, a_col: usize)
166where
167    BE: Backend<ScalarPrep = f64, ScalarBig = i64>
168        + ReimDFTExecute<ReimIFFTTable<f64>, f64>
169        + ReimCopy
170        + ReimToZnxInplace
171        + ZnxZero,
172    R: VecZnxBigToMut<BE>,
173    A: VecZnxDftToRef<BE>,
174{
175    let mut res: VecZnxBig<&mut [u8], BE> = res.to_mut();
176    let a: VecZnxDft<&[u8], BE> = a.to_ref();
177
178    #[cfg(debug_assertions)]
179    {
180        assert_eq!(table.m() << 1, res.n());
181        assert_eq!(a.n(), res.n());
182    }
183
184    let res_size: usize = res.size();
185    let min_size: usize = res_size.min(a.size());
186
187    let divisor: f64 = table.m() as f64;
188
189    for j in 0..min_size {
190        let res_slice_f64: &mut [f64] = cast_slice_mut(res.at_mut(res_col, j));
191        BE::reim_copy(res_slice_f64, a.at(a_col, j));
192        BE::reim_dft_execute(table, res_slice_f64);
193        BE::reim_to_znx_inplace(res_slice_f64, divisor);
194    }
195
196    for j in min_size..res_size {
197        BE::znx_zero(res.at_mut(res_col, j));
198    }
199}
200
201pub fn vec_znx_idft_apply_tmpa<R, A, BE>(table: &ReimIFFTTable<f64>, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
202where
203    BE: Backend<ScalarPrep = f64, ScalarBig = i64> + ReimDFTExecute<ReimIFFTTable<f64>, f64> + ReimToZnx + ZnxZero,
204    R: VecZnxBigToMut<BE>,
205    A: VecZnxDftToMut<BE>,
206{
207    let mut res: VecZnxBig<&mut [u8], BE> = res.to_mut();
208    let mut a: VecZnxDft<&mut [u8], BE> = a.to_mut();
209
210    #[cfg(debug_assertions)]
211    {
212        assert_eq!(table.m() << 1, res.n());
213        assert_eq!(a.n(), res.n());
214    }
215
216    let res_size = res.size();
217    let min_size: usize = res_size.min(a.size());
218
219    let divisor: f64 = table.m() as f64;
220
221    for j in 0..min_size {
222        BE::reim_dft_execute(table, a.at_mut(a_col, j));
223        BE::reim_to_znx(res.at_mut(res_col, j), divisor, a.at(a_col, j));
224    }
225
226    for j in min_size..res_size {
227        BE::znx_zero(res.at_mut(res_col, j));
228    }
229}
230
231pub fn vec_znx_idft_apply_consume<D: Data, BE>(table: &ReimIFFTTable<f64>, mut res: VecZnxDft<D, BE>) -> VecZnxBig<D, BE>
232where
233    BE: Backend<ScalarPrep = f64, ScalarBig = i64> + ReimDFTExecute<ReimIFFTTable<f64>, f64> + ReimToZnxInplace,
234    VecZnxDft<D, BE>: VecZnxDftToMut<BE>,
235{
236    {
237        let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
238
239        #[cfg(debug_assertions)]
240        {
241            assert_eq!(table.m() << 1, res.n());
242        }
243
244        let divisor: f64 = table.m() as f64;
245
246        for i in 0..res.cols() {
247            for j in 0..res.size() {
248                BE::reim_dft_execute(table, res.at_mut(i, j));
249                BE::reim_to_znx_inplace(res.at_mut(i, j), divisor);
250            }
251        }
252    }
253
254    res.into_big()
255}
256
257pub fn vec_znx_dft_sub<R, A, B, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
258where
259    BE: Backend<ScalarPrep = f64> + ReimSub + ReimNegate + ReimZero + ReimCopy,
260    R: VecZnxDftToMut<BE>,
261    A: VecZnxDftToRef<BE>,
262    B: VecZnxDftToRef<BE>,
263{
264    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
265    let a: VecZnxDft<&[u8], BE> = a.to_ref();
266    let b: VecZnxDft<&[u8], BE> = b.to_ref();
267
268    #[cfg(debug_assertions)]
269    {
270        assert_eq!(a.n(), res.n());
271        assert_eq!(b.n(), res.n());
272    }
273
274    let res_size: usize = res.size();
275    let a_size: usize = a.size();
276    let b_size: usize = b.size();
277
278    if a_size <= b_size {
279        let sum_size: usize = a_size.min(res_size);
280        let cpy_size: usize = b_size.min(res_size);
281
282        for j in 0..sum_size {
283            BE::reim_sub(res.at_mut(res_col, j), a.at(a_col, j), b.at(b_col, j));
284        }
285
286        for j in sum_size..cpy_size {
287            BE::reim_negate(res.at_mut(res_col, j), b.at(b_col, j));
288        }
289
290        for j in cpy_size..res_size {
291            BE::reim_zero(res.at_mut(res_col, j));
292        }
293    } else {
294        let sum_size: usize = b_size.min(res_size);
295        let cpy_size: usize = a_size.min(res_size);
296
297        for j in 0..sum_size {
298            BE::reim_sub(res.at_mut(res_col, j), a.at(a_col, j), b.at(b_col, j));
299        }
300
301        for j in sum_size..cpy_size {
302            BE::reim_copy(res.at_mut(res_col, j), a.at(a_col, j));
303        }
304
305        for j in cpy_size..res_size {
306            BE::reim_zero(res.at_mut(res_col, j));
307        }
308    }
309}
310
311pub fn vec_znx_dft_sub_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
312where
313    BE: Backend<ScalarPrep = f64> + ReimSubInplace,
314    R: VecZnxDftToMut<BE>,
315    A: VecZnxDftToRef<BE>,
316{
317    let a: VecZnxDft<&[u8], BE> = a.to_ref();
318    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
319
320    #[cfg(debug_assertions)]
321    {
322        assert_eq!(a.n(), res.n());
323    }
324
325    let res_size: usize = res.size();
326    let a_size: usize = a.size();
327
328    let sum_size: usize = a_size.min(res_size);
329
330    for j in 0..sum_size {
331        BE::reim_sub_inplace(res.at_mut(res_col, j), a.at(a_col, j));
332    }
333}
334
335pub fn vec_znx_dft_sub_negate_inplace<R, A, BE>(res: &mut R, res_col: usize, a: &A, a_col: usize)
336where
337    BE: Backend<ScalarPrep = f64> + ReimSubNegateInplace + ReimNegateInplace,
338    R: VecZnxDftToMut<BE>,
339    A: VecZnxDftToRef<BE>,
340{
341    let a: VecZnxDft<&[u8], BE> = a.to_ref();
342    let mut res: VecZnxDft<&mut [u8], BE> = res.to_mut();
343
344    #[cfg(debug_assertions)]
345    {
346        assert_eq!(a.n(), res.n());
347    }
348
349    let res_size: usize = res.size();
350    let a_size: usize = a.size();
351
352    let sum_size: usize = a_size.min(res_size);
353
354    for j in 0..sum_size {
355        BE::reim_sub_negate_inplace(res.at_mut(res_col, j), a.at(a_col, j));
356    }
357
358    for j in sum_size..res_size {
359        BE::reim_negate_inplace(res.at_mut(res_col, j));
360    }
361}
362
363pub fn vec_znx_dft_zero<R, BE>(res: &mut R)
364where
365    R: VecZnxDftToMut<BE>,
366    BE: Backend<ScalarPrep = f64> + ReimZero,
367{
368    BE::reim_zero(res.to_mut().raw_mut());
369}