use poulpy_hal::{ api::{Convolution, ModuleN, ScratchTakeBasic, TakeSlice, VecZnxDftApply, VecZnxDftBytesOf}, layouts::{ Backend, CnvPVecL, CnvPVecLToMut, CnvPVecLToRef, CnvPVecR, CnvPVecRToMut, CnvPVecRToRef, Module, Scratch, VecZnx, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftToMut, VecZnxToRef, ZnxInfos, }, oep::{CnvPVecBytesOfImpl, CnvPVecLAllocImpl, ConvolutionImpl}, reference::fft64::convolution::{ convolution_apply_dft, convolution_apply_dft_tmp_bytes, convolution_by_const_apply, convolution_by_const_apply_tmp_bytes, convolution_pairwise_apply_dft, convolution_pairwise_apply_dft_tmp_bytes, convolution_prepare_left, convolution_prepare_right, }, }; use crate::{FFT64Ref, module::FFT64ModuleHandle}; unsafe impl CnvPVecLAllocImpl for FFT64Ref { fn cnv_pvec_left_alloc_impl(n: usize, cols: usize, size: usize) -> CnvPVecL, Self> { CnvPVecL::alloc(n, cols, size) } fn cnv_pvec_right_alloc_impl(n: usize, cols: usize, size: usize) -> CnvPVecR, Self> { CnvPVecR::alloc(n, cols, size) } } unsafe impl CnvPVecBytesOfImpl for FFT64Ref { fn bytes_of_cnv_pvec_left_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * cols * size * size_of::<::ScalarPrep>() } fn bytes_of_cnv_pvec_right_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * cols * size * size_of::<::ScalarPrep>() } } unsafe impl ConvolutionImpl for FFT64Ref where Module: ModuleN + VecZnxDftBytesOf + VecZnxDftApply, { fn cnv_prepare_left_tmp_bytes_impl(module: &Module, res_size: usize, a_size: usize) -> usize { module.bytes_of_vec_znx_dft(1, res_size.min(a_size)) } fn cnv_prepare_left_impl(module: &Module, res: &mut R, a: &A, scratch: &mut Scratch) where R: CnvPVecLToMut, A: VecZnxToRef, { let res: &mut CnvPVecL<&mut [u8], FFT64Ref> = &mut res.to_mut(); let a: &VecZnx<&[u8]> = &a.to_ref(); let (mut tmp, _) = scratch.take_vec_znx_dft(module, 1, res.size().min(a.size())); convolution_prepare_left(module.get_fft_table(), res, a, &mut tmp); } fn cnv_prepare_right_tmp_bytes_impl(module: &Module, res_size: usize, a_size: usize) -> usize { module.bytes_of_vec_znx_dft(1, res_size.min(a_size)) } fn cnv_prepare_right_impl(module: &Module, res: &mut R, a: &A, scratch: &mut Scratch) where R: CnvPVecRToMut, A: VecZnxToRef, { let res: &mut CnvPVecR<&mut [u8], FFT64Ref> = &mut res.to_mut(); let a: &VecZnx<&[u8]> = &a.to_ref(); let (mut tmp, _) = scratch.take_vec_znx_dft(module, 1, res.size().min(a.size())); convolution_prepare_right(module.get_fft_table(), res, a, &mut tmp); } fn cnv_apply_dft_tmp_bytes_impl( _module: &Module, res_size: usize, _res_offset: usize, a_size: usize, b_size: usize, ) -> usize { convolution_apply_dft_tmp_bytes(res_size, a_size, b_size) } fn cnv_by_const_apply_tmp_bytes_impl( _module: &Module, res_size: usize, _res_offset: usize, a_size: usize, b_size: usize, ) -> usize { convolution_by_const_apply_tmp_bytes(res_size, a_size, b_size) } fn cnv_by_const_apply_impl( module: &Module, res: &mut R, res_offset: usize, res_col: usize, a: &A, a_col: usize, b: &[i64], scratch: &mut Scratch, ) where R: VecZnxBigToMut, A: VecZnxToRef, { let res: &mut VecZnxBig<&mut [u8], Self> = &mut res.to_mut(); let a: &VecZnx<&[u8]> = &a.to_ref(); let (tmp, _) = scratch.take_slice(module.cnv_by_const_apply_tmp_bytes(res.size(), res_offset, a.size(), b.len()) / size_of::()); convolution_by_const_apply(res, res_offset, res_col, a, a_col, b, tmp); } fn cnv_apply_dft_impl( module: &Module, res: &mut R, res_offset: usize, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize, scratch: &mut Scratch, ) where R: VecZnxDftToMut, A: CnvPVecLToRef, B: CnvPVecRToRef, { let res: &mut VecZnxDft<&mut [u8], FFT64Ref> = &mut res.to_mut(); let a: &CnvPVecL<&[u8], FFT64Ref> = &a.to_ref(); let b: &CnvPVecR<&[u8], FFT64Ref> = &b.to_ref(); let (tmp, _) = scratch.take_slice(module.cnv_apply_dft_tmp_bytes(res.size(), res_offset, a.size(), b.size()) / size_of::()); convolution_apply_dft(res, res_offset, res_col, a, a_col, b, b_col, tmp); } fn cnv_pairwise_apply_dft_tmp_bytes( _module: &Module, res_size: usize, _res_offset: usize, a_size: usize, b_size: usize, ) -> usize { convolution_pairwise_apply_dft_tmp_bytes(res_size, a_size, b_size) } fn cnv_pairwise_apply_dft_impl( module: &Module, res: &mut R, res_offset: usize, res_col: usize, a: &A, b: &B, col_0: usize, col_1: usize, scratch: &mut Scratch, ) where R: VecZnxDftToMut, A: CnvPVecLToRef, B: CnvPVecRToRef, { let res: &mut VecZnxDft<&mut [u8], FFT64Ref> = &mut res.to_mut(); let a: &CnvPVecL<&[u8], FFT64Ref> = &a.to_ref(); let b: &CnvPVecR<&[u8], FFT64Ref> = &b.to_ref(); let (tmp, _) = scratch .take_slice(module.cnv_pairwise_apply_dft_tmp_bytes(res.size(), res_offset, a.size(), b.size()) / size_of::()); convolution_pairwise_apply_dft(res, res_offset, res_col, a, b, col_0, col_1, tmp); } }