arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-backend/src/cpu_fft64_avx/module.rs
poulpy-backend/src/cpu_fft64_avx/module.rsRaw
  1use std::ptr::NonNull;
  2
  3use poulpy_hal::{
  4    layouts::{Backend, Module},
  5    oep::ModuleNewImpl,
  6    reference::{
  7        fft64::{
  8            reim::{
  9                ReimAdd, ReimAddInplace, ReimAddMul, ReimCopy, ReimDFTExecute, ReimFFTTable, ReimFromZnx, ReimIFFTTable, ReimMul,
 10                ReimMulInplace, ReimNegate, ReimNegateInplace, ReimSub, ReimSubInplace, ReimSubNegateInplace, ReimToZnx,
 11                ReimToZnxInplace, ReimZero, reim_copy_ref, reim_zero_ref,
 12            },
 13            reim4::{
 14                Reim4Extract1Blk, Reim4Mat1ColProd, Reim4Mat2Cols2ndColProd, Reim4Mat2ColsProd, Reim4Save1Blk, Reim4Save2Blks,
 15            },
 16        },
 17        znx::{
 18            ZnxAdd, ZnxAddInplace, ZnxAutomorphism, ZnxCopy, ZnxExtractDigitAddMul, ZnxMulAddPowerOfTwo, ZnxMulPowerOfTwo,
 19            ZnxMulPowerOfTwoInplace, ZnxNegate, ZnxNegateInplace, ZnxNormalizeDigit, ZnxNormalizeFinalStep,
 20            ZnxNormalizeFinalStepInplace, ZnxNormalizeFirstStep, ZnxNormalizeFirstStepCarryOnly, ZnxNormalizeFirstStepInplace,
 21            ZnxNormalizeMiddleStep, ZnxNormalizeMiddleStepCarryOnly, ZnxNormalizeMiddleStepInplace, ZnxRotate, ZnxSub,
 22            ZnxSubInplace, ZnxSubNegateInplace, ZnxSwitchRing, ZnxZero, znx_copy_ref, znx_rotate, znx_zero_ref,
 23        },
 24    },
 25};
 26
 27use crate::cpu_fft64_avx::{
 28    FFT64Avx,
 29    reim::{
 30        ReimFFTAvx, ReimIFFTAvx, reim_add_avx2_fma, reim_add_inplace_avx2_fma, reim_addmul_avx2_fma, reim_from_znx_i64_bnd50_fma,
 31        reim_mul_avx2_fma, reim_mul_inplace_avx2_fma, reim_negate_avx2_fma, reim_negate_inplace_avx2_fma, reim_sub_avx2_fma,
 32        reim_sub_inplace_avx2_fma, reim_sub_negate_inplace_avx2_fma, reim_to_znx_i64_inplace_bnd63_avx2_fma,
 33    },
 34    reim_to_znx_i64_bnd63_avx2_fma,
 35    reim4::{
 36        reim4_extract_1blk_from_reim_avx, reim4_save_1blk_to_reim_avx, reim4_save_2blk_to_reim_avx,
 37        reim4_vec_mat1col_product_avx, reim4_vec_mat2cols_2ndcol_product_avx, reim4_vec_mat2cols_product_avx,
 38    },
 39    znx_avx::{
 40        znx_add_avx, znx_add_inplace_avx, znx_automorphism_avx, znx_extract_digit_addmul_avx, znx_mul_add_power_of_two_avx,
 41        znx_mul_power_of_two_avx, znx_mul_power_of_two_inplace_avx, znx_negate_avx, znx_negate_inplace_avx,
 42        znx_normalize_digit_avx, znx_normalize_final_step_avx, znx_normalize_final_step_inplace_avx,
 43        znx_normalize_first_step_avx, znx_normalize_first_step_carry_only_avx, znx_normalize_first_step_inplace_avx,
 44        znx_normalize_middle_step_avx, znx_normalize_middle_step_carry_only_avx, znx_normalize_middle_step_inplace_avx,
 45        znx_sub_avx, znx_sub_inplace_avx, znx_sub_negate_inplace_avx, znx_switch_ring_avx,
 46    },
 47};
 48
 49#[repr(C)]
 50pub struct FFT64AvxHandle {
 51    table_fft: ReimFFTTable<f64>,
 52    table_ifft: ReimIFFTTable<f64>,
 53}
 54
 55impl Backend for FFT64Avx {
 56    type ScalarPrep = f64;
 57    type ScalarBig = i64;
 58    type Handle = FFT64AvxHandle;
 59    unsafe fn destroy(handle: NonNull<Self::Handle>) {
 60        unsafe {
 61            drop(Box::from_raw(handle.as_ptr()));
 62        }
 63    }
 64
 65    fn layout_big_word_count() -> usize {
 66        1
 67    }
 68
 69    fn layout_prep_word_count() -> usize {
 70        1
 71    }
 72}
 73
 74unsafe impl ModuleNewImpl<Self> for FFT64Avx {
 75    fn new_impl(n: u64) -> Module<Self> {
 76        if !std::arch::is_x86_feature_detected!("avx")
 77            || !std::arch::is_x86_feature_detected!("avx2")
 78            || !std::arch::is_x86_feature_detected!("fma")
 79        {
 80            panic!("arch must support avx2, avx and fma")
 81        }
 82
 83        let handle: FFT64AvxHandle = FFT64AvxHandle {
 84            table_fft: ReimFFTTable::new(n as usize >> 1),
 85            table_ifft: ReimIFFTTable::new(n as usize >> 1),
 86        };
 87        // Leak Box to get a stable NonNull pointer
 88        let ptr: NonNull<FFT64AvxHandle> = NonNull::from(Box::leak(Box::new(handle)));
 89        unsafe { Module::from_nonnull(ptr, n) }
 90    }
 91}
 92
 93pub trait FFT64ModuleHandle {
 94    fn get_fft_table(&self) -> &ReimFFTTable<f64>;
 95    fn get_ifft_table(&self) -> &ReimIFFTTable<f64>;
 96}
 97
 98impl FFT64ModuleHandle for Module<FFT64Avx> {
 99    fn get_fft_table(&self) -> &ReimFFTTable<f64> {
100        let h: &FFT64AvxHandle = unsafe { &*self.ptr() };
101        &h.table_fft
102    }
103    fn get_ifft_table(&self) -> &ReimIFFTTable<f64> {
104        let h: &FFT64AvxHandle = unsafe { &*self.ptr() };
105        &h.table_ifft
106    }
107}
108
109impl ZnxAdd for FFT64Avx {
110    #[inline(always)]
111    fn znx_add(res: &mut [i64], a: &[i64], b: &[i64]) {
112        unsafe {
113            znx_add_avx(res, a, b);
114        }
115    }
116}
117
118impl ZnxAddInplace for FFT64Avx {
119    #[inline(always)]
120    fn znx_add_inplace(res: &mut [i64], a: &[i64]) {
121        unsafe {
122            znx_add_inplace_avx(res, a);
123        }
124    }
125}
126
127impl ZnxSub for FFT64Avx {
128    #[inline(always)]
129    fn znx_sub(res: &mut [i64], a: &[i64], b: &[i64]) {
130        unsafe {
131            znx_sub_avx(res, a, b);
132        }
133    }
134}
135
136impl ZnxSubInplace for FFT64Avx {
137    #[inline(always)]
138    fn znx_sub_inplace(res: &mut [i64], a: &[i64]) {
139        unsafe {
140            znx_sub_inplace_avx(res, a);
141        }
142    }
143}
144
145impl ZnxSubNegateInplace for FFT64Avx {
146    #[inline(always)]
147    fn znx_sub_negate_inplace(res: &mut [i64], a: &[i64]) {
148        unsafe {
149            znx_sub_negate_inplace_avx(res, a);
150        }
151    }
152}
153
154impl ZnxAutomorphism for FFT64Avx {
155    #[inline(always)]
156    fn znx_automorphism(p: i64, res: &mut [i64], a: &[i64]) {
157        unsafe {
158            znx_automorphism_avx(p, res, a);
159        }
160    }
161}
162
163impl ZnxCopy for FFT64Avx {
164    #[inline(always)]
165    fn znx_copy(res: &mut [i64], a: &[i64]) {
166        znx_copy_ref(res, a);
167    }
168}
169
170impl ZnxNegate for FFT64Avx {
171    #[inline(always)]
172    fn znx_negate(res: &mut [i64], src: &[i64]) {
173        unsafe {
174            znx_negate_avx(res, src);
175        }
176    }
177}
178
179impl ZnxNegateInplace for FFT64Avx {
180    #[inline(always)]
181    fn znx_negate_inplace(res: &mut [i64]) {
182        unsafe {
183            znx_negate_inplace_avx(res);
184        }
185    }
186}
187
188impl ZnxMulAddPowerOfTwo for FFT64Avx {
189    #[inline(always)]
190    fn znx_muladd_power_of_two(k: i64, res: &mut [i64], a: &[i64]) {
191        unsafe {
192            znx_mul_add_power_of_two_avx(k, res, a);
193        }
194    }
195}
196
197impl ZnxMulPowerOfTwo for FFT64Avx {
198    #[inline(always)]
199    fn znx_mul_power_of_two(k: i64, res: &mut [i64], a: &[i64]) {
200        unsafe {
201            znx_mul_power_of_two_avx(k, res, a);
202        }
203    }
204}
205
206impl ZnxMulPowerOfTwoInplace for FFT64Avx {
207    #[inline(always)]
208    fn znx_mul_power_of_two_inplace(k: i64, res: &mut [i64]) {
209        unsafe {
210            znx_mul_power_of_two_inplace_avx(k, res);
211        }
212    }
213}
214
215impl ZnxRotate for FFT64Avx {
216    #[inline(always)]
217    fn znx_rotate(p: i64, res: &mut [i64], src: &[i64]) {
218        znx_rotate::<Self>(p, res, src);
219    }
220}
221
222impl ZnxZero for FFT64Avx {
223    #[inline(always)]
224    fn znx_zero(res: &mut [i64]) {
225        znx_zero_ref(res);
226    }
227}
228
229impl ZnxSwitchRing for FFT64Avx {
230    #[inline(always)]
231    fn znx_switch_ring(res: &mut [i64], a: &[i64]) {
232        unsafe {
233            znx_switch_ring_avx(res, a);
234        }
235    }
236}
237
238impl ZnxNormalizeFinalStep for FFT64Avx {
239    #[inline(always)]
240    fn znx_normalize_final_step(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
241        unsafe {
242            znx_normalize_final_step_avx(base2k, lsh, x, a, carry);
243        }
244    }
245}
246
247impl ZnxNormalizeFinalStepInplace for FFT64Avx {
248    #[inline(always)]
249    fn znx_normalize_final_step_inplace(base2k: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) {
250        unsafe {
251            znx_normalize_final_step_inplace_avx(base2k, lsh, x, carry);
252        }
253    }
254}
255
256impl ZnxNormalizeFirstStep for FFT64Avx {
257    #[inline(always)]
258    fn znx_normalize_first_step(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
259        unsafe {
260            znx_normalize_first_step_avx(base2k, lsh, x, a, carry);
261        }
262    }
263}
264
265impl ZnxNormalizeFirstStepCarryOnly for FFT64Avx {
266    #[inline(always)]
267    fn znx_normalize_first_step_carry_only(base2k: usize, lsh: usize, x: &[i64], carry: &mut [i64]) {
268        unsafe {
269            znx_normalize_first_step_carry_only_avx(base2k, lsh, x, carry);
270        }
271    }
272}
273
274impl ZnxNormalizeFirstStepInplace for FFT64Avx {
275    #[inline(always)]
276    fn znx_normalize_first_step_inplace(base2k: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) {
277        unsafe {
278            znx_normalize_first_step_inplace_avx(base2k, lsh, x, carry);
279        }
280    }
281}
282
283impl ZnxNormalizeMiddleStep for FFT64Avx {
284    #[inline(always)]
285    fn znx_normalize_middle_step(base2k: usize, lsh: usize, x: &mut [i64], a: &[i64], carry: &mut [i64]) {
286        unsafe {
287            znx_normalize_middle_step_avx(base2k, lsh, x, a, carry);
288        }
289    }
290}
291
292impl ZnxNormalizeMiddleStepCarryOnly for FFT64Avx {
293    #[inline(always)]
294    fn znx_normalize_middle_step_carry_only(base2k: usize, lsh: usize, x: &[i64], carry: &mut [i64]) {
295        unsafe {
296            znx_normalize_middle_step_carry_only_avx(base2k, lsh, x, carry);
297        }
298    }
299}
300
301impl ZnxNormalizeMiddleStepInplace for FFT64Avx {
302    #[inline(always)]
303    fn znx_normalize_middle_step_inplace(base2k: usize, lsh: usize, x: &mut [i64], carry: &mut [i64]) {
304        unsafe {
305            znx_normalize_middle_step_inplace_avx(base2k, lsh, x, carry);
306        }
307    }
308}
309
310impl ZnxExtractDigitAddMul for FFT64Avx {
311    #[inline(always)]
312    fn znx_extract_digit_addmul(base2k: usize, lsh: usize, res: &mut [i64], src: &mut [i64]) {
313        unsafe {
314            znx_extract_digit_addmul_avx(base2k, lsh, res, src);
315        }
316    }
317}
318
319impl ZnxNormalizeDigit for FFT64Avx {
320    #[inline(always)]
321    fn znx_normalize_digit(base2k: usize, res: &mut [i64], src: &mut [i64]) {
322        unsafe {
323            znx_normalize_digit_avx(base2k, res, src);
324        }
325    }
326}
327
328impl ReimDFTExecute<ReimFFTTable<f64>, f64> for FFT64Avx {
329    #[inline(always)]
330    fn reim_dft_execute(table: &ReimFFTTable<f64>, data: &mut [f64]) {
331        ReimFFTAvx::reim_dft_execute(table, data);
332    }
333}
334
335impl ReimDFTExecute<ReimIFFTTable<f64>, f64> for FFT64Avx {
336    #[inline(always)]
337    fn reim_dft_execute(table: &ReimIFFTTable<f64>, data: &mut [f64]) {
338        ReimIFFTAvx::reim_dft_execute(table, data);
339    }
340}
341
342impl ReimFromZnx for FFT64Avx {
343    #[inline(always)]
344    fn reim_from_znx(res: &mut [f64], a: &[i64]) {
345        unsafe {
346            reim_from_znx_i64_bnd50_fma(res, a);
347        }
348    }
349}
350
351impl ReimToZnx for FFT64Avx {
352    #[inline(always)]
353    fn reim_to_znx(res: &mut [i64], divisor: f64, a: &[f64]) {
354        unsafe {
355            reim_to_znx_i64_bnd63_avx2_fma(res, divisor, a);
356        }
357    }
358}
359
360impl ReimToZnxInplace for FFT64Avx {
361    #[inline(always)]
362    fn reim_to_znx_inplace(res: &mut [f64], divisor: f64) {
363        unsafe {
364            reim_to_znx_i64_inplace_bnd63_avx2_fma(res, divisor);
365        }
366    }
367}
368
369impl ReimAdd for FFT64Avx {
370    #[inline(always)]
371    fn reim_add(res: &mut [f64], a: &[f64], b: &[f64]) {
372        unsafe {
373            reim_add_avx2_fma(res, a, b);
374        }
375    }
376}
377
378impl ReimAddInplace for FFT64Avx {
379    #[inline(always)]
380    fn reim_add_inplace(res: &mut [f64], a: &[f64]) {
381        unsafe {
382            reim_add_inplace_avx2_fma(res, a);
383        }
384    }
385}
386
387impl ReimSub for FFT64Avx {
388    #[inline(always)]
389    fn reim_sub(res: &mut [f64], a: &[f64], b: &[f64]) {
390        unsafe {
391            reim_sub_avx2_fma(res, a, b);
392        }
393    }
394}
395
396impl ReimSubInplace for FFT64Avx {
397    #[inline(always)]
398    fn reim_sub_inplace(res: &mut [f64], a: &[f64]) {
399        unsafe {
400            reim_sub_inplace_avx2_fma(res, a);
401        }
402    }
403}
404
405impl ReimSubNegateInplace for FFT64Avx {
406    #[inline(always)]
407    fn reim_sub_negate_inplace(res: &mut [f64], a: &[f64]) {
408        unsafe {
409            reim_sub_negate_inplace_avx2_fma(res, a);
410        }
411    }
412}
413
414impl ReimNegate for FFT64Avx {
415    #[inline(always)]
416    fn reim_negate(res: &mut [f64], a: &[f64]) {
417        unsafe {
418            reim_negate_avx2_fma(res, a);
419        }
420    }
421}
422
423impl ReimNegateInplace for FFT64Avx {
424    #[inline(always)]
425    fn reim_negate_inplace(res: &mut [f64]) {
426        unsafe {
427            reim_negate_inplace_avx2_fma(res);
428        }
429    }
430}
431
432impl ReimMul for FFT64Avx {
433    #[inline(always)]
434    fn reim_mul(res: &mut [f64], a: &[f64], b: &[f64]) {
435        unsafe {
436            reim_mul_avx2_fma(res, a, b);
437        }
438    }
439}
440
441impl ReimMulInplace for FFT64Avx {
442    #[inline(always)]
443    fn reim_mul_inplace(res: &mut [f64], a: &[f64]) {
444        unsafe {
445            reim_mul_inplace_avx2_fma(res, a);
446        }
447    }
448}
449
450impl ReimAddMul for FFT64Avx {
451    #[inline(always)]
452    fn reim_addmul(res: &mut [f64], a: &[f64], b: &[f64]) {
453        unsafe {
454            reim_addmul_avx2_fma(res, a, b);
455        }
456    }
457}
458
459impl ReimCopy for FFT64Avx {
460    #[inline(always)]
461    fn reim_copy(res: &mut [f64], a: &[f64]) {
462        reim_copy_ref(res, a);
463    }
464}
465
466impl ReimZero for FFT64Avx {
467    #[inline(always)]
468    fn reim_zero(res: &mut [f64]) {
469        reim_zero_ref(res);
470    }
471}
472
473impl Reim4Extract1Blk for FFT64Avx {
474    #[inline(always)]
475    fn reim4_extract_1blk(m: usize, rows: usize, blk: usize, dst: &mut [f64], src: &[f64]) {
476        unsafe {
477            reim4_extract_1blk_from_reim_avx(m, rows, blk, dst, src);
478        }
479    }
480}
481
482impl Reim4Save1Blk for FFT64Avx {
483    #[inline(always)]
484    fn reim4_save_1blk<const OVERWRITE: bool>(m: usize, blk: usize, dst: &mut [f64], src: &[f64]) {
485        unsafe {
486            reim4_save_1blk_to_reim_avx::<OVERWRITE>(m, blk, dst, src);
487        }
488    }
489}
490
491impl Reim4Save2Blks for FFT64Avx {
492    #[inline(always)]
493    fn reim4_save_2blks<const OVERWRITE: bool>(m: usize, blk: usize, dst: &mut [f64], src: &[f64]) {
494        unsafe {
495            reim4_save_2blk_to_reim_avx::<OVERWRITE>(m, blk, dst, src);
496        }
497    }
498}
499
500impl Reim4Mat1ColProd for FFT64Avx {
501    #[inline(always)]
502    fn reim4_mat1col_prod(nrows: usize, dst: &mut [f64], u: &[f64], v: &[f64]) {
503        unsafe {
504            reim4_vec_mat1col_product_avx(nrows, dst, u, v);
505        }
506    }
507}
508
509impl Reim4Mat2ColsProd for FFT64Avx {
510    #[inline(always)]
511    fn reim4_mat2cols_prod(nrows: usize, dst: &mut [f64], u: &[f64], v: &[f64]) {
512        unsafe {
513            reim4_vec_mat2cols_product_avx(nrows, dst, u, v);
514        }
515    }
516}
517
518impl Reim4Mat2Cols2ndColProd for FFT64Avx {
519    #[inline(always)]
520    fn reim4_mat2cols_2ndcol_prod(nrows: usize, dst: &mut [f64], u: &[f64], v: &[f64]) {
521        unsafe {
522            reim4_vec_mat2cols_2ndcol_product_avx(nrows, dst, u, v);
523        }
524    }
525}