arnaucube
arnaucube/poulpyPublic Self-hosted repository
wip
Pro7ech jeanphilippe.bossuat@gmail.com
Sun, 12 Oct 2025 21:34:10 +0200
commit

2b2b994f7d110efd0ce5923fb154fc0290e00063

parent

f72363cc4b44927ff61b211783462a6f00859462

169 files changed, 8319 insertions(+), 7291 deletions(-)

jump to
M poulpy-backend/src/cpu_fft64_avx/scratch.rs → poulpy-backend/src/cpu_fft64_avx/scratch.rs

@@ -3,13 +3,8 @@

use poulpy_hal::{ DEFAULTALIGN, alloc_aligned, api::ScratchFromBytes, - layouts::{Backend, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, - oep::{ - ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, SvpPPolAllocBytesImpl, - TakeMatZnxImpl, TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, - TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl, VecZnxBigAllocBytesImpl, - VecZnxDftAllocBytesImpl, VmpPMatAllocBytesImpl, - }, + layouts::{Backend, Scratch, ScratchOwned}, + oep::{ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeSliceImpl}, }; use crate::cpu_fft64_avx::FFT64Avx;

@@ -61,178 +56,6 @@ &mut *(std::ptr::slice_from_raw_parts_mut(take_slice.as_mut_ptr() as *mut T, len)),

Scratch::from_bytes(rem_slice), ) } - } -} - -unsafe impl<B: Backend> TakeScalarZnxImpl<B> for FFT64Avx -where - B: ScratchFromBytesImpl<B>, -{ - fn take_scalar_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, ScalarZnx::alloc_bytes(n, cols)); - ( - ScalarZnx::from_data(take_slice, n, cols), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeSvpPPolImpl<B> for FFT64Avx -where - B: SvpPPolAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_svp_ppol_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, B::svp_ppol_alloc_bytes_impl(n, cols)); - ( - SvpPPol::from_data(take_slice, n, cols), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxImpl<B> for FFT64Avx -where - B: ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, VecZnx::alloc_bytes(n, cols, size)); - ( - VecZnx::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxBigImpl<B> for FFT64Avx -where - B: VecZnxBigAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_big_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxBig<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vec_znx_big_alloc_bytes_impl(n, cols, size), - ); - ( - VecZnxBig::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxDftImpl<B> for FFT64Avx -where - B: VecZnxDftAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_dft_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxDft<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vec_znx_dft_alloc_bytes_impl(n, cols, size), - ); - - ( - VecZnxDft::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxDftSliceImpl<B> for FFT64Avx -where - B: VecZnxDftAllocBytesImpl<B> + ScratchFromBytesImpl<B> + TakeVecZnxDftImpl<B>, -{ - fn take_vec_znx_dft_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Scratch<B>) { - let mut scratch: &mut Scratch<B> = scratch; - let mut slice: Vec<VecZnxDft<&mut [u8], B>> = Vec::with_capacity(len); - for _ in 0..len { - let (znx, new_scratch) = B::take_vec_znx_dft_impl(scratch, n, cols, size); - scratch = new_scratch; - slice.push(znx); - } - (slice, scratch) - } -} - -unsafe impl<B: Backend> TakeVecZnxSliceImpl<B> for FFT64Avx -where - B: ScratchFromBytesImpl<B> + TakeVecZnxImpl<B>, -{ - fn take_vec_znx_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnx<&mut [u8]>>, &mut Scratch<B>) { - let mut scratch: &mut Scratch<B> = scratch; - let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len); - for _ in 0..len { - let (znx, new_scratch) = B::take_vec_znx_impl(scratch, n, cols, size); - scratch = new_scratch; - slice.push(znx); - } - (slice, scratch) - } -} - -unsafe impl<B: Backend> TakeVmpPMatImpl<B> for FFT64Avx -where - B: VmpPMatAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vmp_pmat_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (VmpPMat<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size), - ); - ( - VmpPMat::from_data(take_slice, n, rows, cols_in, cols_out, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeMatZnxImpl<B> for FFT64Avx -where - B: ScratchFromBytesImpl<B>, -{ - fn take_mat_znx_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (MatZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - MatZnx::alloc_bytes(n, rows, cols_in, cols_out, size), - ); - ( - MatZnx::from_data(take_slice, n, rows, cols_in, cols_out, size), - Scratch::from_bytes(rem_slice), - ) } }
M poulpy-backend/src/cpu_fft64_avx/svp.rs → poulpy-backend/src/cpu_fft64_avx/svp.rs

@@ -22,7 +22,7 @@ }

} unsafe impl SvpPPolAllocBytesImpl<Self> for FFT64Avx { - fn svp_ppol_alloc_bytes_impl(n: usize, cols: usize) -> usize { + fn svp_ppol_bytes_of_impl(n: usize, cols: usize) -> usize { Self::layout_prep_word_count() * n * cols * size_of::<f64>() } }
M poulpy-backend/src/cpu_fft64_avx/vec_znx_big.rs → poulpy-backend/src/cpu_fft64_avx/vec_znx_big.rs

@@ -27,7 +27,7 @@ source::Source,

}; unsafe impl VecZnxBigAllocBytesImpl<Self> for FFT64Avx { - fn vec_znx_big_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_big_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_big_word_count() * n * cols * size * size_of::<f64>() } }
M poulpy-backend/src/cpu_fft64_avx/vec_znx_dft.rs → poulpy-backend/src/cpu_fft64_avx/vec_znx_dft.rs

@@ -24,7 +24,7 @@ }

} unsafe impl VecZnxDftAllocBytesImpl<Self> for FFT64Avx { - fn vec_znx_dft_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_dft_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * cols * size * size_of::<<FFT64Avx as Backend>::ScalarPrep>() } }
M poulpy-backend/src/cpu_fft64_avx/vmp.rs → poulpy-backend/src/cpu_fft64_avx/vmp.rs

@@ -16,7 +16,7 @@

use crate::cpu_fft64_avx::{FFT64Avx, module::FFT64ModuleHandle}; unsafe impl VmpPMatAllocBytesImpl<Self> for FFT64Avx { - fn vmp_pmat_alloc_bytes_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { + fn vmp_pmat_bytes_of_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * rows * cols_in * cols_out * size * size_of::<f64>() } }
M poulpy-backend/src/cpu_fft64_ref/scratch.rs → poulpy-backend/src/cpu_fft64_ref/scratch.rs

@@ -3,13 +3,8 @@

use poulpy_hal::{ DEFAULTALIGN, alloc_aligned, api::ScratchFromBytes, - layouts::{Backend, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, - oep::{ - ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, SvpPPolAllocBytesImpl, - TakeMatZnxImpl, TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, - TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl, VecZnxBigAllocBytesImpl, - VecZnxDftAllocBytesImpl, VmpPMatAllocBytesImpl, - }, + layouts::{Backend, Scratch, ScratchOwned}, + oep::{ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeSliceImpl}, }; use crate::cpu_fft64_ref::FFT64Ref;

@@ -61,178 +56,6 @@ &mut *(std::ptr::slice_from_raw_parts_mut(take_slice.as_mut_ptr() as *mut T, len)),

Scratch::from_bytes(rem_slice), ) } - } -} - -unsafe impl<B: Backend> TakeScalarZnxImpl<B> for FFT64Ref -where - B: ScratchFromBytesImpl<B>, -{ - fn take_scalar_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, ScalarZnx::alloc_bytes(n, cols)); - ( - ScalarZnx::from_data(take_slice, n, cols), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeSvpPPolImpl<B> for FFT64Ref -where - B: SvpPPolAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_svp_ppol_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, B::svp_ppol_alloc_bytes_impl(n, cols)); - ( - SvpPPol::from_data(take_slice, n, cols), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxImpl<B> for FFT64Ref -where - B: ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, VecZnx::alloc_bytes(n, cols, size)); - ( - VecZnx::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxBigImpl<B> for FFT64Ref -where - B: VecZnxBigAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_big_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxBig<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vec_znx_big_alloc_bytes_impl(n, cols, size), - ); - ( - VecZnxBig::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxDftImpl<B> for FFT64Ref -where - B: VecZnxDftAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_dft_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxDft<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vec_znx_dft_alloc_bytes_impl(n, cols, size), - ); - - ( - VecZnxDft::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxDftSliceImpl<B> for FFT64Ref -where - B: VecZnxDftAllocBytesImpl<B> + ScratchFromBytesImpl<B> + TakeVecZnxDftImpl<B>, -{ - fn take_vec_znx_dft_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Scratch<B>) { - let mut scratch: &mut Scratch<B> = scratch; - let mut slice: Vec<VecZnxDft<&mut [u8], B>> = Vec::with_capacity(len); - for _ in 0..len { - let (znx, new_scratch) = B::take_vec_znx_dft_impl(scratch, n, cols, size); - scratch = new_scratch; - slice.push(znx); - } - (slice, scratch) - } -} - -unsafe impl<B: Backend> TakeVecZnxSliceImpl<B> for FFT64Ref -where - B: ScratchFromBytesImpl<B> + TakeVecZnxImpl<B>, -{ - fn take_vec_znx_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnx<&mut [u8]>>, &mut Scratch<B>) { - let mut scratch: &mut Scratch<B> = scratch; - let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len); - for _ in 0..len { - let (znx, new_scratch) = B::take_vec_znx_impl(scratch, n, cols, size); - scratch = new_scratch; - slice.push(znx); - } - (slice, scratch) - } -} - -unsafe impl<B: Backend> TakeVmpPMatImpl<B> for FFT64Ref -where - B: VmpPMatAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vmp_pmat_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (VmpPMat<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size), - ); - ( - VmpPMat::from_data(take_slice, n, rows, cols_in, cols_out, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeMatZnxImpl<B> for FFT64Ref -where - B: ScratchFromBytesImpl<B>, -{ - fn take_mat_znx_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (MatZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - MatZnx::alloc_bytes(n, rows, cols_in, cols_out, size), - ); - ( - MatZnx::from_data(take_slice, n, rows, cols_in, cols_out, size), - Scratch::from_bytes(rem_slice), - ) } }
M poulpy-backend/src/cpu_fft64_ref/svp.rs → poulpy-backend/src/cpu_fft64_ref/svp.rs

@@ -22,7 +22,7 @@ }

} unsafe impl SvpPPolAllocBytesImpl<Self> for FFT64Ref { - fn svp_ppol_alloc_bytes_impl(n: usize, cols: usize) -> usize { + fn svp_ppol_bytes_of_impl(n: usize, cols: usize) -> usize { Self::layout_prep_word_count() * n * cols * size_of::<f64>() } }
M poulpy-backend/src/cpu_fft64_ref/vec_znx_big.rs → poulpy-backend/src/cpu_fft64_ref/vec_znx_big.rs

@@ -27,7 +27,7 @@ source::Source,

}; unsafe impl VecZnxBigAllocBytesImpl<Self> for FFT64Ref { - fn vec_znx_big_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_big_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_big_word_count() * n * cols * size * size_of::<f64>() } }
M poulpy-backend/src/cpu_fft64_ref/vec_znx_dft.rs → poulpy-backend/src/cpu_fft64_ref/vec_znx_dft.rs

@@ -24,7 +24,7 @@ }

} unsafe impl VecZnxDftAllocBytesImpl<Self> for FFT64Ref { - fn vec_znx_dft_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_dft_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * cols * size * size_of::<<FFT64Ref as Backend>::ScalarPrep>() } }
M poulpy-backend/src/cpu_fft64_ref/vmp.rs → poulpy-backend/src/cpu_fft64_ref/vmp.rs

@@ -16,7 +16,7 @@

use crate::cpu_fft64_ref::{FFT64Ref, module::FFT64ModuleHandle}; unsafe impl VmpPMatAllocBytesImpl<Self> for FFT64Ref { - fn vmp_pmat_alloc_bytes_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { + fn vmp_pmat_bytes_of_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * rows * cols_in * cols_out * size * size_of::<f64>() } }
M poulpy-backend/src/cpu_spqlios/fft64/scratch.rs → poulpy-backend/src/cpu_spqlios/fft64/scratch.rs

@@ -3,13 +3,8 @@

use poulpy_hal::{ DEFAULTALIGN, alloc_aligned, api::ScratchFromBytes, - layouts::{Backend, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, - oep::{ - ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, SvpPPolAllocBytesImpl, - TakeMatZnxImpl, TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, - TakeVecZnxDftSliceImpl, TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl, VecZnxBigAllocBytesImpl, - VecZnxDftAllocBytesImpl, VmpPMatAllocBytesImpl, - }, + layouts::{Backend, Scratch, ScratchOwned}, + oep::{ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeSliceImpl}, }; use crate::cpu_spqlios::FFT64Spqlios;

@@ -61,178 +56,6 @@ &mut *(std::ptr::slice_from_raw_parts_mut(take_slice.as_mut_ptr() as *mut T, len)),

Scratch::from_bytes(rem_slice), ) } - } -} - -unsafe impl<B: Backend> TakeScalarZnxImpl<B> for FFT64Spqlios -where - B: ScratchFromBytesImpl<B>, -{ - fn take_scalar_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, ScalarZnx::alloc_bytes(n, cols)); - ( - ScalarZnx::from_data(take_slice, n, cols), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeSvpPPolImpl<B> for FFT64Spqlios -where - B: SvpPPolAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_svp_ppol_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, B::svp_ppol_alloc_bytes_impl(n, cols)); - ( - SvpPPol::from_data(take_slice, n, cols), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxImpl<B> for FFT64Spqlios -where - B: ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned(&mut scratch.data, VecZnx::alloc_bytes(n, cols, size)); - ( - VecZnx::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxBigImpl<B> for FFT64Spqlios -where - B: VecZnxBigAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_big_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxBig<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vec_znx_big_alloc_bytes_impl(n, cols, size), - ); - ( - VecZnxBig::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxDftImpl<B> for FFT64Spqlios -where - B: VecZnxDftAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vec_znx_dft_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxDft<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vec_znx_dft_alloc_bytes_impl(n, cols, size), - ); - - ( - VecZnxDft::from_data(take_slice, n, cols, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeVecZnxDftSliceImpl<B> for FFT64Spqlios -where - B: VecZnxDftAllocBytesImpl<B> + ScratchFromBytesImpl<B> + TakeVecZnxDftImpl<B>, -{ - fn take_vec_znx_dft_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Scratch<B>) { - let mut scratch: &mut Scratch<B> = scratch; - let mut slice: Vec<VecZnxDft<&mut [u8], B>> = Vec::with_capacity(len); - for _ in 0..len { - let (znx, new_scratch) = B::take_vec_znx_dft_impl(scratch, n, cols, size); - scratch = new_scratch; - slice.push(znx); - } - (slice, scratch) - } -} - -unsafe impl<B: Backend> TakeVecZnxSliceImpl<B> for FFT64Spqlios -where - B: ScratchFromBytesImpl<B> + TakeVecZnxImpl<B>, -{ - fn take_vec_znx_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnx<&mut [u8]>>, &mut Scratch<B>) { - let mut scratch: &mut Scratch<B> = scratch; - let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len); - for _ in 0..len { - let (znx, new_scratch) = B::take_vec_znx_impl(scratch, n, cols, size); - scratch = new_scratch; - slice.push(znx); - } - (slice, scratch) - } -} - -unsafe impl<B: Backend> TakeVmpPMatImpl<B> for FFT64Spqlios -where - B: VmpPMatAllocBytesImpl<B> + ScratchFromBytesImpl<B>, -{ - fn take_vmp_pmat_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (VmpPMat<&mut [u8], B>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size), - ); - ( - VmpPMat::from_data(take_slice, n, rows, cols_in, cols_out, size), - Scratch::from_bytes(rem_slice), - ) - } -} - -unsafe impl<B: Backend> TakeMatZnxImpl<B> for FFT64Spqlios -where - B: ScratchFromBytesImpl<B>, -{ - fn take_mat_znx_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (MatZnx<&mut [u8]>, &mut Scratch<B>) { - let (take_slice, rem_slice) = take_slice_aligned( - &mut scratch.data, - MatZnx::alloc_bytes(n, rows, cols_in, cols_out, size), - ); - ( - MatZnx::from_data(take_slice, n, rows, cols_in, cols_out, size), - Scratch::from_bytes(rem_slice), - ) } }
M poulpy-backend/src/cpu_spqlios/fft64/svp_ppol.rs → poulpy-backend/src/cpu_spqlios/fft64/svp_ppol.rs

@@ -27,7 +27,7 @@ }

} unsafe impl SvpPPolAllocBytesImpl<Self> for FFT64Spqlios { - fn svp_ppol_alloc_bytes_impl(n: usize, cols: usize) -> usize { + fn svp_ppol_bytes_of_impl(n: usize, cols: usize) -> usize { FFT64Spqlios::layout_prep_word_count() * n * cols * size_of::<f64>() } }
M poulpy-backend/src/cpu_spqlios/fft64/vec_znx_big.rs → poulpy-backend/src/cpu_spqlios/fft64/vec_znx_big.rs

@@ -22,7 +22,7 @@ source::Source,

}; unsafe impl VecZnxBigAllocBytesImpl<Self> for FFT64Spqlios { - fn vec_znx_big_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_big_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_big_word_count() * n * cols * size * size_of::<f64>() } }
M poulpy-backend/src/cpu_spqlios/fft64/vec_znx_dft.rs → poulpy-backend/src/cpu_spqlios/fft64/vec_znx_dft.rs

@@ -30,7 +30,7 @@ }

} unsafe impl VecZnxDftAllocBytesImpl<Self> for FFT64Spqlios { - fn vec_znx_dft_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_dft_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * cols * size * size_of::<<FFT64Spqlios as Backend>::ScalarPrep>() } }
M poulpy-backend/src/cpu_spqlios/fft64/vmp_pmat.rs → poulpy-backend/src/cpu_spqlios/fft64/vmp_pmat.rs

@@ -16,7 +16,7 @@ ffi::{vec_znx_dft::vec_znx_dft_t, vmp},

}; unsafe impl VmpPMatAllocBytesImpl<Self> for FFT64Spqlios { - fn vmp_pmat_alloc_bytes_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { + fn vmp_pmat_bytes_of_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { Self::layout_prep_word_count() * n * rows * cols_in * cols_out * size * size_of::<f64>() } }
M poulpy-backend/src/cpu_spqlios/ntt120/svp_ppol.rs → poulpy-backend/src/cpu_spqlios/ntt120/svp_ppol.rs

@@ -18,7 +18,7 @@ }

} unsafe impl SvpPPolAllocBytesImpl<Self> for NTT120 { - fn svp_ppol_alloc_bytes_impl(n: usize, cols: usize) -> usize { + fn svp_ppol_bytes_of_impl(n: usize, cols: usize) -> usize { NTT120::layout_prep_word_count() * n * cols * size_of::<i64>() } }
M poulpy-backend/src/cpu_spqlios/ntt120/vec_znx_big.rs → poulpy-backend/src/cpu_spqlios/ntt120/vec_znx_big.rs

@@ -3,7 +3,7 @@

use crate::cpu_spqlios::NTT120; unsafe impl VecZnxBigAllocBytesImpl<NTT120> for NTT120 { - fn vec_znx_big_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_big_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { NTT120::layout_big_word_count() * n * cols * size * size_of::<i128>() } }
M poulpy-backend/src/cpu_spqlios/ntt120/vec_znx_dft.rs → poulpy-backend/src/cpu_spqlios/ntt120/vec_znx_dft.rs

@@ -6,7 +6,7 @@

use crate::cpu_spqlios::NTT120; unsafe impl VecZnxDftAllocBytesImpl<NTT120> for NTT120 { - fn vec_znx_dft_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize { + fn vec_znx_dft_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize { NTT120::layout_prep_word_count() * n * cols * size * size_of::<i64>() } }
M poulpy-core/README.md → poulpy-core/README.md

@@ -52,8 +52,8 @@ let mut source_xa: Source = Source::new([2u8; 32]);

// Scratch space let mut scratch: ScratchOwned<FFT64> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(&module, n, base2k, ct.k()) - | GLWECiphertext::decrypt_scratch_space(&module, n, base2k, ct.k()), + GLWECiphertext::encrypt_sk_tmp_bytes(&module, n, base2k, ct.k()) + | GLWECiphertext::decrypt_tmp_bytes(&module, n, base2k, ct.k()), ); // Generate secret-key
M poulpy-core/benches/external_product_glwe_fft64.rs → poulpy-core/benches/external_product_glwe_fft64.rs

@@ -1,7 +1,6 @@

use poulpy_core::layouts::{ - Base2K, Degree, Dnum, Dsize, GGSWCiphertext, GGSWCiphertextLayout, GLWECiphertext, GLWECiphertextLayout, GLWESecret, Rank, - TorusPrecision, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, + Base2K, Dnum, Dsize, GGSW, GGSWLayout, GLWE, GLWELayout, GLWESecret, Rank, RingDegree, TorusPrecision, + prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, }; use std::hint::black_box;

@@ -29,7 +28,7 @@

fn runner(p: Params) -> impl FnMut() { let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(1 << p.log_n); - let n: Degree = Degree(module.n() as u32); + let n: RingDegree = RingDegree(module.n() as u32); let base2k: Base2K = p.base2k; let k_ct_in: TorusPrecision = p.k_ct_in; let k_ct_out: TorusPrecision = p.k_ct_out;

@@ -39,7 +38,7 @@ let dsize: Dsize = Dsize(1);

let dnum: Dnum = Dnum(1); //(p.k_ct_in.div_ceil(p.base2k); - let ggsw_layout: GGSWCiphertextLayout = GGSWCiphertextLayout { + let ggsw_layout: GGSWLayout = GGSWLayout { n, base2k, k: k_ggsw,

@@ -48,36 +47,36 @@ dsize: dsize,

rank, }; - let glwe_out_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_layout: GLWELayout = GLWELayout { n, base2k, k: k_ct_out, rank, }; - let glwe_in_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_in_layout: GLWELayout = GLWELayout { n, base2k, k: k_ct_in, rank, }; - let mut ct_ggsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_layout); - let mut ct_glwe_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_in_layout); - let mut ct_glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_layout); + let mut ct_ggsw: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_layout); + let mut ct_glwe_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_in_layout); + let mut ct_glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_layout); let pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n.into(), 1); let mut scratch: ScratchOwned<FFT64Spqlios> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(&module, &ggsw_layout) - | GLWECiphertext::encrypt_sk_scratch_space(&module, &glwe_in_layout) - | GLWECiphertext::external_product_scratch_space(&module, &glwe_out_layout, &glwe_in_layout, &ggsw_layout), + GGSW::encrypt_sk_tmp_bytes(&module, &ggsw_layout) + | GLWE::encrypt_sk_tmp_bytes(&module, &glwe_in_layout) + | GLWE::external_product_tmp_bytes(&module, &glwe_out_layout, &glwe_in_layout, &ggsw_layout), ); let mut source_xs = Source::new([0u8; 32]); let mut source_xe = Source::new([0u8; 32]); let mut source_xa = Source::new([0u8; 32]); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_in_layout); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_in_layout); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_dft: GLWESecretPrepared<Vec<u8>, FFT64Spqlios> = sk.prepare_alloc(&module, scratch.borrow());

@@ -98,7 +97,7 @@ &mut source_xe,

scratch.borrow(), ); - let ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, FFT64Spqlios> = ct_ggsw.prepare_alloc(&module, scratch.borrow()); + let ggsw_prepared: GGSWPrepared<Vec<u8>, FFT64Spqlios> = ct_ggsw.prepare_alloc(&module, scratch.borrow()); move || { ct_glwe_out.external_product(&module, &ct_glwe_in, &ggsw_prepared, scratch.borrow());

@@ -138,7 +137,7 @@

fn runner(p: Params) -> impl FnMut() { let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(1 << p.log_n); - let n: Degree = Degree(module.n() as u32); + let n: RingDegree = RingDegree(module.n() as u32); let base2k: Base2K = p.base2k; let k_glwe: TorusPrecision = p.k_ct; let k_ggsw: TorusPrecision = p.k_ggsw;

@@ -147,7 +146,7 @@ let dsize: Dsize = Dsize(1);

let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into(); - let ggsw_layout: GGSWCiphertextLayout = GGSWCiphertextLayout { + let ggsw_layout: GGSWLayout = GGSWLayout { n, base2k, k: k_ggsw,

@@ -156,28 +155,28 @@ dsize: dsize,

rank, }; - let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_layout: GLWELayout = GLWELayout { n, base2k, k: k_glwe, rank, }; - let mut ct_ggsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_layout); - let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_layout); + let mut ct_ggsw: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_layout); + let mut ct_glwe: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_layout); let pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n.into(), 1); let mut scratch: ScratchOwned<FFT64Spqlios> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(&module, &ggsw_layout) - | GLWECiphertext::encrypt_sk_scratch_space(&module, &glwe_layout) - | GLWECiphertext::external_product_inplace_scratch_space(&module, &glwe_layout, &ggsw_layout), + GGSW::encrypt_sk_tmp_bytes(&module, &ggsw_layout) + | GLWE::encrypt_sk_tmp_bytes(&module, &glwe_layout) + | GLWE::external_product_inplace_tmp_bytes(&module, &glwe_layout, &ggsw_layout), ); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_layout); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_layout); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_dft: GLWESecretPrepared<Vec<u8>, FFT64Spqlios> = sk.prepare_alloc(&module, scratch.borrow());

@@ -198,7 +197,7 @@ &mut source_xe,

scratch.borrow(), ); - let ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, FFT64Spqlios> = ct_ggsw.prepare_alloc(&module, scratch.borrow()); + let ggsw_prepared: GGSWPrepared<Vec<u8>, FFT64Spqlios> = ct_ggsw.prepare_alloc(&module, scratch.borrow()); move || { let scratch_borrow = scratch.borrow();
M poulpy-core/benches/keyswitch_glwe_fft64.rs → poulpy-core/benches/keyswitch_glwe_fft64.rs

@@ -1,7 +1,7 @@

use poulpy_core::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWESwitchingKey, GGLWESwitchingKeyLayout, - GLWECiphertext, GLWECiphertextLayout, GLWESecret, Rank, TorusPrecision, - prepared::{GGLWEAutomorphismKeyPrepared, GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + AutomorphismKey, AutomorphismKeyLayout, Base2K, Dnum, Dsize, GLWE, GLWELayout, GLWESecret, GLWESwitchingKey, + GLWESwitchingKeyLayout, Rank, RingDegree, TorusPrecision, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, GLWESwitchingKeyPrepared, PrepareAlloc}, }; use std::{hint::black_box, time::Duration};

@@ -29,7 +29,7 @@

fn runner(p: Params) -> impl FnMut() { let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(1 << p.log_n); - let n: Degree = Degree(module.n() as u32); + let n: RingDegree = RingDegree(module.n() as u32); let base2k: Base2K = p.base2k; let k_glwe_in: TorusPrecision = p.k_ct_in; let k_glwe_out: TorusPrecision = p.k_ct_out;

@@ -39,7 +39,7 @@ let dsize: Dsize = p.dsize;

let dnum: Dnum = p.k_ct_in.div_ceil(p.base2k.0 * dsize.0).into(); - let gglwe_atk_layout: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let gglwe_atk_layout: AutomorphismKeyLayout = AutomorphismKeyLayout { n, base2k, k: k_gglwe,

@@ -48,28 +48,28 @@ rank,

dsize, }; - let glwe_in_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_in_layout: GLWELayout = GLWELayout { n, base2k, k: k_glwe_in, rank, }; - let glwe_out_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_layout: GLWELayout = GLWELayout { n, base2k, k: k_glwe_out, rank, }; - let mut ksk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&gglwe_atk_layout); - let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_in_layout); - let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_layout); + let mut ksk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&gglwe_atk_layout); + let mut ct_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_in_layout); + let mut ct_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_layout); let mut scratch: ScratchOwned<FFT64Spqlios> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(&module, &gglwe_atk_layout) - | GLWECiphertext::encrypt_sk_scratch_space(&module, &glwe_in_layout) - | GLWECiphertext::keyswitch_scratch_space( + GLWESwitchingKey::encrypt_sk_tmp_bytes(&module, &gglwe_atk_layout) + | GLWE::encrypt_sk_tmp_bytes(&module, &glwe_in_layout) + | GLWE::keyswitch_tmp_bytes( &module, &glwe_out_layout, &glwe_in_layout,

@@ -81,7 +81,7 @@ let mut source_xs: Source = Source::new([0u8; 32]);

let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_in_layout); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_in_layout); sk_in.fill_ternary_prob(0.5, &mut source_xs); let sk_in_dft: GLWESecretPrepared<Vec<u8>, FFT64Spqlios> = sk_in.prepare_alloc(&module, scratch.borrow());

@@ -102,7 +102,7 @@ &mut source_xe,

scratch.borrow(), ); - let ksk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, _> = ksk.prepare_alloc(&module, scratch.borrow()); + let ksk_prepared: AutomorphismKeyPrepared<Vec<u8>, _> = ksk.prepare_alloc(&module, scratch.borrow()); move || { ct_out.automorphism(&module, &ct_in, &ksk_prepared, scratch.borrow());

@@ -148,7 +148,7 @@

fn runner(p: Params) -> impl FnMut() { let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(1 << p.log_n); - let n: Degree = Degree(module.n() as u32); + let n: RingDegree = RingDegree(module.n() as u32); let base2k: Base2K = p.base2k; let k_ct: TorusPrecision = p.k_ct; let k_ksk: TorusPrecision = p.k_ksk;

@@ -157,7 +157,7 @@ let dsize: Dsize = Dsize(1);

let dnum: Dnum = p.k_ct.div_ceil(p.base2k).into(); - let gglwe_layout: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_layout: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n, base2k, k: k_ksk,

@@ -167,31 +167,31 @@ rank_in: rank,

rank_out: rank, }; - let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_layout: GLWELayout = GLWELayout { n, base2k, k: k_ct, rank, }; - let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_layout); - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_layout); + let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_layout); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_layout); let mut scratch: ScratchOwned<FFT64Spqlios> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(&module, &gglwe_layout) - | GLWECiphertext::encrypt_sk_scratch_space(&module, &glwe_layout) - | GLWECiphertext::keyswitch_inplace_scratch_space(&module, &glwe_layout, &gglwe_layout), + GLWESwitchingKey::encrypt_sk_tmp_bytes(&module, &gglwe_layout) + | GLWE::encrypt_sk_tmp_bytes(&module, &glwe_layout) + | GLWE::keyswitch_inplace_tmp_bytes(&module, &glwe_layout, &gglwe_layout), ); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_layout); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_layout); sk_in.fill_ternary_prob(0.5, &mut source_xs); let sk_in_dft: GLWESecretPrepared<Vec<u8>, FFT64Spqlios> = sk_in.prepare_alloc(&module, scratch.borrow()); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_layout); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_layout); sk_out.fill_ternary_prob(0.5, &mut source_xs); ksk.encrypt_sk(

@@ -211,7 +211,7 @@ &mut source_xe,

scratch.borrow(), ); - let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, FFT64Spqlios> = ksk.prepare_alloc(&module, scratch.borrow()); + let ksk_prepared: GLWESwitchingKeyPrepared<Vec<u8>, FFT64Spqlios> = ksk.prepare_alloc(&module, scratch.borrow()); move || { ct.keyswitch_inplace(&module, &ksk_prepared, scratch.borrow());
M poulpy-core/examples/encryption.rs → poulpy-core/examples/encryption.rs

@@ -2,8 +2,7 @@ use poulpy_backend::cpu_spqlios::FFT64Spqlios;

use poulpy_core::{ GLWEOperations, SIGMA, layouts::{ - Base2K, Degree, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWEPlaintextLayout, GLWESecret, LWEInfos, Rank, - TorusPrecision, + Base2K, GLWE, GLWELayout, GLWEPlaintext, GLWEPlaintextLayout, GLWESecret, LWEInfos, Rank, RingDegree, TorusPrecision, prepared::{GLWESecretPrepared, PrepareAlloc}, }, };

@@ -17,7 +16,7 @@ fn main() {

// Ring degree let log_n: usize = 10; - let n: Degree = Degree(1 << log_n); + let n: RingDegree = RingDegree(1 << log_n); // Base-2-k (implicit digit decomposition) let base2k: Base2K = Base2K(14);

@@ -34,7 +33,7 @@

// Instantiate Module (DFT Tables) let module: Module<FFT64Spqlios> = Module::<FFT64Spqlios>::new(n.0 as u64); - let glwe_ct_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_ct_infos: GLWELayout = GLWELayout { n, base2k, k: k_ct,

@@ -44,9 +43,9 @@

let glwe_pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout { n, base2k, k: k_pt }; // Allocates ciphertext & plaintexts - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_ct_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_pt_infos); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_pt_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_ct_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_pt_infos); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_pt_infos); // CPRNG let mut source_xs: Source = Source::new([0u8; 32]);

@@ -55,12 +54,11 @@ let mut source_xa: Source = Source::new([2u8; 32]);

// Scratch space let mut scratch: ScratchOwned<FFT64Spqlios> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(&module, &glwe_ct_infos) - | GLWECiphertext::decrypt_scratch_space(&module, &glwe_ct_infos), + GLWE::encrypt_sk_tmp_bytes(&module, &glwe_ct_infos) | GLWE::decrypt_tmp_bytes(&module, &glwe_ct_infos), ); // Generate secret-key - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_ct_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_ct_infos); sk.fill_ternary_prob(0.5, &mut source_xs); // Backend-prepared secret
M poulpy-core/src/automorphism/gglwe_atk.rs → poulpy-core/src/automorphism/gglwe_atk.rs

@@ -1,16 +1,16 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, - VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, - VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + ScratchAvailable, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, + VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero}, }; -use crate::layouts::{GGLWEAutomorphismKey, GGLWEInfos, GLWECiphertext, prepared::GGLWEAutomorphismKeyPrepared}; +use crate::layouts::{AutomorphismKey, GGLWEInfos, GLWE, prepared::AutomorphismKeyPrepared}; -impl GGLWEAutomorphismKey<Vec<u8>> { - pub fn automorphism_scratch_space<B: Backend, OUT, IN, KEY>( +impl AutomorphismKey<Vec<u8>> { + pub fn automorphism_tmp_bytes<B: Backend, OUT, IN, KEY>( module: &Module<B>, out_infos: &OUT, in_infos: &IN,

@@ -20,9 +20,9 @@ where

OUT: GGLWEInfos, IN: GGLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - GLWECiphertext::keyswitch_scratch_space( + GLWE::keyswitch_tmp_bytes( module, &out_infos.glwe_layout(), &in_infos.glwe_layout(),

@@ -30,25 +30,25 @@ key_infos,

) } - pub fn automorphism_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize + pub fn automorphism_inplace_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize where OUT: GGLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - GGLWEAutomorphismKey::automorphism_scratch_space(module, out_infos, out_infos, key_infos) + AutomorphismKey::automorphism_tmp_bytes(module, out_infos, out_infos, key_infos) } } -impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { +impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { pub fn automorphism<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GGLWEAutomorphismKey<DataLhs>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + lhs: &AutomorphismKey<DataLhs>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -61,7 +61,7 @@ + VecZnxAutomorphism

+ VecZnxAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -103,8 +103,8 @@ let p_inv: i64 = module.galois_element_inv(p);

(0..self.rank_in().into()).for_each(|col_i| { (0..self.dnum().into()).for_each(|row_j| { - let mut res_ct: GLWECiphertext<&mut [u8]> = self.at_mut(row_j, col_i); - let lhs_ct: GLWECiphertext<&[u8]> = lhs.at(row_j, col_i); + let mut res_ct: GLWE<&mut [u8]> = self.at_mut(row_j, col_i); + let lhs_ct: GLWE<&[u8]> = lhs.at(row_j, col_i); // Reverts the automorphism X^{-k}: (-pi^{-1}_{k}(s)a + s, a) to (-sa + pi_{k}(s), a) (0..cols_out).for_each(|i| {

@@ -133,10 +133,10 @@

pub fn automorphism_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -149,7 +149,7 @@ + VecZnxAutomorphism

+ VecZnxAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -176,7 +176,7 @@ let p_inv = module.galois_element_inv(p);

(0..self.rank_in().into()).for_each(|col_i| { (0..self.dnum().into()).for_each(|row_j| { - let mut res_ct: GLWECiphertext<&mut [u8]> = self.at_mut(row_j, col_i); + let mut res_ct: GLWE<&mut [u8]> = self.at_mut(row_j, col_i); // Reverts the automorphism X^{-k}: (-pi^{-1}_{k}(s)a + s, a) to (-sa + pi_{k}(s), a) (0..cols_out).for_each(|i| {
M poulpy-core/src/automorphism/ggsw_ct.rs → poulpy-core/src/automorphism/ggsw_ct.rs

@@ -1,20 +1,20 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAddInplace, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeTmpBytes, - VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + ScratchAvailable, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxDftAddInplace, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxIdftApplyConsume, + VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, + VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; use crate::layouts::{ - GGLWEInfos, GGSWCiphertext, GGSWInfos, GLWECiphertext, - prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared}, + GGLWEInfos, GGSW, GGSWInfos, GLWE, + prepared::{AutomorphismKeyPrepared, TensorKeyPrepared}, }; -impl GGSWCiphertext<Vec<u8>> { - pub fn automorphism_scratch_space<B: Backend, OUT, IN, KEY, TSK>( +impl GGSW<Vec<u8>> { + pub fn automorphism_tmp_bytes<B: Backend, OUT, IN, KEY, TSK>( module: &Module<B>, out_infos: &OUT, in_infos: &IN,

@@ -26,25 +26,22 @@ OUT: GGSWInfos,

IN: GGSWInfos, KEY: GGLWEInfos, TSK: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxBigNormalizeTmpBytes, + Module<B>: + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigBytesOf + VecZnxNormalizeTmpBytes + VecZnxBigNormalizeTmpBytes, { let out_size: usize = out_infos.size(); - let ci_dft: usize = module.vec_znx_dft_alloc_bytes((key_infos.rank_out() + 1).into(), out_size); - let ks_internal: usize = GLWECiphertext::keyswitch_scratch_space( + let ci_dft: usize = module.bytes_of_vec_znx_dft((key_infos.rank_out() + 1).into(), out_size); + let ks_internal: usize = GLWE::keyswitch_tmp_bytes( module, &out_infos.glwe_layout(), &in_infos.glwe_layout(), key_infos, ); - let expand: usize = GGSWCiphertext::expand_row_scratch_space(module, out_infos, tsk_infos); + let expand: usize = GGSW::expand_row_tmp_bytes(module, out_infos, tsk_infos); ci_dft + (ks_internal | expand) } - pub fn automorphism_inplace_scratch_space<B: Backend, OUT, KEY, TSK>( + pub fn automorphism_inplace_tmp_bytes<B: Backend, OUT, KEY, TSK>( module: &Module<B>, out_infos: &OUT, key_infos: &KEY,

@@ -54,26 +51,23 @@ where

OUT: GGSWInfos, KEY: GGLWEInfos, TSK: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxBigNormalizeTmpBytes, + Module<B>: + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigBytesOf + VecZnxNormalizeTmpBytes + VecZnxBigNormalizeTmpBytes, { - GGSWCiphertext::automorphism_scratch_space(module, out_infos, out_infos, key_infos, tsk_infos) + GGSW::automorphism_tmp_bytes(module, out_infos, out_infos, key_infos, tsk_infos) } } -impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> { +impl<DataSelf: DataMut> GGSW<DataSelf> { pub fn automorphism<DataLhs: DataRef, DataAk: DataRef, DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GGSWCiphertext<DataLhs>, - auto_key: &GGLWEAutomorphismKeyPrepared<DataAk, B>, - tensor_key: &GGLWETensorKeyPrepared<DataTsk, B>, + lhs: &GGSW<DataLhs>, + auto_key: &AutomorphismKeyPrepared<DataAk, B>, + tensor_key: &TensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -83,13 +77,13 @@ + VecZnxIdftApplyConsume<B>

+ VecZnxBigAddSmallInplace<B> + VecZnxBigNormalize<B> + VecZnxAutomorphismInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftCopy<B> + VecZnxDftAddInplace<B> + VecZnxIdftApplyTmpA<B> + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnxBig<B> + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -121,7 +115,7 @@ "ggsw_in rank: {} != tensor_key rank: {}",

self.rank(), tensor_key.rank_out() ); - assert!(scratch.available() >= GGSWCiphertext::automorphism_scratch_space(module, self, lhs, auto_key, tensor_key)) + assert!(scratch.available() >= GGSW::automorphism_tmp_bytes(module, self, lhs, auto_key, tensor_key)) }; // Keyswitch the j-th row of the col 0

@@ -137,11 +131,11 @@

pub fn automorphism_inplace<DataKsk: DataRef, DataTsk: DataRef, B: Backend>( &mut self, module: &Module<B>, - auto_key: &GGLWEAutomorphismKeyPrepared<DataKsk, B>, - tensor_key: &GGLWETensorKeyPrepared<DataTsk, B>, + auto_key: &AutomorphismKeyPrepared<DataKsk, B>, + tensor_key: &TensorKeyPrepared<DataTsk, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -151,13 +145,13 @@ + VecZnxIdftApplyConsume<B>

+ VecZnxBigAddSmallInplace<B> + VecZnxBigNormalize<B> + VecZnxAutomorphismInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftCopy<B> + VecZnxDftAddInplace<B> + VecZnxIdftApplyTmpA<B> + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnxBig<B> + TakeVecZnx, + Scratch<B>: ScratchAvailable, { // Keyswitch the j-th row of the col 0 (0..self.dnum().into()).for_each(|row_i| {
M poulpy-core/src/automorphism/glwe_ct.rs → poulpy-core/src/automorphism/glwe_ct.rs

@@ -1,17 +1,17 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, - VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallInplace, - VecZnxBigSubSmallNegateInplace, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, - VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + ScratchAvailable, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallInplace, VecZnxBigSubSmallNegateInplace, VecZnxDftApply, VecZnxDftBytesOf, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, + VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnxBig}, }; -use crate::layouts::{GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared}; +use crate::layouts::{GGLWEInfos, GLWE, GLWEInfos, LWEInfos, prepared::AutomorphismKeyPrepared}; -impl GLWECiphertext<Vec<u8>> { - pub fn automorphism_scratch_space<B: Backend, OUT, IN, KEY>( +impl GLWE<Vec<u8>> { + pub fn automorphism_tmp_bytes<B: Backend, OUT, IN, KEY>( module: &Module<B>, out_infos: &OUT, in_infos: &IN,

@@ -21,30 +21,30 @@ where

OUT: GLWEInfos, IN: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - Self::keyswitch_scratch_space(module, out_infos, in_infos, key_infos) + Self::keyswitch_tmp_bytes(module, out_infos, in_infos, key_infos) } - pub fn automorphism_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize + pub fn automorphism_inplace_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize where OUT: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - Self::keyswitch_inplace_scratch_space(module, out_infos, key_infos) + Self::keyswitch_inplace_tmp_bytes(module, out_infos, key_infos) } } -impl<DataSelf: DataMut> GLWECiphertext<DataSelf> { +impl<DataSelf: DataMut> GLWE<DataSelf> { pub fn automorphism<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + lhs: &GLWE<DataLhs>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -56,7 +56,7 @@ + VecZnxBigNormalize<B>

+ VecZnxAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { self.keyswitch(module, lhs, &rhs.key, scratch); (0..(self.rank() + 1).into()).for_each(|i| {

@@ -67,10 +67,10 @@

pub fn automorphism_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -82,7 +82,7 @@ + VecZnxBigNormalize<B>

+ VecZnxAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { self.keyswitch_inplace(module, &rhs.key, scratch); (0..(self.rank() + 1).into()).for_each(|i| {

@@ -93,11 +93,11 @@

pub fn automorphism_add<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + lhs: &GLWE<DataLhs>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -109,7 +109,7 @@ + VecZnxBigNormalize<B>

+ VecZnxBigAutomorphismInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -135,10 +135,10 @@

pub fn automorphism_add_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -150,7 +150,7 @@ + VecZnxBigNormalize<B>

+ VecZnxBigAutomorphismInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -176,11 +176,11 @@

pub fn automorphism_sub_ab<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + lhs: &GLWE<DataLhs>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -193,7 +193,7 @@ + VecZnxBigAutomorphismInplace<B>

+ VecZnxBigSubSmallInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -219,10 +219,10 @@

pub fn automorphism_sub_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -235,7 +235,7 @@ + VecZnxBigAutomorphismInplace<B>

+ VecZnxBigSubSmallInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -261,11 +261,11 @@

pub fn automorphism_sub_negate<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + lhs: &GLWE<DataLhs>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -278,7 +278,7 @@ + VecZnxBigAutomorphismInplace<B>

+ VecZnxBigSubSmallNegateInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -304,10 +304,10 @@

pub fn automorphism_sub_negate_inplace<DataRhs: DataRef, B: Backend>( &mut self, module: &Module<B>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, + rhs: &AutomorphismKeyPrepared<DataRhs, B>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -320,7 +320,7 @@ + VecZnxBigAutomorphismInplace<B>

+ VecZnxBigSubSmallNegateInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {
A poulpy-core/src/conversion/gglwe_to_ggsw.rs

@@ -0,0 +1,279 @@

+use poulpy_hal::{ + api::{ + ModuleN, ScratchAvailable, ScratchTakeBasic, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAddInplace, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeTmpBytes, + VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + }, + layouts::{Backend, DataMut, Module, Scratch, VmpPMat, ZnxInfos}, +}; + +use crate::{ + ScratchTakeCore, + layouts::{ + GGLWE, GGLWEInfos, GGLWEToRef, GGSW, GGSWInfos, GGSWToMut, GLWEInfos, LWEInfos, + prepared::{TensorKeyPrepared, TensorKeyPreparedToRef}, + }, + operations::GLWEOperations, +}; + +impl GGLWE<Vec<u8>> { + pub fn from_gglw_tmp_bytes<R, A, M, BE: Backend>(module: &M, res_infos: &R, tsk_infos: &A) -> usize + where + M: GGSWFromGGLWE<BE>, + R: GGSWInfos, + A: GGLWEInfos, + { + module.ggsw_from_gglwe_tmp_bytes(res_infos, tsk_infos) + } +} + +impl<D: DataMut> GGSW<D> { + pub fn from_gglwe<G, M, T, BE: Backend>(&mut self, module: &M, gglwe: &G, tsk: &T, scratch: &mut Scratch<BE>) + where + M: GGSWFromGGLWE<BE>, + G: GGLWEToRef, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.ggsw_from_gglwe(self, gglwe, tsk, scratch); + } +} + +impl<BE: Backend> GGSWFromGGLWE<BE> for Module<BE> where Self: GGSWExpandRows<BE> + VecZnxCopy {} + +pub trait GGSWFromGGLWE<BE: Backend> +where + Self: GGSWExpandRows<BE> + VecZnxCopy, +{ + fn ggsw_from_gglwe_tmp_bytes<R, A>(&self, res_infos: &R, tsk_infos: &A) -> usize + where + R: GGSWInfos, + A: GGLWEInfos, + { + self.ggsw_expand_rows_tmp_bytes(res_infos, tsk_infos) + } + + fn ggsw_from_gglwe<R, A, T>(&self, res: &mut R, a: &A, tsk: &T, scratch: &mut Scratch<BE>) + where + R: GGSWToMut, + A: GGLWEToRef, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let a: &GGLWE<&[u8]> = &a.to_ref(); + let tsk: &TensorKeyPrepared<&[u8], BE> = &tsk.to_ref(); + + assert_eq!(res.rank(), a.rank_out()); + assert_eq!(res.dnum(), a.dnum()); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(a.n(), self.n() as u32); + assert_eq!(tsk.n(), self.n() as u32); + + for row in 0..res.dnum().into() { + res.at_mut(row, 0).copy(self, &a.at(row, 0)); + } + + self.ggsw_expand_row(res, tsk, scratch); + } +} + +impl<BE: Backend> GGSWExpandRows<BE> for Module<BE> where + Self: Sized + + ModuleN + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigBytesOf + + VecZnxNormalizeTmpBytes + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigBytesOf + + VecZnxNormalizeTmpBytes + + VecZnxDftApply<BE> + + VecZnxDftCopy<BE> + + VmpApplyDftToDft<BE> + + VmpApplyDftToDftAdd<BE> + + VecZnxDftAddInplace<BE> + + VecZnxBigNormalize<BE> + + VecZnxIdftApplyTmpA<BE> + + VecZnxNormalize<BE> +{ +} + +pub(crate) trait GGSWExpandRows<BE: Backend> +where + Self: Sized + + ModuleN + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigBytesOf + + VecZnxNormalizeTmpBytes + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigBytesOf + + VecZnxNormalizeTmpBytes + + VecZnxDftApply<BE> + + VecZnxDftCopy<BE> + + VmpApplyDftToDft<BE> + + VmpApplyDftToDftAdd<BE> + + VecZnxDftAddInplace<BE> + + VecZnxBigNormalize<BE> + + VecZnxIdftApplyTmpA<BE> + + VecZnxNormalize<BE>, +{ + fn ggsw_expand_rows_tmp_bytes<R, A>(&self, res_infos: &R, tsk_infos: &A) -> usize + where + R: GGSWInfos, + A: GGLWEInfos, + { + let tsk_size: usize = tsk_infos.k().div_ceil(tsk_infos.base2k()) as usize; + let size_in: usize = res_infos + .k() + .div_ceil(tsk_infos.base2k()) + .div_ceil(tsk_infos.dsize().into()) as usize; + + let tmp_dft_i: usize = self.bytes_of_vec_znx_dft((tsk_infos.rank_out() + 1).into(), tsk_size); + let tmp_a: usize = self.bytes_of_vec_znx_dft(1, size_in); + let vmp: usize = self.vmp_apply_dft_to_dft_tmp_bytes( + tsk_size, + size_in, + size_in, + (tsk_infos.rank_in()).into(), // Verify if rank+1 + (tsk_infos.rank_out()).into(), // Verify if rank+1 + tsk_size, + ); + let tmp_idft: usize = self.bytes_of_vec_znx_big(1, tsk_size); + let norm: usize = self.vec_znx_normalize_tmp_bytes(); + + tmp_dft_i + ((tmp_a + vmp) | (tmp_idft + norm)) + } + + fn ggsw_expand_row<R, T>(&self, res: &mut R, tsk: &T, scratch: &mut Scratch<BE>) + where + R: GGSWToMut, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let tsk: &TensorKeyPrepared<&[u8], BE> = &tsk.to_ref(); + + let basek_in: usize = res.base2k().into(); + let basek_tsk: usize = tsk.base2k().into(); + + assert!(scratch.available() >= self.ggsw_expand_rows_tmp_bytes(res, tsk)); + + let rank: usize = res.rank().into(); + let cols: usize = rank + 1; + + let a_size: usize = (res.size() * basek_in).div_ceil(basek_tsk); + + // Keyswitch the j-th row of the col 0 + for row_i in 0..res.dnum().into() { + let a = &res.at(row_i, 0).data; + + // Pre-compute DFT of (a0, a1, a2) + let (mut ci_dft, scratch_1) = scratch.take_vec_znx_dft(self, cols, a_size); + + if basek_in == basek_tsk { + for i in 0..cols { + self.vec_znx_dft_apply(1, 0, &mut ci_dft, i, a, i); + } + } else { + let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(self, 1, a_size); + for i in 0..cols { + self.vec_znx_normalize(basek_tsk, &mut a_conv, 0, basek_in, a, i, scratch_2); + self.vec_znx_dft_apply(1, 0, &mut ci_dft, i, &a_conv, 0); + } + } + + for col_j in 1..cols { + // Example for rank 3: + // + // Note: M is a vector (m, Bm, B^2m, B^3m, ...), so each column is + // actually composed of that many dnum and we focus on a specific row here + // implicitely given ci_dft. + // + // # Input + // + // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0 , a1 , a2 ) + // col 1: (0, 0, 0, 0) + // col 2: (0, 0, 0, 0) + // col 3: (0, 0, 0, 0) + // + // # Output + // + // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0 , a1 , a2 ) + // col 1: (-(b0s0 + b1s1 + b2s2) , b0 + M[i], b1 , b2 ) + // col 2: (-(c0s0 + c1s1 + c2s2) , c0 , c1 + M[i], c2 ) + // col 3: (-(d0s0 + d1s1 + d2s2) , d0 , d1 , d2 + M[i]) + + let dsize: usize = tsk.dsize().into(); + + let (mut tmp_dft_i, scratch_2) = scratch_1.take_vec_znx_dft(self, cols, tsk.size()); + let (mut tmp_a, scratch_3) = scratch_2.take_vec_znx_dft(self, 1, ci_dft.size().div_ceil(dsize)); + + { + // Performs a key-switch for each combination of s[i]*s[j], i.e. for a0, a1, a2 + // + // # Example for col=1 + // + // a0 * (-(f0s0 + f1s1 + f1s2) + s0^2, f0, f1, f2) = (-(a0f0s0 + a0f1s1 + a0f1s2) + a0s0^2, a0f0, a0f1, a0f2) + // + + // a1 * (-(g0s0 + g1s1 + g1s2) + s0s1, g0, g1, g2) = (-(a1g0s0 + a1g1s1 + a1g1s2) + a1s0s1, a1g0, a1g1, a1g2) + // + + // a2 * (-(h0s0 + h1s1 + h1s2) + s0s2, h0, h1, h2) = (-(a2h0s0 + a2h1s1 + a2h1s2) + a2s0s2, a2h0, a2h1, a2h2) + // = + // (-(x0s0 + x1s1 + x2s2) + s0(a0s0 + a1s1 + a2s2), x0, x1, x2) + for col_i in 1..cols { + let pmat: &VmpPMat<&[u8], BE> = &tsk.at(col_i - 1, col_j - 1).key.data; // Selects Enc(s[i]s[j]) + + // Extracts a[i] and multipies with Enc(s[i]s[j]) + for di in 0..dsize { + tmp_a.set_size((ci_dft.size() + di) / dsize); + + // Small optimization for dsize > 2 + // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then + // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}. + // As such we can ignore the last dsize-2 limbs safely of the sum of vmp products. + // It is possible to further ignore the last dsize-1 limbs, but this introduce + // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same + // noise is kept with respect to the ideal functionality. + tmp_dft_i.set_size(tsk.size() - ((dsize - di) as isize - 2).max(0) as usize); + + self.vec_znx_dft_copy(dsize, dsize - 1 - di, &mut tmp_a, 0, &ci_dft, col_i); + if di == 0 && col_i == 1 { + self.vmp_apply_dft_to_dft(&mut tmp_dft_i, &tmp_a, pmat, scratch_3); + } else { + self.vmp_apply_dft_to_dft_add(&mut tmp_dft_i, &tmp_a, pmat, di, scratch_3); + } + } + } + } + + // Adds -(sum a[i] * s[i]) + m) on the i-th column of tmp_idft_i + // + // (-(x0s0 + x1s1 + x2s2) + a0s0s0 + a1s0s1 + a2s0s2, x0, x1, x2) + // + + // (0, -(a0s0 + a1s1 + a2s2) + M[i], 0, 0) + // = + // (-(x0s0 + x1s1 + x2s2) + s0(a0s0 + a1s1 + a2s2), x0 -(a0s0 + a1s1 + a2s2) + M[i], x1, x2) + // = + // (-(x0s0 + x1s1 + x2s2), x0 + M[i], x1, x2) + self.vec_znx_dft_add_inplace(&mut tmp_dft_i, col_j, &ci_dft, 0); + let (mut tmp_idft, scratch_3) = scratch_2.take_vec_znx_big(self, 1, tsk.size()); + for i in 0..cols { + self.vec_znx_idft_apply_tmpa(&mut tmp_idft, 0, &mut tmp_dft_i, i); + self.vec_znx_big_normalize( + basek_in, + &mut res.at_mut(row_i, col_j).data, + i, + basek_tsk, + &tmp_idft, + 0, + scratch_3, + ); + } + } + } + } +}
M poulpy-core/src/conversion/glwe_to_lwe.rs → poulpy-core/src/conversion/glwe_to_lwe.rs

@@ -1,22 +1,16 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, - VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, + VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero}, }; -use crate::{ - TakeGLWECt, - layouts::{ - GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos, Rank, - prepared::GLWEToLWESwitchingKeyPrepared, - }, -}; +use crate::layouts::{GGLWEInfos, GLWE, GLWEInfos, GLWELayout, LWE, LWEInfos, Rank, prepared::GLWEToLWESwitchingKeyPrepared}; -impl LWECiphertext<Vec<u8>> { - pub fn from_glwe_scratch_space<B: Backend, OUT, IN, KEY>( +impl LWE<Vec<u8>> { + pub fn from_glwe_tmp_bytes<B: Backend, OUT, IN, KEY>( module: &Module<B>, lwe_infos: &OUT, glwe_infos: &IN,

@@ -26,26 +20,26 @@ where

OUT: LWEInfos, IN: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_layout: GLWELayout = GLWELayout { n: module.n().into(), base2k: lwe_infos.base2k(), k: lwe_infos.k(), rank: Rank(1), }; - GLWECiphertext::alloc_bytes_with( + GLWE::bytes_of( module.n().into(), lwe_infos.base2k(), lwe_infos.k(), 1u32.into(), - ) + GLWECiphertext::keyswitch_scratch_space(module, &glwe_layout, glwe_infos, key_infos) + ) + GLWE::keyswitch_tmp_bytes(module, &glwe_layout, glwe_infos, key_infos) } } -impl<DLwe: DataMut> LWECiphertext<DLwe> { - pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWECiphertext<DGlwe>) { +impl<DLwe: DataMut> LWE<DLwe> { + pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWE<DGlwe>) { #[cfg(debug_assertions)] { assert!(self.n() <= a.n());

@@ -66,13 +60,13 @@

pub fn from_glwe<DGlwe, DKs, B: Backend>( &mut self, module: &Module<B>, - a: &GLWECiphertext<DGlwe>, + a: &GLWE<DGlwe>, ks: &GLWEToLWESwitchingKeyPrepared<DKs, B>, scratch: &mut Scratch<B>, ) where DGlwe: DataRef, DKs: DataRef, - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -83,7 +77,7 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeGLWECt + TakeVecZnx, + Scratch<B>:, { #[cfg(debug_assertions)] {

@@ -92,7 +86,7 @@ assert_eq!(ks.n(), module.n() as u32);

assert!(self.n() <= module.n() as u32); } - let glwe_layout: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_layout: GLWELayout = GLWELayout { n: module.n().into(), base2k: self.base2k(), k: self.k(),
M poulpy-core/src/conversion/lwe_to_glwe.rs → poulpy-core/src/conversion/lwe_to_glwe.rs

@@ -1,22 +1,16 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, + ScratchAvailable, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, ZnxView, ZnxViewMut, ZnxZero}, }; -use crate::{ - TakeGLWECt, - layouts::{ - GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWECiphertext, LWEInfos, - prepared::LWEToGLWESwitchingKeyPrepared, - }, -}; +use crate::layouts::{GGLWEInfos, GLWE, GLWEInfos, GLWELayout, LWE, LWEInfos, prepared::LWEToGLWESwitchingKeyPrepared}; -impl GLWECiphertext<Vec<u8>> { - pub fn from_lwe_scratch_space<B: Backend, OUT, IN, KEY>( +impl GLWE<Vec<u8>> { + pub fn from_lwe_tmp_bytes<B: Backend, OUT, IN, KEY>( module: &Module<B>, glwe_infos: &OUT, lwe_infos: &IN,

@@ -26,35 +20,35 @@ where

OUT: GLWEInfos, IN: LWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - let ct: usize = GLWECiphertext::alloc_bytes_with( + let ct: usize = GLWE::bytes_of( module.n().into(), key_infos.base2k(), lwe_infos.k().max(glwe_infos.k()), 1u32.into(), ); - let ks: usize = GLWECiphertext::keyswitch_inplace_scratch_space(module, glwe_infos, key_infos); + let ks: usize = GLWE::keyswitch_inplace_tmp_bytes(module, glwe_infos, key_infos); if lwe_infos.base2k() == key_infos.base2k() { ct + ks } else { - let a_conv = VecZnx::alloc_bytes(module.n(), 1, lwe_infos.size()) + module.vec_znx_normalize_tmp_bytes(); + let a_conv = VecZnx::bytes_of(module.n(), 1, lwe_infos.size()) + module.vec_znx_normalize_tmp_bytes(); ct + a_conv + ks } } } -impl<D: DataMut> GLWECiphertext<D> { +impl<D: DataMut> GLWE<D> { pub fn from_lwe<DLwe, DKsk, B: Backend>( &mut self, module: &Module<B>, - lwe: &LWECiphertext<DLwe>, + lwe: &LWE<DLwe>, ksk: &LWEToGLWESwitchingKeyPrepared<DKsk, B>, scratch: &mut Scratch<B>, ) where DLwe: DataRef, DKsk: DataRef, - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -65,7 +59,7 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeGLWECt + TakeVecZnx, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -74,7 +68,7 @@ assert_eq!(ksk.n(), module.n() as u32);

assert!(lwe.n() <= module.n() as u32); } - let (mut glwe, scratch_1) = scratch.take_glwe_ct(&GLWECiphertextLayout { + let (mut glwe, scratch_1) = scratch.take_glwe_ct(&GLWELayout { n: ksk.n(), base2k: ksk.base2k(), k: lwe.k(),
M poulpy-core/src/conversion/mod.rs → poulpy-core/src/conversion/mod.rs

@@ -1,2 +1,5 @@

+mod gglwe_to_ggsw; mod glwe_to_lwe; mod lwe_to_glwe; + +pub use gglwe_to_ggsw::*;
M poulpy-core/src/decryption/glwe_ct.rs → poulpy-core/src/decryption/glwe_ct.rs

@@ -1,25 +1,25 @@

use poulpy_hal::{ api::{ - SvpApplyDftToDftInplace, TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, + SvpApplyDftToDftInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, }, layouts::{Backend, DataMut, DataRef, DataViewMut, Module, Scratch}, }; -use crate::layouts::{GLWECiphertext, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; +use crate::layouts::{GLWE, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; -impl GLWECiphertext<Vec<u8>> { - pub fn decrypt_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GLWE<Vec<u8>> { + pub fn decrypt_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GLWEInfos, - Module<B>: VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { let size: usize = infos.size(); - (module.vec_znx_normalize_tmp_bytes() | module.vec_znx_dft_alloc_bytes(1, size)) + module.vec_znx_dft_alloc_bytes(1, size) + (module.vec_znx_normalize_tmp_bytes() | module.bytes_of_vec_znx_dft(1, size)) + module.bytes_of_vec_znx_dft(1, size) } } -impl<DataSelf: DataRef> GLWECiphertext<DataSelf> { +impl<DataSelf: DataRef> GLWE<DataSelf> { pub fn decrypt<DataPt: DataMut, DataSk: DataRef, B: Backend>( &self, module: &Module<B>,

@@ -33,7 +33,7 @@ + VecZnxIdftApplyConsume<B>

+ VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxBigNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnxBig<B>, + Scratch<B>:, { #[cfg(debug_assertions)] {
M poulpy-core/src/decryption/lwe_ct.rs → poulpy-core/src/decryption/lwe_ct.rs

@@ -4,9 +4,9 @@ layouts::{Backend, DataMut, DataRef, Module, ScratchOwned, ZnxView, ZnxViewMut},

oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::layouts::{LWECiphertext, LWEInfos, LWEPlaintext, LWESecret}; +use crate::layouts::{LWE, LWEInfos, LWEPlaintext, LWESecret}; -impl<DataSelf> LWECiphertext<DataSelf> +impl<DataSelf> LWE<DataSelf> where DataSelf: DataRef, {
M poulpy-core/src/encryption/compressed/gglwe_atk.rs → poulpy-core/src/encryption/compressed/gglwe_atk.rs

@@ -1,84 +1,81 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, - }, + api::{ScratchAvailable, SvpPPolBytesOf, VecZnxAutomorphism, VecZnxDftBytesOf, VecZnxNormalizeTmpBytes}, layouts::{Backend, DataMut, DataRef, Module, Scratch}, source::Source, }; use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, + encryption::compressed::gglwe_ksk::GGLWEKeyCompressedEncryptSk, layouts::{ - GGLWEInfos, GLWEInfos, GLWESecret, LWEInfos, - compressed::{GGLWEAutomorphismKeyCompressed, GGLWESwitchingKeyCompressed}, + GGLWEInfos, GLWEInfos, GLWESecret, GLWESecretToRef, LWEInfos, + compressed::{AutomorphismKeyCompressed, AutomorphismKeyCompressedToMut, GLWESwitchingKeyCompressed}, }, }; -impl GGLWEAutomorphismKeyCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl AutomorphismKeyCompressed<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + SvpPPolAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + SvpPPolBytesOf, { assert_eq!(module.n() as u32, infos.n()); - GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space(module, infos) - + GLWESecret::alloc_bytes_with(infos.n(), infos.rank_out()) + GLWESwitchingKeyCompressed::encrypt_sk_tmp_bytes(module, infos) + GLWESecret::bytes_of(infos.n(), infos.rank_out()) } } -impl<DataSelf: DataMut> GGLWEAutomorphismKeyCompressed<DataSelf> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, +pub trait GGLWEAutomorphismKeyCompressedEncryptSk<B: Backend> { + fn gglwe_automorphism_key_compressed_encrypt_sk<R, S>( + &self, + res: &mut R, p: i64, - sk: &GLWESecret<DataSk>, + sk: &S, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: AutomorphismKeyCompressedToMut, + S: GLWESecretToRef; +} + +impl<B: Backend> GGLWEAutomorphismKeyCompressedEncryptSk<B> for Module<B> +where + Module<B>: GGLWEKeyCompressedEncryptSk<B> + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + SvpPPolBytesOf + VecZnxAutomorphism, + Scratch<B>: ScratchAvailable, +{ + fn gglwe_automorphism_key_compressed_encrypt_sk<R, S>( + &self, + res: &mut R, + p: i64, + sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxAutomorphism - + SvpPrepare<B> - + SvpPPolAllocBytes - + VecZnxSwitchRing - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub - + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + R: AutomorphismKeyCompressedToMut, + S: GLWESecretToRef, { + let res: &mut AutomorphismKeyCompressed<&mut [u8]> = &mut res.to_mut(); + let sk: &GLWESecret<&[u8]> = &sk.to_ref(); + #[cfg(debug_assertions)] { - assert_eq!(self.n(), sk.n()); - assert_eq!(self.rank_out(), self.rank_in()); - assert_eq!(sk.rank(), self.rank_out()); + assert_eq!(res.n(), sk.n()); + assert_eq!(res.rank_out(), res.rank_in()); + assert_eq!(sk.rank(), res.rank_out()); assert!( - scratch.available() >= GGLWEAutomorphismKeyCompressed::encrypt_sk_scratch_space(module, self), - "scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space: {}", + scratch.available() >= AutomorphismKeyCompressed::encrypt_sk_tmp_bytes(self, res), + "scratch.available(): {} < AutomorphismKey::encrypt_sk_tmp_bytes: {}", scratch.available(), - GGLWEAutomorphismKeyCompressed::encrypt_sk_scratch_space(module, self) + AutomorphismKeyCompressed::encrypt_sk_tmp_bytes(self, res) ) } let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank()); { - (0..self.rank_out().into()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), + (0..res.rank_out().into()).for_each(|i| { + self.vec_znx_automorphism( + self.galois_element_inv(p), &mut sk_out.data.as_vec_znx_mut(), i, &sk.data.as_vec_znx(),

@@ -87,9 +84,25 @@ );

}); } - self.key - .encrypt_sk(module, sk, &sk_out, seed_xa, source_xe, scratch_1); + self.gglwe_key_compressed_encrypt_sk(&mut res.key, sk, &sk_out, seed_xa, source_xe, scratch_1); + + res.p = p; + } +} - self.p = p; +impl<DataSelf: DataMut> AutomorphismKeyCompressed<DataSelf> { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk<DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + p: i64, + sk: &GLWESecret<DataSk>, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWEAutomorphismKeyCompressedEncryptSk<B>, + { + module.gglwe_automorphism_key_compressed_encrypt_sk(self, p, sk, seed_xa, source_xe, scratch); } }
M poulpy-core/src/encryption/compressed/gglwe_ct.rs → poulpy-core/src/encryption/compressed/gglwe_ct.rs

@@ -1,117 +1,150 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, + ScratchAvailable, VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, + ZnNormalizeInplace, }, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, ZnxZero}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxZero}, source::Source, }; use crate::{ - TakeGLWEPt, - encryption::{SIGMA, glwe_encrypt_sk_internal}, - layouts::{GGLWECiphertext, GGLWEInfos, LWEInfos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretPrepared}, + encryption::{SIGMA, glwe_ct::GLWEEncryptSkInternal}, + layouts::{ + GGLWE, GGLWEInfos, LWEInfos, + compressed::{GGLWECompressed, GGLWECompressedToMut}, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, + }, }; -impl GGLWECiphertextCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl<D: DataMut> GGLWECompressed<D> { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretPrepared<DataSk, B>, + seed: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWECompressedEncryptSk<B>, + { + module.gglwe_compressed_encrypt_sk(self, pt, sk, seed, source_xe, scratch); + } +} + +impl GGLWECompressed<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { - GGLWECiphertext::encrypt_sk_scratch_space(module, infos) + GGLWE::encrypt_sk_tmp_bytes(module, infos) } } -impl<D: DataMut> GGLWECiphertextCompressed<D> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretPrepared<DataSk, B>, +pub trait GGLWECompressedEncryptSk<B: Backend> { + fn gglwe_compressed_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, seed: [u8; 32], source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GGLWECompressedToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GGLWECompressedEncryptSk<B> for Module<B> +where + Module<B>: GLWEEncryptSkInternal<B> + + VecZnxNormalizeInplace<B> + + VecZnxNormalizeTmpBytes + + VecZnxDftBytesOf + + VecZnxAddScalarInplace + + ZnNormalizeInplace<B>, + Scratch<B>: ScratchAvailable, +{ + fn gglwe_compressed_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, + seed: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GGLWECompressedToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>, { + let res: &mut GGLWECompressed<&mut [u8]> = &mut res.to_mut(); + let pt: &ScalarZnx<&[u8]> = &pt.to_ref(); + #[cfg(debug_assertions)] { use poulpy_hal::layouts::ZnxInfos; + let sk = &sk.to_ref(); assert_eq!( - self.rank_in(), + res.rank_in(), pt.cols() as u32, - "self.rank_in(): {} != pt.cols(): {}", - self.rank_in(), + "res.rank_in(): {} != pt.cols(): {}", + res.rank_in(), pt.cols() ); assert_eq!( - self.rank_out(), + res.rank_out(), sk.rank(), - "self.rank_out(): {} != sk.rank(): {}", - self.rank_out(), + "res.rank_out(): {} != sk.rank(): {}", + res.rank_out(), sk.rank() ); - assert_eq!(self.n(), sk.n()); + assert_eq!(res.n(), sk.n()); assert_eq!(pt.n() as u32, sk.n()); assert!( - scratch.available() >= GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, self), - "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space: {}", + scratch.available() >= GGLWECompressed::encrypt_sk_tmp_bytes(self, res), + "scratch.available: {} < GGLWECiphertext::encrypt_sk_tmp_bytes: {}", scratch.available(), - GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, self) + GGLWECompressed::encrypt_sk_tmp_bytes(self, res) ); assert!( - self.dnum().0 * self.dsize().0 * self.base2k().0 <= self.k().0, - "self.dnum() : {} * self.dsize() : {} * self.base2k() : {} = {} >= self.k() = {}", - self.dnum(), - self.dsize(), - self.base2k(), - self.dnum().0 * self.dsize().0 * self.base2k().0, - self.k() + res.dnum().0 * res.dsize().0 * res.base2k().0 <= res.k().0, + "res.dnum() : {} * res.dsize() : {} * res.base2k() : {} = {} >= res.k() = {}", + res.dnum(), + res.dsize(), + res.base2k(), + res.dnum().0 * res.dsize().0 * res.base2k().0, + res.k() ); } - let dnum: usize = self.dnum().into(); - let dsize: usize = self.dsize().into(); - let base2k: usize = self.base2k().into(); - let rank_in: usize = self.rank_in().into(); - let cols: usize = (self.rank_out() + 1).into(); + let dnum: usize = res.dnum().into(); + let dsize: usize = res.dsize().into(); + let base2k: usize = res.base2k().into(); + let rank_in: usize = res.rank_in().into(); + let cols: usize = (res.rank_out() + 1).into(); let mut source_xa = Source::new(seed); - let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(self); + let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(res); (0..rank_in).for_each(|col_i| { (0..dnum).for_each(|d_i| { // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt tmp_pt.data.zero(); // zeroes for next iteration - module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + d_i * dsize, pt, col_i); - module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1); + self.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + d_i * dsize, pt, col_i); + self.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1); let (seed, mut source_xa_tmp) = source_xa.branch(); - self.seed[col_i * dnum + d_i] = seed; + res.seed[col_i * dnum + d_i] = seed; - glwe_encrypt_sk_internal( - module, - self.base2k().into(), - self.k().into(), - &mut self.at_mut(d_i, col_i).data, + self.glwe_encrypt_sk_internal( + res.base2k().into(), + res.k().into(), + &mut res.at_mut(d_i, col_i).data, cols, true, Some((&tmp_pt, 0)),
M poulpy-core/src/encryption/compressed/gglwe_ksk.rs → poulpy-core/src/encryption/compressed/gglwe_ksk.rs

@@ -1,35 +1,31 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, - VecZnxSubInplace, VecZnxSwitchRing, - }, + api::{ScratchAvailable, SvpPPolBytesOf, SvpPrepare, VecZnxDftBytesOf, VecZnxNormalizeTmpBytes, VecZnxSwitchRing}, layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, source::Source, }; use crate::{ - TakeGLWESecretPrepared, + encryption::compressed::gglwe_ct::GGLWECompressedEncryptSk, layouts::{ - Degree, GGLWECiphertext, GGLWEInfos, GLWEInfos, GLWESecret, LWEInfos, compressed::GGLWESwitchingKeyCompressed, + GGLWE, GGLWEInfos, GLWEInfos, GLWESecret, GLWESecretToRef, LWEInfos, RingDegree, + compressed::{GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedToMut}, prepared::GLWESecretPrepared, }, }; -impl GGLWESwitchingKeyCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GLWESwitchingKeyCompressed<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + SvpPPolAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + SvpPPolBytesOf, { - (GGLWECiphertext::encrypt_sk_scratch_space(module, infos) | ScalarZnx::alloc_bytes(module.n(), 1)) - + ScalarZnx::alloc_bytes(module.n(), infos.rank_in().into()) - + GLWESecretPrepared::alloc_bytes_with(module, infos.rank_out()) + (GGLWE::encrypt_sk_tmp_bytes(module, infos) | ScalarZnx::bytes_of(module.n(), 1)) + + ScalarZnx::bytes_of(module.n(), infos.rank_in().into()) + + GLWESecretPrepared::bytes_of(module, infos.rank_out()) } } -impl<DataSelf: DataMut> GGLWESwitchingKeyCompressed<DataSelf> { +impl<DataSelf: DataMut> GLWESwitchingKeyCompressed<DataSelf> { #[allow(clippy::too_many_arguments)] pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>( &mut self,

@@ -40,36 +36,65 @@ seed_xa: [u8; 32],

source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: SvpPrepare<B> - + SvpPPolAllocBytes - + VecZnxSwitchRing - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub - + VecZnxAddScalarInplace, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + Module<B>: GGLWEKeyCompressedEncryptSk<B>, + { + module.gglwe_key_compressed_encrypt_sk(self, sk_in, sk_out, seed_xa, source_xe, scratch); + } +} + +pub trait GGLWEKeyCompressedEncryptSk<B: Backend> { + fn gglwe_key_compressed_encrypt_sk<R, SI, SO>( + &self, + res: &mut R, + sk_in: &SI, + sk_out: &SO, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWESwitchingKeyCompressedToMut, + SI: GLWESecretToRef, + SO: GLWESecretToRef; +} + +impl<B: Backend> GGLWEKeyCompressedEncryptSk<B> for Module<B> +where + Module<B>: GGLWECompressedEncryptSk<B> + + SvpPPolBytesOf + + VecZnxNormalizeTmpBytes + + VecZnxDftBytesOf + + VecZnxSwitchRing + + SvpPrepare<B>, + Scratch<B>: ScratchAvailable, +{ + fn gglwe_key_compressed_encrypt_sk<R, SI, SO>( + &self, + res: &mut R, + sk_in: &SI, + sk_out: &SO, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWESwitchingKeyCompressedToMut, + SI: GLWESecretToRef, + SO: GLWESecretToRef, { + let res: &mut GLWESwitchingKeyCompressed<&mut [u8]> = &mut res.to_mut(); + let sk_in: &GLWESecret<&[u8]> = &sk_in.to_ref(); + let sk_out: &GLWESecret<&[u8]> = &sk_out.to_ref(); + #[cfg(debug_assertions)] { - use crate::layouts::GGLWESwitchingKey; + use crate::layouts::GLWESwitchingKey; - assert!(sk_in.n().0 <= module.n() as u32); - assert!(sk_out.n().0 <= module.n() as u32); + assert!(sk_in.n().0 <= self.n() as u32); + assert!(sk_out.n().0 <= self.n() as u32); assert!( - scratch.available() >= GGLWESwitchingKey::encrypt_sk_scratch_space(module, self), - "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}", + scratch.available() >= GLWESwitchingKey::encrypt_sk_tmp_bytes(self, res), + "scratch.available()={} < GLWESwitchingKey::encrypt_sk_tmp_bytes={}", scratch.available(), - GGLWESwitchingKey::encrypt_sk_scratch_space(module, self) + GLWESwitchingKey::encrypt_sk_tmp_bytes(self, res) ) }

@@ -77,7 +102,7 @@ let n: usize = sk_in.n().max(sk_out.n()).into();

let (mut sk_in_tmp, scratch_1) = scratch.take_scalar_znx(n, sk_in.rank().into()); (0..sk_in.rank().into()).for_each(|i| { - module.vec_znx_switch_ring( + self.vec_znx_switch_ring( &mut sk_in_tmp.as_vec_znx_mut(), i, &sk_in.data.as_vec_znx(),

@@ -85,24 +110,24 @@ i,

); }); - let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(Degree(n as u32), sk_out.rank()); + let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(RingDegree(n as u32), sk_out.rank()); { let (mut tmp, _) = scratch_2.take_scalar_znx(n, 1); (0..sk_out.rank().into()).for_each(|i| { - module.vec_znx_switch_ring(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i); - module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0); + self.vec_znx_switch_ring(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i); + self.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0); }); } - self.key.encrypt_sk( - module, + self.gglwe_compressed_encrypt_sk( + &mut res.key, &sk_in_tmp, &sk_out_tmp, seed_xa, source_xe, scratch_2, ); - self.sk_in_n = sk_in.n().into(); - self.sk_out_n = sk_out.n().into(); + res.sk_in_n = sk_in.n().into(); + res.sk_out_n = sk_out.n().into(); } }
M poulpy-core/src/encryption/compressed/gglwe_tsk.rs → poulpy-core/src/encryption/compressed/gglwe_tsk.rs

@@ -1,86 +1,83 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, - TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAllocBytes, - VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, - VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, + SvpApplyDftToDft, SvpPPolBytesOf, SvpPrepare, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, + VecZnxIdftApplyTmpA, VecZnxNormalizeTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch}, source::Source, }; use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, + encryption::compressed::gglwe_ksk::GGLWEKeyCompressedEncryptSk, layouts::{ - GGLWEInfos, GGLWETensorKey, GLWEInfos, GLWESecret, LWEInfos, Rank, compressed::GGLWETensorKeyCompressed, - prepared::Prepare, + GGLWEInfos, GLWEInfos, GLWESecret, GLWESecretToRef, LWEInfos, Rank, TensorKey, + compressed::{TensorKeyCompressed, TensorKeyCompressedToMut}, }, }; -impl GGLWETensorKeyCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl TensorKeyCompressed<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: - SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + VecZnxBigAllocBytes, + Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + VecZnxBigBytesOf, { - GGLWETensorKey::encrypt_sk_scratch_space(module, infos) + TensorKey::encrypt_sk_tmp_bytes(module, infos) } } -impl<DataSelf: DataMut> GGLWETensorKeyCompressed<DataSelf> { - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - sk: &GLWESecret<DataSk>, +pub trait GGLWETensorKeyCompressedEncryptSk<B: Backend> { + fn gglwe_tensor_key_encrypt_sk<R, S>( + &self, + res: &mut R, + sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: SvpApplyDftToDft<B> - + VecZnxIdftApplyTmpA<B> - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub - + VecZnxSwitchRing - + VecZnxAddScalarInplace - + SvpPrepare<B> - + SvpPPolAllocBytes - + SvpPPolAlloc<B>, - Scratch<B>: ScratchAvailable - + TakeScalarZnx - + TakeVecZnxDft<B> - + TakeGLWESecretPrepared<B> - + ScratchAvailable - + TakeVecZnx - + TakeVecZnxBig<B>, + R: TensorKeyCompressedToMut, + S: GLWESecretToRef; +} + +impl<B: Backend> GGLWETensorKeyCompressedEncryptSk<B> for Module<B> +where + Module<B>: GGLWEKeyCompressedEncryptSk<B> + + VecZnxDftApply<B> + + SvpApplyDftToDft<B> + + VecZnxIdftApplyTmpA<B> + + VecZnxBigNormalize<B> + + SvpPrepare<B>, + Scratch<B>:, +{ + fn gglwe_tensor_key_encrypt_sk<R, S>( + &self, + res: &mut R, + sk: &S, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: TensorKeyCompressedToMut, + S: GLWESecretToRef, { + let res: &mut TensorKeyCompressed<&mut [u8]> = &mut res.to_mut(); + let sk: &GLWESecret<&[u8]> = &sk.to_ref(); + #[cfg(debug_assertions)] { - assert_eq!(self.rank_out(), sk.rank()); - assert_eq!(self.n(), sk.n()); + assert_eq!(res.rank_out(), sk.rank()); + assert_eq!(res.n(), sk.n()); } let n: usize = sk.n().into(); - let rank: usize = self.rank_out().into(); + let rank: usize = res.rank_out().into(); - let (mut sk_dft_prep, scratch_1) = scratch.take_glwe_secret_prepared(sk.n(), self.rank_out()); - sk_dft_prep.prepare(module, sk, scratch_1); + let (mut sk_dft_prep, scratch_1) = scratch.take_glwe_secret_prepared(sk.n(), res.rank_out()); + sk_dft_prep.prepare(self, sk, scratch_1); let (mut sk_dft, scratch_2) = scratch_1.take_vec_znx_dft(n, rank, 1); for i in 0..rank { - module.vec_znx_dft_apply(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i); + self.vec_znx_dft_apply(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i); } let (mut sk_ij_big, scratch_3) = scratch_2.take_vec_znx_big(n, 1, 1);

@@ -91,14 +88,14 @@ let mut source_xa: Source = Source::new(seed_xa);

for i in 0..rank { for j in i..rank { - module.svp_apply_dft_to_dft(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i); + self.svp_apply_dft_to_dft(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i); - module.vec_znx_idft_apply_tmpa(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); - module.vec_znx_big_normalize( - self.base2k().into(), + self.vec_znx_idft_apply_tmpa(&mut sk_ij_big, 0, &mut sk_ij_dft, 0); + self.vec_znx_big_normalize( + res.base2k().into(), &mut sk_ij.data.as_vec_znx_mut(), 0, - self.base2k().into(), + res.base2k().into(), &sk_ij_big, 0, scratch_5,

@@ -106,9 +103,30 @@ );

let (seed_xa_tmp, _) = source_xa.branch(); - self.at_mut(i, j) - .encrypt_sk(module, &sk_ij, sk, seed_xa_tmp, source_xe, scratch_5); + self.gglwe_key_compressed_encrypt_sk( + res.at_mut(i, j), + &sk_ij, + sk, + seed_xa_tmp, + source_xe, + scratch_5, + ); } } } } + +impl<DataSelf: DataMut> TensorKeyCompressed<DataSelf> { + pub fn encrypt_sk<DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk: &GLWESecret<DataSk>, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWETensorKeyCompressedEncryptSk<B>, + { + module.gglwe_tensor_key_encrypt_sk(self, sk, seed_xa, source_xe, scratch); + } +}
M poulpy-core/src/encryption/compressed/ggsw_ct.rs → poulpy-core/src/encryption/compressed/ggsw_ct.rs

@@ -1,97 +1,103 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, - }, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, ZnxZero}, + api::{VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxZero}, source::Source, }; use crate::{ - TakeGLWEPt, - encryption::{SIGMA, glwe_encrypt_sk_internal}, + encryption::{SIGMA, glwe_ct::GLWEEncryptSkInternal}, layouts::{ - GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, compressed::GGSWCiphertextCompressed, prepared::GLWESecretPrepared, + GGSW, GGSWInfos, GLWEInfos, LWEInfos, + compressed::{GGSWCompressed, GGSWCompressedToMut}, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, }, }; -impl GGSWCiphertextCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GGSWCompressed<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGSWInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { - GGSWCiphertext::encrypt_sk_scratch_space(module, infos) + GGSW::encrypt_sk_tmp_bytes(module, infos) } } -impl<DataSelf: DataMut> GGSWCiphertextCompressed<DataSelf> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretPrepared<DataSk, B>, +pub trait GGSWCompressedEncryptSk<B: Backend> { + fn ggsw_compressed_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GGSWCompressedToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GGSWCompressedEncryptSk<B> for Module<B> +where + Module<B>: GLWEEncryptSkInternal<B> + VecZnxAddScalarInplace + VecZnxNormalizeInplace<B>, + Scratch<B>:, +{ + fn ggsw_compressed_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GGSWCompressedToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>, { + let res: &mut GGSWCompressed<&mut [u8]> = &mut res.to_mut(); + let sk: &GLWESecretPrepared<&[u8], B> = &sk.to_ref(); + let pt: &ScalarZnx<&[u8]> = &pt.to_ref(); + #[cfg(debug_assertions)] { use poulpy_hal::layouts::ZnxInfos; - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), sk.n()); + assert_eq!(res.rank(), sk.rank()); + assert_eq!(res.n(), sk.n()); assert_eq!(pt.n() as u32, sk.n()); } - let base2k: usize = self.base2k().into(); - let rank: usize = self.rank().into(); + let base2k: usize = res.base2k().into(); + let rank: usize = res.rank().into(); let cols: usize = rank + 1; - let dsize: usize = self.dsize().into(); + let dsize: usize = res.dsize().into(); - let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&self.glwe_layout()); + let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&res.glwe_layout()); let mut source = Source::new(seed_xa); - self.seed = vec![[0u8; 32]; self.dnum().0 as usize * cols]; + res.seed = vec![[0u8; 32]; res.dnum().0 as usize * cols]; - (0..self.dnum().into()).for_each(|row_i| { + for row_i in 0..res.dnum().into() { tmp_pt.data.zero(); // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt - module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0); - module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1); + self.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0); + self.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1); - (0..rank + 1).for_each(|col_j| { + for col_j in 0..rank + 1 { // rlwe encrypt of vec_znx_pt into vec_znx_ct let (seed, mut source_xa_tmp) = source.branch(); - self.seed[row_i * cols + col_j] = seed; + res.seed[row_i * cols + col_j] = seed; - glwe_encrypt_sk_internal( - module, - self.base2k().into(), - self.k().into(), - &mut self.at_mut(row_i, col_j).data, + self.glwe_encrypt_sk_internal( + res.base2k().into(), + res.k().into(), + &mut res.at_mut(row_i, col_j).data, cols, true, Some((&tmp_pt, col_j)),

@@ -101,7 +107,24 @@ source_xe,

SIGMA, scratch_1, ); - }); - }); + } + } + } +} + +impl<DataSelf: DataMut> GGSWCompressed<DataSelf> { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretPrepared<DataSk, B>, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGSWCompressedEncryptSk<B>, + { + module.ggsw_compressed_encrypt_sk(self, pt, sk, seed_xa, source_xe, scratch); } }
M poulpy-core/src/encryption/compressed/glwe_ct.rs → poulpy-core/src/encryption/compressed/glwe_ct.rs

@@ -1,100 +1,95 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, - VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, - }, + api::{VecZnxDftBytesOf, VecZnxNormalizeTmpBytes}, layouts::{Backend, DataMut, DataRef, Module, Scratch}, source::Source, }; use crate::{ - encryption::{SIGMA, glwe_ct::glwe_encrypt_sk_internal}, + encryption::{SIGMA, glwe_ct::GLWEEncryptSkInternal}, layouts::{ - GLWECiphertext, GLWEInfos, GLWEPlaintext, LWEInfos, compressed::GLWECiphertextCompressed, prepared::GLWESecretPrepared, + GLWE, GLWEInfos, GLWEPlaintext, GLWEPlaintextToRef, LWEInfos, + compressed::{GLWECompressed, GLWECompressedToMut}, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, }, }; -impl GLWECiphertextCompressed<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GLWECompressed<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GLWEInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { - GLWECiphertext::encrypt_sk_scratch_space(module, infos) + GLWE::encrypt_sk_tmp_bytes(module, infos) } } -impl<D: DataMut> GLWECiphertextCompressed<D> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &GLWEPlaintext<DataPt>, - sk: &GLWESecretPrepared<DataSk, B>, +pub trait GLWECompressedEncryptSk<B: Backend> { + fn glwe_compressed_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, - { - self.encrypt_sk_internal(module, Some((pt, 0)), sk, seed_xa, source_xe, scratch); - } + R: GLWECompressedToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>; +} - #[allow(clippy::too_many_arguments)] - pub(crate) fn encrypt_sk_internal<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretPrepared<DataSk, B>, +impl<B: Backend> GLWECompressedEncryptSk<B> for Module<B> +where + Module<B>: GLWEEncryptSkInternal<B>, +{ + fn glwe_compressed_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GLWECompressedToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>, { - let mut source_xa = Source::new(seed_xa); - let cols: usize = (self.rank() + 1).into(); - glwe_encrypt_sk_internal( - module, - self.base2k().into(), - self.k().into(), - &mut self.data, + let res: &mut GLWECompressed<&mut [u8]> = &mut res.to_mut(); + let mut source_xa: Source = Source::new(seed_xa); + let cols: usize = (res.rank() + 1).into(); + + self.glwe_encrypt_sk_internal( + res.base2k().into(), + res.k().into(), + &mut res.data, cols, true, - pt, + Some((pt, 0)), sk, &mut source_xa, source_xe, SIGMA, scratch, ); - self.seed = seed_xa; + + res.seed = seed_xa; + } +} + +impl<D: DataMut> GLWECompressed<D> { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &GLWEPlaintext<DataPt>, + sk: &GLWESecretPrepared<DataSk, B>, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GLWECompressedEncryptSk<B>, + { + module.glwe_compressed_encrypt_sk(self, pt, sk, seed_xa, source_xe, scratch); } }
M poulpy-core/src/encryption/gglwe_atk.rs → poulpy-core/src/encryption/gglwe_atk.rs

@@ -1,34 +1,33 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, + ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, + VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, + VecZnxSwitchRing, }, - layouts::{Backend, DataMut, DataRef, Module, Scratch}, + layouts::{Backend, DataMut, Module, Scratch}, source::Source, }; -use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, - layouts::{GGLWEAutomorphismKey, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos}, +use crate::layouts::{ + AutomorphismKey, AutomorphismKeyToMut, GGLWEInfos, GLWEInfos, GLWESecret, GLWESecretToRef, GLWESwitchingKey, LWEInfos, }; -impl GGLWEAutomorphismKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl AutomorphismKey<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<BE: Backend, A>(module: &Module<BE>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<BE>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWEAutomorphismKey" ); - GGLWESwitchingKey::encrypt_sk_scratch_space(module, infos) + GLWESecret::alloc_bytes(&infos.glwe_layout()) + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, infos) + GLWESecret::bytes_of_from_infos(module, &infos.glwe_layout()) } - pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize + pub fn encrypt_pk_tmp_bytes<BE: Backend, A>(module: &Module<BE>, _infos: &A) -> usize where A: GGLWEInfos, {

@@ -37,62 +36,102 @@ _infos.rank_in(),

_infos.rank_out(), "rank_in != rank_out is not supported for GGLWEAutomorphismKey" ); - GGLWESwitchingKey::encrypt_pk_scratch_space(module, _infos) + GLWESwitchingKey::encrypt_pk_tmp_bytes(module, _infos) } } -impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataSk: DataRef, B: Backend>( +pub trait GGLWEAutomorphismKeyEncryptSk<BE: Backend> { + fn gglwe_automorphism_key_encrypt_sk<A, B>( + &self, + res: &mut A, + p: i64, + sk: &B, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<BE>, + ) where + A: AutomorphismKeyToMut, + B: GLWESecretToRef; +} + +impl<DM: DataMut> AutomorphismKey<DM> +where + Self: AutomorphismKeyToMut, +{ + pub fn encrypt_sk<S, BE: Backend>( &mut self, - module: &Module<B>, + module: &Module<BE>, + p: i64, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<BE>, + ) where + S: GLWESecretToRef, + Module<BE>: GGLWEAutomorphismKeyEncryptSk<BE>, + { + module.gglwe_automorphism_key_encrypt_sk(self, p, sk, source_xa, source_xe, scratch); + } +} + +impl<BE: Backend> GGLWEAutomorphismKeyEncryptSk<BE> for Module<BE> +where + Module<BE>: VecZnxAddScalarInplace + + VecZnxDftBytesOf + + VecZnxBigNormalize<BE> + + VecZnxDftApply<BE> + + SvpApplyDftToDftInplace<BE> + + VecZnxIdftApplyConsume<BE> + + VecZnxNormalizeTmpBytes + + VecZnxFillUniform + + VecZnxSubInplace + + VecZnxAddInplace + + VecZnxNormalizeInplace<BE> + + VecZnxAddNormal + + VecZnxNormalize<BE> + + VecZnxSub + + SvpPrepare<BE> + + VecZnxSwitchRing + + SvpPPolBytesOf + + VecZnxAutomorphism, + Scratch<BE>: ScratchAvailable, +{ + fn gglwe_automorphism_key_encrypt_sk<A, B>( + &self, + res: &mut A, p: i64, - sk: &GLWESecret<DataSk>, + sk: &B, source_xa: &mut Source, source_xe: &mut Source, - scratch: &mut Scratch<B>, + scratch: &mut Scratch<BE>, ) where - Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub - + SvpPrepare<B> - + VecZnxSwitchRing - + SvpPPolAllocBytes - + VecZnxAutomorphism, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + A: AutomorphismKeyToMut, + B: GLWESecretToRef, { + let res: &mut AutomorphismKey<&mut [u8]> = &mut res.to_mut(); + let sk: &GLWESecret<&[u8]> = &sk.to_ref(); + #[cfg(debug_assertions)] { use crate::layouts::{GLWEInfos, LWEInfos}; - assert_eq!(self.n(), sk.n()); - assert_eq!(self.rank_out(), self.rank_in()); - assert_eq!(sk.rank(), self.rank_out()); + assert_eq!(res.n(), sk.n()); + assert_eq!(res.rank_out(), res.rank_in()); + assert_eq!(sk.rank(), res.rank_out()); assert!( - scratch.available() >= GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, self), - "scratch.available(): {} < AutomorphismKey::encrypt_sk_scratch_space: {:?}", + scratch.available() >= AutomorphismKey::encrypt_sk_tmp_bytes(self, res), + "scratch.available(): {} < AutomorphismKey::encrypt_sk_tmp_bytes: {:?}", scratch.available(), - GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, self) + AutomorphismKey::encrypt_sk_tmp_bytes(self, res) ) } let (mut sk_out, scratch_1) = scratch.take_glwe_secret(sk.n(), sk.rank()); { - (0..self.rank_out().into()).for_each(|i| { - module.vec_znx_automorphism( - module.galois_element_inv(p), + (0..res.rank_out().into()).for_each(|i| { + self.vec_znx_automorphism( + self.galois_element_inv(p), &mut sk_out.data.as_vec_znx_mut(), i, &sk.data.as_vec_znx(),

@@ -101,9 +140,9 @@ );

}); } - self.key - .encrypt_sk(module, sk, &sk_out, source_xa, source_xe, scratch_1); + res.key + .encrypt_sk(self, sk, &sk_out, source_xa, source_xe, scratch_1); - self.p = p; + res.p = p; } }
M poulpy-core/src/encryption/gglwe_ct.rs → poulpy-core/src/encryption/gglwe_ct.rs

@@ -1,29 +1,28 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, - }, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, ZnxZero}, + api::{ScratchAvailable, VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxZero}, source::Source, }; use crate::{ - TakeGLWEPt, - layouts::{GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}, + encryption::glwe_ct::GLWEEncryptSk, + layouts::{ + GGLWE, GGLWEInfos, GGLWEToMut, GLWE, GLWEPlaintext, LWEInfos, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, + }, }; -impl GGLWECiphertext<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GGLWE<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { - GLWECiphertext::encrypt_sk_scratch_space(module, &infos.glwe_layout()) - + (GLWEPlaintext::alloc_bytes(&infos.glwe_layout()) | module.vec_znx_normalize_tmp_bytes()) + GLWE::encrypt_sk_tmp_bytes(module, &infos.glwe_layout()) + + (GLWEPlaintext::bytes_of_from_infos(module, &infos.glwe_layout()) | module.vec_znx_normalize_tmp_bytes()) } - pub fn encrypt_pk_scratch_space<B: Backend, A>(_module: &Module<B>, _infos: &A) -> usize + pub fn encrypt_pk_tmp_bytes<B: Backend, A>(_module: &Module<B>, _infos: &A) -> usize where A: GGLWEInfos, {

@@ -31,78 +30,88 @@ unimplemented!()

} } -impl<DataSelf: DataMut> GGLWECiphertext<DataSelf> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretPrepared<DataSk, B>, +pub trait GGLWEEncryptSk<B: Backend> { + fn gglwe_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GGLWEToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GGLWEEncryptSk<B> for Module<B> +where + Module<B>: GLWEEncryptSk<B> + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxAddScalarInplace + VecZnxNormalizeInplace<B>, + Scratch<B>: ScratchAvailable, +{ + fn gglwe_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GGLWEToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>, { + let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut(); + let pt: &ScalarZnx<&[u8]> = &pt.to_ref(); + #[cfg(debug_assertions)] { use poulpy_hal::layouts::ZnxInfos; + let sk: GLWESecretPrepared<&[u8], B> = sk.to_ref(); assert_eq!( - self.rank_in(), + res.rank_in(), pt.cols() as u32, - "self.rank_in(): {} != pt.cols(): {}", - self.rank_in(), + "res.rank_in(): {} != pt.cols(): {}", + res.rank_in(), pt.cols() ); assert_eq!( - self.rank_out(), + res.rank_out(), sk.rank(), - "self.rank_out(): {} != sk.rank(): {}", - self.rank_out(), + "res.rank_out(): {} != sk.rank(): {}", + res.rank_out(), sk.rank() ); - assert_eq!(self.n(), sk.n()); + assert_eq!(res.n(), sk.n()); assert_eq!(pt.n() as u32, sk.n()); assert!( - scratch.available() >= GGLWECiphertext::encrypt_sk_scratch_space(module, self), - "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}", + scratch.available() >= GGLWE::encrypt_sk_tmp_bytes(self, res), + "scratch.available: {} < GGLWECiphertext::encrypt_sk_tmp_bytes(self, res.rank()={}, res.size()={}): {}", scratch.available(), - self.rank_out(), - self.size(), - GGLWECiphertext::encrypt_sk_scratch_space(module, self) + res.rank_out(), + res.size(), + GGLWE::encrypt_sk_tmp_bytes(self, res) ); assert!( - self.dnum().0 * self.dsize().0 * self.base2k().0 <= self.k().0, - "self.dnum() : {} * self.dsize() : {} * self.base2k() : {} = {} >= self.k() = {}", - self.dnum(), - self.dsize(), - self.base2k(), - self.dnum().0 * self.dsize().0 * self.base2k().0, - self.k() + res.dnum().0 * res.dsize().0 * res.base2k().0 <= res.k().0, + "res.dnum() : {} * res.dsize() : {} * res.base2k() : {} = {} >= res.k() = {}", + res.dnum(), + res.dsize(), + res.base2k(), + res.dnum().0 * res.dsize().0 * res.base2k().0, + res.k() ); } - let dnum: usize = self.dnum().into(); - let dsize: usize = self.dsize().into(); - let base2k: usize = self.base2k().into(); - let rank_in: usize = self.rank_in().into(); + let dnum: usize = res.dnum().into(); + let dsize: usize = res.dsize().into(); + let base2k: usize = res.base2k().into(); + let rank_in: usize = res.rank_in().into(); - let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(self); + let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(res); // For each input column (i.e. rank) produces a GGLWE ciphertext of rank_out+1 columns // // Example for ksk rank 2 to rank 3:

@@ -114,17 +123,39 @@ // Example ksk rank 2 to rank 1

// // (-(a*s) + s0, a) // (-(b*s) + s1, b) - (0..rank_in).for_each(|col_i| { - (0..dnum).for_each(|row_i| { + + for col_i in 0..rank_in { + for row_i in 0..dnum { // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt tmp_pt.data.zero(); // zeroes for next iteration - module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, col_i); - module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1); + self.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, col_i); + self.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1); + self.glwe_encrypt_sk( + &mut res.at_mut(row_i, col_i), + &tmp_pt, + sk, + source_xa, + source_xe, + scrach_1, + ); + } + } + } +} - // rlwe encrypt of vec_znx_pt into vec_znx_ct - self.at_mut(row_i, col_i) - .encrypt_sk(module, &tmp_pt, sk, source_xa, source_xe, scrach_1); - }); - }); +impl<DataSelf: DataMut> GGLWE<DataSelf> { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretPrepared<DataSk, B>, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGLWEEncryptSk<B>, + { + module.gglwe_encrypt_sk(self, pt, sk, source_xa, source_xe, scratch); } }
M poulpy-core/src/encryption/gglwe_ksk.rs → poulpy-core/src/encryption/gglwe_ksk.rs

@@ -1,41 +1,37 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, - VecZnxSubInplace, VecZnxSwitchRing, + ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, + VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, }, layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch}, source::Source, }; -use crate::{ - TakeGLWESecretPrepared, - layouts::{ - Degree, GGLWECiphertext, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos, prepared::GLWESecretPrepared, - }, +use crate::layouts::{ + GGLWE, GGLWEInfos, GLWEInfos, GLWESecret, GLWESwitchingKey, LWEInfos, RingDegree, prepared::GLWESecretPrepared, }; -impl GGLWESwitchingKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GLWESwitchingKey<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { - (GGLWECiphertext::encrypt_sk_scratch_space(module, infos) | ScalarZnx::alloc_bytes(module.n(), 1)) - + ScalarZnx::alloc_bytes(module.n(), infos.rank_in().into()) - + GLWESecretPrepared::alloc_bytes(module, &infos.glwe_layout()) + (GGLWE::encrypt_sk_tmp_bytes(module, infos) | ScalarZnx::bytes_of(module.n(), 1)) + + ScalarZnx::bytes_of(module.n(), infos.rank_in().into()) + + GLWESecretPrepared::bytes_of_from_infos(module, &infos.glwe_layout()) } - pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize + pub fn encrypt_pk_tmp_bytes<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize where A: GGLWEInfos, { - GGLWECiphertext::encrypt_pk_scratch_space(module, _infos) + GGLWE::encrypt_pk_tmp_bytes(module, _infos) } } -impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> { +impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { #[allow(clippy::too_many_arguments)] pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>( &mut self,

@@ -47,7 +43,7 @@ source_xe: &mut Source,

scratch: &mut Scratch<B>, ) where Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -62,18 +58,18 @@ + VecZnxNormalize<B>

+ VecZnxSub + SvpPrepare<B> + VecZnxSwitchRing - + SvpPPolAllocBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + + SvpPPolBytesOf, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] { assert!(sk_in.n().0 <= module.n() as u32); assert!(sk_out.n().0 <= module.n() as u32); assert!( - scratch.available() >= GGLWESwitchingKey::encrypt_sk_scratch_space(module, self), - "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}", + scratch.available() >= GLWESwitchingKey::encrypt_sk_tmp_bytes(module, self), + "scratch.available()={} < GLWESwitchingKey::encrypt_sk_tmp_bytes={}", scratch.available(), - GGLWESwitchingKey::encrypt_sk_scratch_space(module, self) + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, self) ) }

@@ -89,7 +85,7 @@ i,

); }); - let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(Degree(n as u32), sk_out.rank()); + let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(RingDegree(n as u32), sk_out.rank()); { let (mut tmp, _) = scratch_2.take_scalar_znx(n, 1); (0..sk_out.rank().into()).for_each(|i| {
M poulpy-core/src/encryption/gglwe_tsk.rs → poulpy-core/src/encryption/gglwe_tsk.rs

@@ -1,39 +1,34 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, - TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAllocBytes, - VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, - VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, + SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, + VecZnxAddScalarInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, + VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, + VecZnxSubInplace, VecZnxSwitchRing, }, layouts::{Backend, DataMut, DataRef, Module, Scratch}, source::Source, }; -use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, - layouts::{ - Degree, GGLWEInfos, GGLWESwitchingKey, GGLWETensorKey, GLWEInfos, GLWESecret, LWEInfos, Rank, - prepared::{GLWESecretPrepared, Prepare}, - }, +use crate::layouts::{ + GGLWEInfos, GLWEInfos, GLWESecret, GLWESwitchingKey, LWEInfos, Rank, RingDegree, TensorKey, prepared::GLWESecretPrepared, }; -impl GGLWETensorKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl TensorKey<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: - SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + VecZnxBigAllocBytes, + Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + VecZnxBigBytesOf, { - GLWESecretPrepared::alloc_bytes_with(module, infos.rank_out()) - + module.vec_znx_dft_alloc_bytes(infos.rank_out().into(), 1) - + module.vec_znx_big_alloc_bytes(1, 1) - + module.vec_znx_dft_alloc_bytes(1, 1) - + GLWESecret::alloc_bytes_with(Degree(module.n() as u32), Rank(1)) - + GGLWESwitchingKey::encrypt_sk_scratch_space(module, infos) + GLWESecretPrepared::bytes_of(module, infos.rank_out()) + + module.bytes_of_vec_znx_dft(infos.rank_out().into(), 1) + + module.bytes_of_vec_znx_big(1, 1) + + module.bytes_of_vec_znx_dft(1, 1) + + GLWESecret::bytes_of(RingDegree(module.n() as u32), Rank(1)) + + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, infos) } } -impl<DataSelf: DataMut> GGLWETensorKey<DataSelf> { +impl<DataSelf: DataMut> TensorKey<DataSelf> { pub fn encrypt_sk<DataSk: DataRef, B: Backend>( &mut self, module: &Module<B>,

@@ -45,7 +40,7 @@ ) where

Module<B>: SvpApplyDftToDft<B> + VecZnxIdftApplyTmpA<B> + VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -60,9 +55,8 @@ + VecZnxNormalize<B>

+ VecZnxSub + SvpPrepare<B> + VecZnxSwitchRing - + SvpPPolAllocBytes, - Scratch<B>: - TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B> + TakeVecZnxBig<B>, + + SvpPPolBytesOf, + Scratch<B>:, { #[cfg(debug_assertions)] {

@@ -70,7 +64,7 @@ assert_eq!(self.rank_out(), sk.rank());

assert_eq!(self.n(), sk.n()); } - let n: Degree = sk.n(); + let n: RingDegree = sk.n(); let rank: Rank = self.rank_out(); let (mut sk_dft_prep, scratch_1) = scratch.take_glwe_secret_prepared(n, rank);
M poulpy-core/src/encryption/ggsw_ct.rs → poulpy-core/src/encryption/ggsw_ct.rs

@@ -1,93 +1,124 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, - }, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, VecZnx, ZnxZero}, + api::{VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes}, + layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, VecZnx, ZnxZero}, source::Source, }; use crate::{ - TakeGLWEPt, - layouts::{GGSWCiphertext, GGSWInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GLWESecretPrepared}, + SIGMA, + encryption::glwe_ct::GLWEEncryptSkInternal, + layouts::{ + GGSW, GGSWInfos, GGSWToMut, GLWE, GLWEInfos, LWEInfos, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, + }, }; -impl GGSWCiphertext<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GGSW<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGSWInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { let size = infos.size(); - GLWECiphertext::encrypt_sk_scratch_space(module, &infos.glwe_layout()) - + VecZnx::alloc_bytes(module.n(), (infos.rank() + 1).into(), size) - + VecZnx::alloc_bytes(module.n(), 1, size) - + module.vec_znx_dft_alloc_bytes((infos.rank() + 1).into(), size) + GLWE::encrypt_sk_tmp_bytes(module, &infos.glwe_layout()) + + VecZnx::bytes_of(module.n(), (infos.rank() + 1).into(), size) + + VecZnx::bytes_of(module.n(), 1, size) + + module.bytes_of_vec_znx_dft((infos.rank() + 1).into(), size) } } -impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &ScalarZnx<DataPt>, - sk: &GLWESecretPrepared<DataSk, B>, +pub trait GGSWEncryptSk<B: Backend> { + fn ggsw_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GGSWToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GGSWEncryptSk<B> for Module<B> +where + Module<B>: GLWEEncryptSkInternal<B> + VecZnxAddScalarInplace + VecZnxNormalizeInplace<B>, + Scratch<B>:, +{ + fn ggsw_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GGSWToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef<B>, { + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let pt: &ScalarZnx<&[u8]> = &pt.to_ref(); + let sk: &GLWESecretPrepared<&[u8], B> = &sk.to_ref(); + #[cfg(debug_assertions)] { use poulpy_hal::layouts::ZnxInfos; - assert_eq!(self.rank(), sk.rank()); - assert_eq!(self.n(), sk.n()); - assert_eq!(pt.n() as u32, sk.n()); + assert_eq!(res.rank(), sk.rank()); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(pt.n(), self.n()); + assert_eq!(sk.n(), self.n() as u32); } - let base2k: usize = self.base2k().into(); - let rank: usize = self.rank().into(); - let dsize: usize = self.dsize().into(); + let k: usize = res.k().into(); + let base2k: usize = res.base2k().into(); + let rank: usize = res.rank().into(); + let dsize: usize = res.dsize().into(); + let cols: usize = (rank + 1).into(); - let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&self.glwe_layout()); + let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&res.glwe_layout()); - (0..self.dnum().into()).for_each(|row_i| { + for row_i in 0..res.dnum().into() { tmp_pt.data.zero(); - // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt - module.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0); - module.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1); - - (0..rank + 1).for_each(|col_j| { - // rlwe encrypt of vec_znx_pt into vec_znx_ct - - self.at_mut(row_i, col_j).encrypt_sk_internal( - module, + self.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0); + self.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1); + for col_j in 0..rank + 1 { + self.glwe_encrypt_sk_internal( + base2k, + k, + res.at_mut(row_i, col_j).data_mut(), + cols, + false, Some((&tmp_pt, col_j)), sk, source_xa, source_xe, + SIGMA, scratch_1, ); - }); - }); + } + } + } +} + +impl<DataSelf: DataMut> GGSW<DataSelf> { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + pt: &ScalarZnx<DataPt>, + sk: &GLWESecretPrepared<DataSk, B>, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + Module<B>: GGSWEncryptSk<B>, + { + module.ggsw_encrypt_sk(self, pt, sk, source_xa, source_xe, scratch); } }
M poulpy-core/src/encryption/glwe_ct.rs → poulpy-core/src/encryption/glwe_ct.rs

@@ -1,11 +1,11 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeSvpPPol, - TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxBigAddNormal, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, - VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, + ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, + VecZnxAddNormal, VecZnxBigAddNormal, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, + VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, }, - layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch, VecZnx, VecZnxBig, ZnxInfos, ZnxZero}, + layouts::{Backend, DataMut, Module, ScalarZnx, Scratch, VecZnx, VecZnxBig, VecZnxToMut, ZnxInfos, ZnxZero}, source::Source, };

@@ -13,157 +13,217 @@ use crate::{

dist::Distribution, encryption::{SIGMA, SIGMA_BOUND}, layouts::{ - GLWECiphertext, GLWEInfos, GLWEPlaintext, LWEInfos, - prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared}, + GLWE, GLWEInfos, GLWEPlaintext, GLWEPlaintextToRef, GLWEToMut, LWEInfos, + prepared::{GLWEPublicKeyPrepared, GLWEPublicKeyPreparedToRef, GLWESecretPrepared, GLWESecretPreparedToRef}, }, }; -impl GLWECiphertext<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GLWE<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GLWEInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { let size: usize = infos.size(); assert_eq!(module.n() as u32, infos.n()); - module.vec_znx_normalize_tmp_bytes() - + 2 * VecZnx::alloc_bytes(module.n(), 1, size) - + module.vec_znx_dft_alloc_bytes(1, size) + module.vec_znx_normalize_tmp_bytes() + 2 * VecZnx::bytes_of(module.n(), 1, size) + module.bytes_of_vec_znx_dft(1, size) } - pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize + pub fn encrypt_pk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GLWEInfos, - Module<B>: VecZnxDftAllocBytes + SvpPPolAllocBytes + VecZnxBigAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + SvpPPolBytesOf + VecZnxBigBytesOf + VecZnxNormalizeTmpBytes, { let size: usize = infos.size(); assert_eq!(module.n() as u32, infos.n()); - ((module.vec_znx_dft_alloc_bytes(1, size) + module.vec_znx_big_alloc_bytes(1, size)) - | ScalarZnx::alloc_bytes(module.n(), 1)) - + module.svp_ppol_alloc_bytes(1) + ((module.bytes_of_vec_znx_dft(1, size) + module.bytes_of_vec_znx_big(1, size)) | ScalarZnx::bytes_of(module.n(), 1)) + + module.bytes_of_svp_ppol(1) + module.vec_znx_normalize_tmp_bytes() } } -impl<DataSelf: DataMut> GLWECiphertext<DataSelf> { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>( +impl<D: DataMut> GLWE<D> { + pub fn encrypt_sk<R, P, S, B: Backend>( &mut self, module: &Module<B>, - pt: &GLWEPlaintext<DataPt>, - sk: &GLWESecretPrepared<DataSk, B>, + pt: &P, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>, + Module<B>: GLWEEncryptSk<B>, { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), sk.rank()); - assert_eq!(sk.n(), self.n()); - assert_eq!(pt.n(), self.n()); - assert!( - scratch.available() >= GLWECiphertext::encrypt_sk_scratch_space(module, self), - "scratch.available(): {} < GLWECiphertext::encrypt_sk_scratch_space: {}", - scratch.available(), - GLWECiphertext::encrypt_sk_scratch_space(module, self) - ) - } + module.glwe_encrypt_sk(self, pt, sk, source_xa, source_xe, scratch); + } - self.encrypt_sk_internal(module, Some((pt, 0)), sk, source_xa, source_xe, scratch); + pub fn encrypt_zero_sk<S, B: Backend>( + &mut self, + module: &Module<B>, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + S: GLWESecretPreparedToRef<B>, + Module<B>: GLWEEncryptZeroSk<B>, + { + module.glwe_encrypt_zero_sk(self, sk, source_xa, source_xe, scratch); } - pub fn encrypt_zero_sk<DataSk: DataRef, B: Backend>( + pub fn encrypt_pk<P, K, B: Backend>( + &mut self, + module: &Module<B>, + pt: &P, + pk: &K, + source_xu: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + P: GLWEPlaintextToRef, + K: GLWEPublicKeyPreparedToRef<B>, + Module<B>: GLWEEncryptPk<B>, + { + module.glwe_encrypt_pk(self, pt, pk, source_xu, source_xe, scratch); + } + + pub fn encrypt_zero_pk<K, B: Backend>( &mut self, module: &Module<B>, - sk: &GLWESecretPrepared<DataSk, B>, + pk: &K, + source_xu: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + K: GLWEPublicKeyPreparedToRef<B>, + Module<B>: GLWEEncryptZeroPk<B>, + { + module.glwe_encrypt_zero_pk(self, pk, source_xu, source_xe, scratch); + } +} + +pub trait GLWEEncryptSk<B: Backend> { + fn glwe_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GLWEToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GLWEEncryptSk<B> for Module<B> +where + Module<B>: GLWEEncryptSkInternal<B> + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, + Scratch<B>: ScratchAvailable, +{ + fn glwe_encrypt_sk<R, P, S>( + &self, + res: &mut R, + pt: &P, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWEToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>, { + let mut res: GLWE<&mut [u8]> = res.to_mut(); + let pt: GLWEPlaintext<&[u8]> = pt.to_ref(); + #[cfg(debug_assertions)] { - assert_eq!(self.rank(), sk.rank()); - assert_eq!(sk.n(), self.n()); + let sk: GLWESecretPrepared<&[u8], B> = sk.to_ref(); + assert_eq!(res.rank(), sk.rank()); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(sk.n(), self.n() as u32); + assert_eq!(pt.n(), self.n() as u32); assert!( - scratch.available() >= GLWECiphertext::encrypt_sk_scratch_space(module, self), - "scratch.available(): {} < GLWECiphertext::encrypt_sk_scratch_space: {}", + scratch.available() >= GLWE::encrypt_sk_tmp_bytes(self, &res), + "scratch.available(): {} < GLWECiphertext::encrypt_sk_tmp_bytes: {}", scratch.available(), - GLWECiphertext::encrypt_sk_scratch_space(module, self) + GLWE::encrypt_sk_tmp_bytes(self, &res) ) } - self.encrypt_sk_internal( - module, - None::<(&GLWEPlaintext<Vec<u8>>, usize)>, + + let cols: usize = (res.rank() + 1).into(); + self.glwe_encrypt_sk_internal( + res.base2k().into(), + res.k().into(), + res.data_mut(), + cols, + false, + Some((&pt, 0)), sk, source_xa, source_xe, + SIGMA, scratch, ); } +} - #[allow(clippy::too_many_arguments)] - pub(crate) fn encrypt_sk_internal<DataPt: DataRef, DataSk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretPrepared<DataSk, B>, +pub trait GLWEEncryptZeroSk<B: Backend> { + fn glwe_encrypt_zero_sk<R, S>( + &self, + res: &mut R, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWEToMut, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GLWEEncryptZeroSk<B> for Module<B> +where + Module<B>: GLWEEncryptSkInternal<B> + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, + Scratch<B>: ScratchAvailable, +{ + fn glwe_encrypt_zero_sk<R, S>( + &self, + res: &mut R, + sk: &S, source_xa: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + R: GLWEToMut, + S: GLWESecretPreparedToRef<B>, { - let cols: usize = (self.rank() + 1).into(); - glwe_encrypt_sk_internal( - module, - self.base2k().into(), - self.k().into(), - &mut self.data, + let mut res: GLWE<&mut [u8]> = res.to_mut(); + + #[cfg(debug_assertions)] + { + let sk: GLWESecretPrepared<&[u8], B> = sk.to_ref(); + assert_eq!(res.rank(), sk.rank()); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(sk.n(), self.n() as u32); + assert!( + scratch.available() >= GLWE::encrypt_sk_tmp_bytes(self, &res), + "scratch.available(): {} < GLWECiphertext::encrypt_sk_tmp_bytes: {}", + scratch.available(), + GLWE::encrypt_sk_tmp_bytes(self, &res) + ) + } + + let cols: usize = (res.rank() + 1).into(); + self.glwe_encrypt_sk_internal( + res.base2k().into(), + res.k().into(), + res.data_mut(), cols, false, - pt, + None::<(&GLWEPlaintext<Vec<u8>>, usize)>, sk, source_xa, source_xe,

@@ -171,46 +231,74 @@ SIGMA,

scratch, ); } +} - #[allow(clippy::too_many_arguments)] - pub fn encrypt_pk<DataPt: DataRef, DataPk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: &GLWEPlaintext<DataPt>, - pk: &GLWEPublicKeyPrepared<DataPk, B>, +pub trait GLWEEncryptPk<B: Backend> { + fn glwe_encrypt_pk<R, P, K>( + &self, + res: &mut R, + pt: &P, + pk: &K, source_xu: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: SvpPrepare<B> - + SvpApplyDftToDft<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddNormal<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B>, - Scratch<B>: TakeSvpPPol<B> + TakeScalarZnx + TakeVecZnxDft<B>, + R: GLWEToMut, + P: GLWEPlaintextToRef, + K: GLWEPublicKeyPreparedToRef<B>; +} + +impl<B: Backend> GLWEEncryptPk<B> for Module<B> +where + Module<B>: GLWEEncryptPkInternal<B>, +{ + fn glwe_encrypt_pk<R, P, K>( + &self, + res: &mut R, + pt: &P, + pk: &K, + source_xu: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWEToMut, + P: GLWEPlaintextToRef, + K: GLWEPublicKeyPreparedToRef<B>, { - self.encrypt_pk_internal::<DataPt, DataPk, B>(module, Some((pt, 0)), pk, source_xu, source_xe, scratch); + self.glwe_encrypt_pk_internal(res, Some((pt, 0)), pk, source_xu, source_xe, scratch); } +} - pub fn encrypt_zero_pk<DataPk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pk: &GLWEPublicKeyPrepared<DataPk, B>, +pub trait GLWEEncryptZeroPk<B: Backend> { + fn glwe_encrypt_zero_pk<R, K>( + &self, + res: &mut R, + pk: &K, source_xu: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: SvpPrepare<B> - + SvpApplyDftToDft<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddNormal<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B>, - Scratch<B>: TakeSvpPPol<B> + TakeScalarZnx + TakeVecZnxDft<B>, + R: GLWEToMut, + K: GLWEPublicKeyPreparedToRef<B>; +} + +impl<B: Backend> GLWEEncryptZeroPk<B> for Module<B> +where + Module<B>: GLWEEncryptPkInternal<B>, +{ + fn glwe_encrypt_zero_pk<R, K>( + &self, + res: &mut R, + pk: &K, + source_xu: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWEToMut, + K: GLWEPublicKeyPreparedToRef<B>, { - self.encrypt_pk_internal::<Vec<u8>, DataPk, B>( - module, + self.glwe_encrypt_pk_internal( + res, None::<(&GLWEPlaintext<Vec<u8>>, usize)>, pk, source_xu,

@@ -218,45 +306,69 @@ source_xe,

scratch, ); } +} - #[allow(clippy::too_many_arguments)] - pub(crate) fn encrypt_pk_internal<DataPt: DataRef, DataPk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - pk: &GLWEPublicKeyPrepared<DataPk, B>, +pub(crate) trait GLWEEncryptPkInternal<B: Backend> { + fn glwe_encrypt_pk_internal<R, P, K>( + &self, + res: &mut R, + pt: Option<(&P, usize)>, + pk: &K, + source_xu: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch<B>, + ) where + R: GLWEToMut, + P: GLWEPlaintextToRef, + K: GLWEPublicKeyPreparedToRef<B>; +} + +impl<B: Backend> GLWEEncryptPkInternal<B> for Module<B> +where + Module<B>: SvpPrepare<B> + + SvpApplyDftToDft<B> + + VecZnxIdftApplyConsume<B> + + VecZnxBigAddNormal<B> + + VecZnxBigAddSmallInplace<B> + + VecZnxBigNormalize<B>, + Scratch<B>:, +{ + fn glwe_encrypt_pk_internal<R, P, K>( + &self, + res: &mut R, + pt: Option<(&P, usize)>, + pk: &K, source_xu: &mut Source, source_xe: &mut Source, scratch: &mut Scratch<B>, ) where - Module<B>: SvpPrepare<B> - + SvpApplyDftToDft<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddNormal<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B>, - Scratch<B>: TakeSvpPPol<B> + TakeScalarZnx + TakeVecZnxDft<B>, + R: GLWEToMut, + P: GLWEPlaintextToRef, + K: GLWEPublicKeyPreparedToRef<B>, { + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let pk: &GLWEPublicKeyPrepared<&[u8], B> = &pk.to_ref(); + #[cfg(debug_assertions)] { - assert_eq!(self.base2k(), pk.base2k()); - assert_eq!(self.n(), pk.n()); - assert_eq!(self.rank(), pk.rank()); + assert_eq!(res.base2k(), pk.base2k()); + assert_eq!(res.n(), pk.n()); + assert_eq!(res.rank(), pk.rank()); if let Some((pt, _)) = pt { - assert_eq!(pt.base2k(), pk.base2k()); - assert_eq!(pt.n(), pk.n()); + assert_eq!(pt.to_ref().base2k(), pk.base2k()); + assert_eq!(pt.to_ref().n(), pk.n()); } } let base2k: usize = pk.base2k().into(); let size_pk: usize = pk.size(); - let cols: usize = (self.rank() + 1).into(); + let cols: usize = (res.rank() + 1).into(); // Generates u according to the underlying secret distribution. - let (mut u_dft, scratch_1) = scratch.take_svp_ppol(self.n().into(), 1); + let (mut u_dft, scratch_1) = scratch.take_svp_ppol(res.n().into(), 1); { - let (mut u, _) = scratch_1.take_scalar_znx(self.n().into(), 1); + let (mut u, _) = scratch_1.take_scalar_znx(res.n().into(), 1); match pk.dist { Distribution::NONE => panic!( "invalid public key: SecretDistribution::NONE, ensure it has been correctly intialized through \

@@ -270,20 +382,20 @@ Distribution::BinaryBlock(block_size) => u.fill_binary_block(0, block_size, source_xu),

Distribution::ZERO => {} } - module.svp_prepare(&mut u_dft, 0, &u, 0); + self.svp_prepare(&mut u_dft, 0, &u, 0); } // ct[i] = pk[i] * u + ei (+ m if col = i) (0..cols).for_each(|i| { - let (mut ci_dft, scratch_2) = scratch_1.take_vec_znx_dft(self.n().into(), 1, size_pk); + let (mut ci_dft, scratch_2) = scratch_1.take_vec_znx_dft(res.n().into(), 1, size_pk); // ci_dft = DFT(u) * DFT(pk[i]) - module.svp_apply_dft_to_dft(&mut ci_dft, 0, &u_dft, 0, &pk.data, i); + self.svp_apply_dft_to_dft(&mut ci_dft, 0, &u_dft, 0, &pk.data, i); // ci_big = u * p[i] - let mut ci_big = module.vec_znx_idft_apply_consume(ci_dft); + let mut ci_big = self.vec_znx_idft_apply_consume(ci_dft); // ci_big = u * pk[i] + e - module.vec_znx_big_add_normal( + self.vec_znx_big_add_normal( base2k, &mut ci_big, 0,

@@ -297,31 +409,38 @@ // ci_big = u * pk[i] + e + m (if col = i)

if let Some((pt, col)) = pt && col == i { - module.vec_znx_big_add_small_inplace(&mut ci_big, 0, &pt.data, 0); + self.vec_znx_big_add_small_inplace(&mut ci_big, 0, &pt.to_ref().data, 0); } // ct[i] = norm(ci_big) - module.vec_znx_big_normalize(base2k, &mut self.data, i, base2k, &ci_big, 0, scratch_2); + self.vec_znx_big_normalize(base2k, &mut res.data, i, base2k, &ci_big, 0, scratch_2); }); } } -#[allow(clippy::too_many_arguments)] -pub(crate) fn glwe_encrypt_sk_internal<DataCt: DataMut, DataPt: DataRef, DataSk: DataRef, B: Backend>( - module: &Module<B>, - base2k: usize, - k: usize, - ct: &mut VecZnx<DataCt>, - cols: usize, - compressed: bool, - pt: Option<(&GLWEPlaintext<DataPt>, usize)>, - sk: &GLWESecretPrepared<DataSk, B>, - source_xa: &mut Source, - source_xe: &mut Source, - sigma: f64, - scratch: &mut Scratch<B>, -) where - Module<B>: VecZnxDftAllocBytes +pub(crate) trait GLWEEncryptSkInternal<B: Backend> { + fn glwe_encrypt_sk_internal<R, P, S>( + &self, + base2k: usize, + k: usize, + res: &mut R, + cols: usize, + compressed: bool, + pt: Option<(&P, usize)>, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + R: VecZnxToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GLWEEncryptSkInternal<B> for Module<B> +where + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -334,74 +453,96 @@ + VecZnxNormalizeInplace<B>

+ VecZnxAddNormal + VecZnxNormalize<B> + VecZnxSub, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { - #[cfg(debug_assertions)] + fn glwe_encrypt_sk_internal<R, P, S>( + &self, + base2k: usize, + k: usize, + res: &mut R, + cols: usize, + compressed: bool, + pt: Option<(&P, usize)>, + sk: &S, + source_xa: &mut Source, + source_xe: &mut Source, + sigma: f64, + scratch: &mut Scratch<B>, + ) where + R: VecZnxToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef<B>, { - if compressed { - assert_eq!( - ct.cols(), - 1, - "invalid ciphertext: compressed tag=true but #cols={} != 1", - ct.cols() - ) + let ct: &mut VecZnx<&mut [u8]> = &mut res.to_mut(); + let sk: GLWESecretPrepared<&[u8], B> = sk.to_ref(); + + #[cfg(debug_assertions)] + { + if compressed { + assert_eq!( + ct.cols(), + 1, + "invalid ciphertext: compressed tag=true but #cols={} != 1", + ct.cols() + ) + } } - } - let size: usize = ct.size(); + let size: usize = ct.size(); - let (mut c0, scratch_1) = scratch.take_vec_znx(ct.n(), 1, size); - c0.zero(); + let (mut c0, scratch_1) = scratch.take_vec_znx(ct.n(), 1, size); + c0.zero(); - { - let (mut ci, scratch_2) = scratch_1.take_vec_znx(ct.n(), 1, size); + { + let (mut ci, scratch_2) = scratch_1.take_vec_znx(ct.n(), 1, size); - // ct[i] = uniform - // ct[0] -= c[i] * s[i], - (1..cols).for_each(|i| { - let col_ct: usize = if compressed { 0 } else { i }; + // ct[i] = uniform + // ct[0] -= c[i] * s[i], + (1..cols).for_each(|i| { + let col_ct: usize = if compressed { 0 } else { i }; - // ct[i] = uniform (+ pt) - module.vec_znx_fill_uniform(base2k, ct, col_ct, source_xa); + // ct[i] = uniform (+ pt) + self.vec_znx_fill_uniform(base2k, ct, col_ct, source_xa); - let (mut ci_dft, scratch_3) = scratch_2.take_vec_znx_dft(ct.n(), 1, size); + let (mut ci_dft, scratch_3) = scratch_2.take_vec_znx_dft(ct.n(), 1, size); - // ci = ct[i] - pt - // i.e. we act as we sample ct[i] already as uniform + pt - // and if there is a pt, then we subtract it before applying DFT - if let Some((pt, col)) = pt { - if i == col { - module.vec_znx_sub(&mut ci, 0, ct, col_ct, &pt.data, 0); - module.vec_znx_normalize_inplace(base2k, &mut ci, 0, scratch_3); - module.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, &ci, 0); + // ci = ct[i] - pt + // i.e. we act as we sample ct[i] already as uniform + pt + // and if there is a pt, then we subtract it before applying DFT + if let Some((pt, col)) = pt { + if i == col { + self.vec_znx_sub(&mut ci, 0, ct, col_ct, &pt.to_ref().data, 0); + self.vec_znx_normalize_inplace(base2k, &mut ci, 0, scratch_3); + self.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, &ci, 0); + } else { + self.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, ct, col_ct); + } } else { - module.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, ct, col_ct); + self.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, ct, col_ct); } - } else { - module.vec_znx_dft_apply(1, 0, &mut ci_dft, 0, ct, col_ct); - } + + self.svp_apply_dft_to_dft_inplace(&mut ci_dft, 0, &sk.data, i - 1); + let ci_big: VecZnxBig<&mut [u8], B> = self.vec_znx_idft_apply_consume(ci_dft); - module.svp_apply_dft_to_dft_inplace(&mut ci_dft, 0, &sk.data, i - 1); - let ci_big: VecZnxBig<&mut [u8], B> = module.vec_znx_idft_apply_consume(ci_dft); + // use c[0] as buffer, which is overwritten later by the normalization step + self.vec_znx_big_normalize(base2k, &mut ci, 0, base2k, &ci_big, 0, scratch_3); - // use c[0] as buffer, which is overwritten later by the normalization step - module.vec_znx_big_normalize(base2k, &mut ci, 0, base2k, &ci_big, 0, scratch_3); + // c0_tmp = -c[i] * s[i] (use c[0] as buffer) + self.vec_znx_sub_inplace(&mut c0, 0, &ci, 0); + }); + } - // c0_tmp = -c[i] * s[i] (use c[0] as buffer) - module.vec_znx_sub_inplace(&mut c0, 0, &ci, 0); - }); - } + // c[0] += e + self.vec_znx_add_normal(base2k, &mut c0, 0, k, source_xe, sigma, SIGMA_BOUND); - // c[0] += e - module.vec_znx_add_normal(base2k, &mut c0, 0, k, source_xe, sigma, SIGMA_BOUND); + // c[0] += m if col = 0 + if let Some((pt, col)) = pt + && col == 0 + { + self.vec_znx_add_inplace(&mut c0, 0, &pt.to_ref().data, 0); + } - // c[0] += m if col = 0 - if let Some((pt, col)) = pt - && col == 0 - { - module.vec_znx_add_inplace(&mut c0, 0, &pt.data, 0); + // c[0] = norm(c[0]) + self.vec_znx_normalize(base2k, ct, 0, base2k, &c0, 0, scratch_1); } - - // c[0] = norm(c[0]) - module.vec_znx_normalize(base2k, ct, 0, base2k, &c0, 0, scratch_1); }
M poulpy-core/src/encryption/glwe_pk.rs → poulpy-core/src/encryption/glwe_pk.rs

@@ -1,50 +1,43 @@

use poulpy_hal::{ - api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxAddInplace, VecZnxAddNormal, VecZnxBigNormalize, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, - }, + api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxDftBytesOf, VecZnxNormalizeTmpBytes}, layouts::{Backend, DataMut, DataRef, Module, ScratchOwned}, - oep::{ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxDftImpl, TakeVecZnxImpl}, source::Source, }; -use crate::layouts::{GLWECiphertext, GLWEPublicKey, prepared::GLWESecretPrepared}; +use crate::{ + encryption::glwe_ct::GLWEEncryptZeroSk, + layouts::{ + GLWE, GLWEPublicKey, GLWEPublicKeyToMut, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, + }, +}; -impl<D: DataMut> GLWEPublicKey<D> { - pub fn generate_from_sk<S: DataRef, B>( - &mut self, - module: &Module<B>, - sk: &GLWESecretPrepared<S, B>, - source_xa: &mut Source, - source_xe: &mut Source, - ) where - Module<B>:, - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub, - B: Backend - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + TakeVecZnxDftImpl<B> - + ScratchAvailableImpl<B> - + TakeVecZnxImpl<B>, +pub trait GLWEPublicKeyGenerate<B: Backend> { + fn glwe_public_key_generate<R, S>(&self, res: &mut R, sk: &S, source_xa: &mut Source, source_xe: &mut Source) + where + R: GLWEPublicKeyToMut, + S: GLWESecretPreparedToRef<B>; +} + +impl<B: Backend> GLWEPublicKeyGenerate<B> for Module<B> +where + Module<B>: GLWEEncryptZeroSk<B> + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, + ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>, +{ + fn glwe_public_key_generate<R, S>(&self, res: &mut R, sk: &S, source_xa: &mut Source, source_xe: &mut Source) + where + R: GLWEPublicKeyToMut, + S: GLWESecretPreparedToRef<B>, { + let res: &mut GLWEPublicKey<&mut [u8]> = &mut res.to_mut(); + let sk: &GLWESecretPrepared<&[u8], B> = &sk.to_ref(); + #[cfg(debug_assertions)] { use crate::{Distribution, layouts::LWEInfos}; - assert_eq!(self.n(), sk.n()); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(sk.n(), self.n() as u32); if sk.dist == Distribution::NONE { panic!("invalid sk: SecretDistribution::NONE")

@@ -52,10 +45,25 @@ }

} // Its ok to allocate scratch space here since pk is usually generated only once. - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::encrypt_sk_scratch_space(module, self)); + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWE::encrypt_sk_tmp_bytes(self, res)); - let mut tmp: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(self); - tmp.encrypt_zero_sk(module, sk, source_xa, source_xe, scratch.borrow()); - self.dist = sk.dist; + let mut tmp: GLWE<Vec<u8>> = GLWE::alloc_from_infos(res); + + tmp.encrypt_zero_sk(self, sk, source_xa, source_xe, scratch.borrow()); + res.dist = sk.dist; + } +} + +impl<D: DataMut> GLWEPublicKey<D> { + pub fn generate<S: DataRef, B: Backend>( + &mut self, + module: &Module<B>, + sk: &GLWESecretPrepared<S, B>, + source_xa: &mut Source, + source_xe: &mut Source, + ) where + Module<B>: GLWEPublicKeyGenerate<B>, + { + module.glwe_public_key_generate(self, sk, source_xa, source_xe); } }
M poulpy-core/src/encryption/glwe_to_lwe_ksk.rs → poulpy-core/src/encryption/glwe_to_lwe_ksk.rs

@@ -1,32 +1,30 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigNormalize, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, + ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, + VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, + VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, + VecZnxSubInplace, VecZnxSwitchRing, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero}, source::Source, }; -use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, - layouts::{GGLWEInfos, GGLWESwitchingKey, GLWESecret, GLWEToLWEKey, LWEInfos, LWESecret, Rank, prepared::GLWESecretPrepared}, +use crate::layouts::{ + GGLWEInfos, GLWESecret, GLWESwitchingKey, GLWEToLWESwitchingKey, LWEInfos, LWESecret, Rank, prepared::GLWESecretPrepared, }; -impl GLWEToLWEKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize +impl GLWEToLWESwitchingKey<Vec<u8>> { + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { - GLWESecretPrepared::alloc_bytes_with(module, infos.rank_in()) - + (GGLWESwitchingKey::encrypt_sk_scratch_space(module, infos) - | GLWESecret::alloc_bytes_with(infos.n(), infos.rank_in())) + GLWESecretPrepared::bytes_of(module, infos.rank_in()) + + (GLWESwitchingKey::encrypt_sk_tmp_bytes(module, infos) | GLWESecret::bytes_of(infos.n(), infos.rank_in())) } } -impl<D: DataMut> GLWEToLWEKey<D> { +impl<D: DataMut> GLWEToLWESwitchingKey<D> { #[allow(clippy::too_many_arguments)] pub fn encrypt_sk<DLwe, DGlwe, B: Backend>( &mut self,

@@ -41,7 +39,7 @@ DLwe: DataRef,

DGlwe: DataRef, Module<B>: VecZnxAutomorphismInplace<B> + VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -56,8 +54,8 @@ + VecZnxNormalize<B>

+ VecZnxSub + SvpPrepare<B> + VecZnxSwitchRing - + SvpPPolAllocBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + + SvpPPolBytesOf, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {
M poulpy-core/src/encryption/lwe_ct.rs → poulpy-core/src/encryption/lwe_ct.rs

@@ -7,10 +7,10 @@ };

use crate::{ encryption::{SIGMA, SIGMA_BOUND}, - layouts::{LWECiphertext, LWEInfos, LWEPlaintext, LWESecret}, + layouts::{LWE, LWEInfos, LWEPlaintext, LWESecret}, }; -impl<DataSelf: DataMut> LWECiphertext<DataSelf> { +impl<DataSelf: DataMut> LWE<DataSelf> { pub fn encrypt_sk<DataPt, DataSk, B>( &mut self, module: &Module<B>,
M poulpy-core/src/encryption/lwe_ksk.rs → poulpy-core/src/encryption/lwe_ksk.rs

@@ -1,27 +1,24 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigNormalize, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, + SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, + VecZnxAutomorphismInplace, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, + VecZnxSwitchRing, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut}, source::Source, }; -use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, - layouts::{ - Degree, GGLWEInfos, GGLWESwitchingKey, GLWESecret, LWEInfos, LWESecret, LWESwitchingKey, Rank, - prepared::GLWESecretPrepared, - }, +use crate::layouts::{ + GGLWEInfos, GLWESecret, GLWESwitchingKey, LWEInfos, LWESecret, LWESwitchingKey, Rank, RingDegree, + prepared::GLWESecretPrepared, }; impl LWESwitchingKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { debug_assert_eq!( infos.dsize().0,

@@ -38,9 +35,9 @@ infos.rank_out().0,

1, "rank_out > 1 is not supported for LWESwitchingKey" ); - GLWESecret::alloc_bytes_with(Degree(module.n() as u32), Rank(1)) - + GLWESecretPrepared::alloc_bytes_with(module, Rank(1)) - + GGLWESwitchingKey::encrypt_sk_scratch_space(module, infos) + GLWESecret::bytes_of(RingDegree(module.n() as u32), Rank(1)) + + GLWESecretPrepared::bytes_of(module, Rank(1)) + + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, infos) } }

@@ -59,7 +56,7 @@ DIn: DataRef,

DOut: DataRef, Module<B>: VecZnxAutomorphismInplace<B> + VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -74,8 +71,8 @@ + VecZnxNormalize<B>

+ VecZnxSub + SvpPrepare<B> + VecZnxSwitchRing - + SvpPPolAllocBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + + SvpPPolBytesOf, + Scratch<B>:, { #[cfg(debug_assertions)] {
M poulpy-core/src/encryption/lwe_to_glwe_ksk.rs → poulpy-core/src/encryption/lwe_to_glwe_ksk.rs

@@ -1,32 +1,29 @@

use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, - VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigNormalize, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, + ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, + VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, + VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, + VecZnxSubInplace, VecZnxSwitchRing, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut}, source::Source, }; -use crate::{ - TakeGLWESecret, TakeGLWESecretPrepared, - layouts::{Degree, GGLWEInfos, GGLWESwitchingKey, GLWESecret, LWEInfos, LWESecret, LWEToGLWESwitchingKey, Rank}, -}; +use crate::layouts::{GGLWEInfos, GLWESecret, GLWESwitchingKey, LWEInfos, LWESecret, LWEToGLWESwitchingKey, Rank, RingDegree}; impl LWEToGLWESwitchingKey<Vec<u8>> { - pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize + pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes, + Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes, { debug_assert_eq!( infos.rank_in(), Rank(1), "rank_in != 1 is not supported for LWEToGLWESwitchingKey" ); - GGLWESwitchingKey::encrypt_sk_scratch_space(module, infos) - + GLWESecret::alloc_bytes_with(Degree(module.n() as u32), infos.rank_in()) + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, infos) + + GLWESecret::bytes_of(RingDegree(module.n() as u32), infos.rank_in()) } }

@@ -45,7 +42,7 @@ DLwe: DataRef,

DGlwe: DataRef, Module<B>: VecZnxAutomorphismInplace<B> + VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -60,8 +57,8 @@ + VecZnxNormalize<B>

+ VecZnxSub + SvpPrepare<B> + VecZnxSwitchRing - + SvpPPolAllocBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>, + + SvpPPolBytesOf, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {
M poulpy-core/src/encryption/mod.rs → poulpy-core/src/encryption/mod.rs

@@ -11,7 +11,5 @@ mod lwe_ct;

mod lwe_ksk; mod lwe_to_glwe_ksk; -pub(crate) use glwe_ct::glwe_encrypt_sk_internal; - pub const SIGMA: f64 = 3.2; pub(crate) const SIGMA_BOUND: f64 = 6.0 * SIGMA;
M poulpy-core/src/external_product/gglwe_atk.rs → poulpy-core/src/external_product/gglwe_atk.rs

@@ -1,83 +1,46 @@

-use poulpy_hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, - }, - layouts::{Backend, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, DataMut, Scratch}; -use crate::layouts::{GGLWEAutomorphismKey, GGLWEInfos, GGLWESwitchingKey, GGSWInfos, prepared::GGSWCiphertextPrepared}; +use crate::{ + ScratchTakeCore, + external_product::gglwe_ksk::GGLWEExternalProduct, + layouts::{AutomorphismKey, AutomorphismKeyToRef, GGLWEInfos, GGSWInfos, prepared::GGSWPreparedToRef}, +}; -impl GGLWEAutomorphismKey<Vec<u8>> { - pub fn external_product_scratch_space<B: Backend, OUT, IN, GGSW>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - ggsw_infos: &GGSW, +impl AutomorphismKey<Vec<u8>> { + pub fn external_product_tmp_bytes<R, A, B, M, BE: Backend>( + &self, + module: &M, + res_infos: &R, + a_infos: &A, + b_infos: &B, ) -> usize where - OUT: GGLWEInfos, - IN: GGLWEInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + R: GGLWEInfos, + A: GGLWEInfos, + B: GGSWInfos, + M: GGLWEExternalProduct<BE>, { - GGLWESwitchingKey::external_product_scratch_space(module, out_infos, in_infos, ggsw_infos) + module.gglwe_external_product_tmp_bytes(res_infos, a_infos, b_infos) } +} - pub fn external_product_inplace_scratch_space<B: Backend, OUT, GGSW>( - module: &Module<B>, - out_infos: &OUT, - ggsw_infos: &GGSW, - ) -> usize +impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { + pub fn external_product<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) where - OUT: GGLWEInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, - { - GGLWESwitchingKey::external_product_inplace_scratch_space(module, out_infos, ggsw_infos) - } -} - -impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { - pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GGLWEAutomorphismKey<DataLhs>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + M: GGLWEExternalProduct<BE>, + A: AutomorphismKeyToRef, + B: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - self.key.external_product(module, &lhs.key, rhs, scratch); + module.gglwe_external_product(&mut self.key.key, &a.to_ref().key.key, b, scratch); } - pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + pub fn external_product_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) + where + M: GGLWEExternalProduct<BE>, + A: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - self.key.external_product_inplace(module, rhs, scratch); + module.gglwe_external_product_inplace(&mut self.key.key, a, scratch); } }
M poulpy-core/src/external_product/gglwe_ksk.rs → poulpy-core/src/external_product/gglwe_ksk.rs

@@ -1,144 +1,134 @@

-use poulpy_hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, +use poulpy_hal::layouts::{Backend, DataMut, Module, Scratch, ZnxZero}; + +use crate::{ + GLWEExternalProduct, ScratchTakeCore, + layouts::{ + GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GGSWInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyToRef, + prepared::{GGSWPrepared, GGSWPreparedToRef}, }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero}, }; -use crate::layouts::{GGLWEInfos, GGLWESwitchingKey, GGSWInfos, GLWECiphertext, prepared::GGSWCiphertextPrepared}; - -impl GGLWESwitchingKey<Vec<u8>> { - pub fn external_product_scratch_space<B: Backend, OUT, IN, GGSW>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - ggsw_infos: &GGSW, - ) -> usize +pub trait GGLWEExternalProduct<BE: Backend> +where + Self: GLWEExternalProduct<BE>, +{ + fn gglwe_external_product_tmp_bytes<R, A, B>(&self, res_infos: &R, a_infos: &A, b_infos: &B) -> usize where - OUT: GGLWEInfos, - IN: GGLWEInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + R: GGLWEInfos, + A: GGLWEInfos, + B: GGSWInfos, { - GLWECiphertext::external_product_scratch_space( - module, - &out_infos.glwe_layout(), - &in_infos.glwe_layout(), - ggsw_infos, - ) + self.glwe_external_product_tmp_bytes(res_infos, a_infos, b_infos) } - pub fn external_product_inplace_scratch_space<B: Backend, OUT, GGSW>( - module: &Module<B>, - out_infos: &OUT, - ggsw_infos: &GGSW, - ) -> usize + fn gglwe_external_product<R, A, B>(&self, res: &mut R, a: &A, b: &B, scratch: &mut Scratch<BE>) where - OUT: GGLWEInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + R: GGLWEToMut, + A: GGLWEToRef, + B: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - GLWECiphertext::external_product_inplace_scratch_space(module, &out_infos.glwe_layout(), ggsw_infos) + let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GGLWE<&[u8]> = &a.to_ref(); + let b: &GGSWPrepared<&[u8], BE> = &b.to_ref(); + + assert_eq!( + res.rank_in(), + a.rank_in(), + "res input rank_in: {} != a input rank_in: {}", + res.rank_in(), + a.rank_in() + ); + assert_eq!( + a.rank_out(), + b.rank(), + "a output rank_out: {} != b rank: {}", + a.rank_out(), + b.rank() + ); + assert_eq!( + res.rank_out(), + b.rank(), + "res output rank_out: {} != b rank: {}", + res.rank_out(), + b.rank() + ); + + for row in 0..res.dnum().into() { + for col in 0..res.rank_in().into() { + self.glwe_external_product(&mut res.at_mut(row, col), &a.at(row, col), b, scratch); + } + } + + for row in res.dnum().min(a.dnum()).into()..res.dnum().into() { + for col in 0..res.rank_in().into() { + res.at_mut(row, col).data_mut().zero(); + } + } } -} -impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> { - pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GGLWESwitchingKey<DataLhs>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + fn gglwe_external_product_inplace<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<BE>) + where + R: GGLWEToMut, + A: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - use crate::layouts::GLWEInfos; + let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GGSWPrepared<&[u8], BE> = &a.to_ref(); - assert_eq!( - self.rank_in(), - lhs.rank_in(), - "ksk_out input rank: {} != ksk_in input rank: {}", - self.rank_in(), - lhs.rank_in() - ); - assert_eq!( - lhs.rank_out(), - rhs.rank(), - "ksk_in output rank: {} != ggsw rank: {}", - self.rank_out(), - rhs.rank() - ); - assert_eq!( - self.rank_out(), - rhs.rank(), - "ksk_out output rank: {} != ggsw rank: {}", - self.rank_out(), - rhs.rank() - ); + assert_eq!( + res.rank_out(), + a.rank(), + "res output rank: {} != a rank: {}", + res.rank_out(), + a.rank() + ); + + for row in 0..res.dnum().into() { + for col in 0..res.rank_in().into() { + self.glwe_external_product_inplace(&mut res.at_mut(row, col), a, scratch); + } } + } +} - (0..self.rank_in().into()).for_each(|col_i| { - (0..self.dnum().into()).for_each(|row_j| { - self.at_mut(row_j, col_i) - .external_product(module, &lhs.at(row_j, col_i), rhs, scratch); - }); - }); +impl<BE: Backend> GGLWEExternalProduct<BE> for Module<BE> where Self: GLWEExternalProduct<BE> {} - (self.dnum().min(lhs.dnum()).into()..self.dnum().into()).for_each(|row_i| { - (0..self.rank_in().into()).for_each(|col_j| { - self.at_mut(row_i, col_j).data.zero(); - }); - }); +impl GLWESwitchingKey<Vec<u8>> { + pub fn external_product_tmp_bytes<R, A, B, M, BE: Backend>( + &self, + module: &M, + res_infos: &R, + a_infos: &A, + b_infos: &B, + ) -> usize + where + R: GGLWEInfos, + A: GGLWEInfos, + B: GGSWInfos, + M: GGLWEExternalProduct<BE>, + { + module.gglwe_external_product_tmp_bytes(res_infos, a_infos, b_infos) } +} - pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, +impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { + pub fn external_product<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) + where + M: GGLWEExternalProduct<BE>, + A: GLWESwitchingKeyToRef, + B: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - use crate::layouts::GLWEInfos; + module.gglwe_external_product(&mut self.key, &a.to_ref().key, b, scratch); + } - assert_eq!( - self.rank_out(), - rhs.rank(), - "ksk_out output rank: {} != ggsw rank: {}", - self.rank_out(), - rhs.rank() - ); - } - - (0..self.rank_in().into()).for_each(|col_i| { - (0..self.dnum().into()).for_each(|row_j| { - self.at_mut(row_j, col_i) - .external_product_inplace(module, rhs, scratch); - }); - }); + pub fn external_product_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) + where + M: GGLWEExternalProduct<BE>, + A: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.gglwe_external_product_inplace(&mut self.key, a, scratch); } }
M poulpy-core/src/external_product/ggsw_ct.rs → poulpy-core/src/external_product/ggsw_ct.rs

@@ -1,143 +1,136 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, + api::ScratchAvailable, + layouts::{Backend, DataMut, Module, Scratch, ZnxZero}, +}; + +use crate::{ + GLWEExternalProduct, ScratchTakeCore, + layouts::{ + GGSW, GGSWInfos, GGSWToMut, GGSWToRef, GLWEInfos, LWEInfos, + prepared::{GGSWPrepared, GGSWPreparedToRef}, }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero}, }; -use crate::layouts::{GGSWCiphertext, GGSWInfos, GLWECiphertext, GLWEInfos, prepared::GGSWCiphertextPrepared}; - -impl GGSWCiphertext<Vec<u8>> { - #[allow(clippy::too_many_arguments)] - pub fn external_product_scratch_space<B: Backend, OUT, IN, GGSW>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - apply_infos: &GGSW, - ) -> usize +pub trait GGSWExternalProduct<BE: Backend> +where + Self: GLWEExternalProduct<BE>, +{ + fn ggsw_external_product_tmp_bytes<R, A, B>(&self, res_infos: &R, a_infos: &A, b_infos: &B) -> usize where - OUT: GGSWInfos, - IN: GGSWInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + R: GGSWInfos, + A: GGSWInfos, + B: GGSWInfos, { - GLWECiphertext::external_product_scratch_space( - module, - &out_infos.glwe_layout(), - &in_infos.glwe_layout(), - apply_infos, - ) + self.glwe_external_product_tmp_bytes(res_infos, a_infos, b_infos) } - pub fn external_product_inplace_scratch_space<B: Backend, OUT, GGSW>( - module: &Module<B>, - out_infos: &OUT, - apply_infos: &GGSW, - ) -> usize + fn ggsw_external_product<R, A, B>(&self, res: &mut R, a: &A, b: &B, scratch: &mut Scratch<BE>) where - OUT: GGSWInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + R: GGSWToMut, + A: GGSWToRef, + B: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - GLWECiphertext::external_product_inplace_scratch_space(module, &out_infos.glwe_layout(), apply_infos) + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let a: &GGSW<&[u8]> = &a.to_ref(); + let b: &GGSWPrepared<&[u8], BE> = &b.to_ref(); + + assert_eq!( + res.rank(), + a.rank(), + "res rank: {} != a rank: {}", + res.rank(), + a.rank() + ); + assert_eq!( + res.rank(), + b.rank(), + "res rank: {} != b rank: {}", + res.rank(), + b.rank() + ); + + assert!(scratch.available() >= self.ggsw_external_product_tmp_bytes(res, a, b)); + + let min_dnum: usize = res.dnum().min(a.dnum()).into(); + + for row in 0..min_dnum { + for col in 0..(res.rank() + 1).into() { + self.glwe_external_product(&mut res.at_mut(row, col), &a.at(row, col), b, scratch); + } + } + + for row in min_dnum..res.dnum().into() { + for col in 0..(res.rank() + 1).into() { + res.at_mut(row, col).data.zero(); + } + } } -} -impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> { - pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GGSWCiphertext<DataLhs>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + fn ggsw_external_product_inplace<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<BE>) + where + R: GGSWToMut, + A: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - use crate::layouts::LWEInfos; + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let a: &GGSWPrepared<&[u8], BE> = &a.to_ref(); - assert_eq!(lhs.n(), self.n()); - assert_eq!(rhs.n(), self.n()); - - assert_eq!( - self.rank(), - lhs.rank(), - "ggsw_out rank: {} != ggsw_in rank: {}", - self.rank(), - lhs.rank() - ); - assert_eq!( - self.rank(), - rhs.rank(), - "ggsw_in rank: {} != ggsw_apply rank: {}", - self.rank(), - rhs.rank() - ); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(a.n(), self.n() as u32); + assert_eq!( + res.rank(), + a.rank(), + "res rank: {} != a rank: {}", + res.rank(), + a.rank() + ); - assert!(scratch.available() >= GGSWCiphertext::external_product_scratch_space(module, self, lhs, rhs)) + for row in 0..res.dnum().into() { + for col in 0..(res.rank() + 1).into() { + self.glwe_external_product_inplace(&mut res.at_mut(row, col), a, scratch); + } } + } +} - let min_dnum: usize = self.dnum().min(lhs.dnum()).into(); +impl<BE: Backend> GGSWExternalProduct<BE> for Module<BE> where Self: GLWEExternalProduct<BE> {} - (0..(self.rank() + 1).into()).for_each(|col_i| { - (0..min_dnum).for_each(|row_j| { - self.at_mut(row_j, col_i) - .external_product(module, &lhs.at(row_j, col_i), rhs, scratch); - }); - (min_dnum..self.dnum().into()).for_each(|row_i| { - self.at_mut(row_i, col_i).data.zero(); - }); - }); +impl GGSW<Vec<u8>> { + pub fn external_product_tmp_bytes<R, A, B, M, BE: Backend>( + &self, + module: &M, + res_infos: &R, + a_infos: &A, + b_infos: &B, + ) -> usize + where + R: GGSWInfos, + A: GGSWInfos, + B: GGSWInfos, + M: GGSWExternalProduct<BE>, + { + module.ggsw_external_product_tmp_bytes(res_infos, a_infos, b_infos) } +} - pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, +impl<DataSelf: DataMut> GGSW<DataSelf> { + pub fn external_product<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) + where + M: GGSWExternalProduct<BE>, + A: GGSWToRef, + B: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - use crate::layouts::LWEInfos; - - assert_eq!(rhs.n(), self.n()); - assert_eq!( - self.rank(), - rhs.rank(), - "ggsw_out rank: {} != ggsw_apply: {}", - self.rank(), - rhs.rank() - ); - } + module.ggsw_external_product(self, a, b, scratch); + } - (0..(self.rank() + 1).into()).for_each(|col_i| { - (0..self.dnum().into()).for_each(|row_j| { - self.at_mut(row_j, col_i) - .external_product_inplace(module, rhs, scratch); - }); - }); + pub fn external_product_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) + where + M: GGSWExternalProduct<BE>, + A: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.ggsw_external_product_inplace(self, a, scratch); } }
M poulpy-core/src/external_product/glwe_ct.rs → poulpy-core/src/external_product/glwe_ct.rs

@@ -1,102 +1,57 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, + ModuleN, ScratchTakeBasic, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, + VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, }, - layouts::{Backend, DataMut, DataRef, DataViewMut, Module, Scratch, VecZnx, VecZnxBig}, + layouts::{Backend, DataMut, DataViewMut, Module, Scratch, VecZnx, VecZnxBig}, }; use crate::{ - GLWEExternalProduct, GLWEExternalProductInplace, + ScratchTakeCore, layouts::{ - GGSWInfos, GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEInfos, LWEInfos, - prepared::{GGSWCiphertextPrepared, GGSWCiphertextPreparedToRef}, + GGSWInfos, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, LWEInfos, + prepared::{GGSWPrepared, GGSWPreparedToRef}, }, }; -impl GLWECiphertext<Vec<u8>> { - #[allow(clippy::too_many_arguments)] - pub fn external_product_scratch_space<B: Backend, OUT, IN, GGSW>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - apply_infos: &GGSW, - ) -> usize +impl GLWE<Vec<u8>> { + pub fn external_product_tmp_bytes<R, A, B, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, b_infos: &B) -> usize where - OUT: GLWEInfos, - IN: GLWEInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + R: GLWEInfos, + A: GLWEInfos, + B: GGSWInfos, + M: GLWEExternalProduct<BE>, { - let in_size: usize = in_infos - .k() - .div_ceil(apply_infos.base2k()) - .div_ceil(apply_infos.dsize().into()) as usize; - let out_size: usize = out_infos.size(); - let ggsw_size: usize = apply_infos.size(); - let res_dft: usize = module.vec_znx_dft_alloc_bytes((apply_infos.rank() + 1).into(), ggsw_size); - let a_dft: usize = module.vec_znx_dft_alloc_bytes((apply_infos.rank() + 1).into(), in_size); - let vmp: usize = module.vmp_apply_dft_to_dft_tmp_bytes( - out_size, - in_size, - in_size, // rows - (apply_infos.rank() + 1).into(), // cols in - (apply_infos.rank() + 1).into(), // cols out - ggsw_size, - ); - let normalize_big: usize = module.vec_znx_normalize_tmp_bytes(); - - if in_infos.base2k() == apply_infos.base2k() { - res_dft + a_dft + (vmp | normalize_big) - } else { - let normalize_conv: usize = VecZnx::alloc_bytes(module.n(), (apply_infos.rank() + 1).into(), in_size); - res_dft + ((a_dft + normalize_conv + (module.vec_znx_normalize_tmp_bytes() | vmp)) | normalize_big) - } + module.glwe_external_product_tmp_bytes(res_infos, a_infos, b_infos) } +} - pub fn external_product_inplace_scratch_space<B: Backend, OUT, GGSW>( - module: &Module<B>, - out_infos: &OUT, - apply_infos: &GGSW, - ) -> usize +impl<DataSelf: DataMut> GLWE<DataSelf> { + pub fn external_product<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) where - OUT: GLWEInfos, - GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes, + A: GLWEToRef, + B: GGSWPreparedToRef<BE>, + M: GLWEExternalProduct<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - Self::external_product_scratch_space(module, out_infos, out_infos, apply_infos) + module.glwe_external_product(self, a, b, scratch); } -} -impl<DataSelf: DataMut> GLWECiphertext<DataSelf> { - pub fn external_product<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GLWECiphertext<DataLhs>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWEExternalProduct<B>, + pub fn external_product_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) + where + A: GGSWPreparedToRef<BE>, + M: GLWEExternalProduct<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - module.external_product(self, lhs, rhs, scratch); - } - - pub fn external_product_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGSWCiphertextPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: GLWEExternalProductInplace<B>, - { - module.external_product_inplace(self, rhs, scratch); + module.glwe_external_product_inplace(self, a, scratch); } } -impl<BE: Backend> GLWEExternalProductInplace<BE> for Module<BE> +pub trait GLWEExternalProduct<BE: Backend> where - Module<BE>: VecZnxDftAllocBytes + Self: Sized + + ModuleN + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes + VecZnxDftApply<BE>

@@ -105,15 +60,47 @@ + VmpApplyDftToDftAdd<BE>

+ VecZnxIdftApplyConsume<BE> + VecZnxBigNormalize<BE> + VecZnxNormalize<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx, { - fn external_product_inplace<R, D>(&self, res: &mut R, ggsw: &D, scratch: &mut Scratch<BE>) + fn glwe_external_product_tmp_bytes<R, A, B>(&self, res_infos: &R, a_infos: &A, b_infos: &B) -> usize + where + R: GLWEInfos, + A: GLWEInfos, + B: GGSWInfos, + { + let in_size: usize = a_infos + .k() + .div_ceil(b_infos.base2k()) + .div_ceil(b_infos.dsize().into()) as usize; + let out_size: usize = res_infos.size(); + let ggsw_size: usize = b_infos.size(); + let res_dft: usize = self.bytes_of_vec_znx_dft((b_infos.rank() + 1).into(), ggsw_size); + let a_dft: usize = self.bytes_of_vec_znx_dft((b_infos.rank() + 1).into(), in_size); + let vmp: usize = self.vmp_apply_dft_to_dft_tmp_bytes( + out_size, + in_size, + in_size, // rows + (b_infos.rank() + 1).into(), // cols in + (b_infos.rank() + 1).into(), // cols out + ggsw_size, + ); + let normalize_big: usize = self.vec_znx_normalize_tmp_bytes(); + + if a_infos.base2k() == b_infos.base2k() { + res_dft + a_dft + (vmp | normalize_big) + } else { + let normalize_conv: usize = VecZnx::bytes_of(self.n(), (b_infos.rank() + 1).into(), in_size); + res_dft + ((a_dft + normalize_conv + (self.vec_znx_normalize_tmp_bytes() | vmp)) | normalize_big) + } + } + + fn glwe_external_product_inplace<R, D>(&self, res: &mut R, a: &D, scratch: &mut Scratch<BE>) where - R: GLWECiphertextToMut, - D: GGSWCiphertextPreparedToRef<BE>, + R: GLWEToMut, + D: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - let res: &mut GLWECiphertext<&mut [u8]> = &mut res.to_mut(); - let rhs: &GGSWCiphertextPrepared<&[u8], BE> = &ggsw.to_ref(); + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let rhs: &GGSWPrepared<&[u8], BE> = &a.to_ref(); let basek_in: usize = res.base2k().into(); let basek_ggsw: usize = rhs.base2k().into();

@@ -124,15 +111,15 @@ use poulpy_hal::api::ScratchAvailable;

assert_eq!(rhs.rank(), res.rank()); assert_eq!(rhs.n(), res.n()); - assert!(scratch.available() >= GLWECiphertext::external_product_inplace_scratch_space(self, res, rhs)); + assert!(scratch.available() >= self.glwe_external_product_tmp_bytes(res, res, rhs)); } let cols: usize = (rhs.rank() + 1).into(); let dsize: usize = rhs.dsize().into(); let a_size: usize = (res.size() * basek_in).div_ceil(basek_ggsw); - let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(res.n().into(), cols, rhs.size()); // Todo optimise - let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(res.n().into(), cols, a_size.div_ceil(dsize)); + let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(self, cols, rhs.size()); // Todo optimise + let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self, cols, a_size.div_ceil(dsize)); a_dft.data_mut().fill(0); if basek_in == basek_ggsw {

@@ -160,7 +147,7 @@ self.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);

} } } else { - let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(self.n(), cols, a_size); + let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(self, cols, a_size); for j in 0..cols { self.vec_znx_normalize(

@@ -213,31 +200,18 @@ scratch_1,

); } } -} -impl<BE: Backend> GLWEExternalProduct<BE> for Module<BE> -where - Module<BE>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<BE> - + VmpApplyDftToDft<BE> - + VmpApplyDftToDftAdd<BE> - + VecZnxIdftApplyConsume<BE> - + VecZnxBigNormalize<BE> - + VecZnxNormalize<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx, -{ - fn external_product<R, A, D>(&self, res: &mut R, lhs: &A, rhs: &D, scratch: &mut Scratch<BE>) + fn glwe_external_product<R, A, D>(&self, res: &mut R, lhs: &A, rhs: &D, scratch: &mut Scratch<BE>) where - R: GLWECiphertextToMut, - A: GLWECiphertextToRef, - D: GGSWCiphertextPreparedToRef<BE>, + R: GLWEToMut, + A: GLWEToRef, + D: GGSWPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - let res: &mut GLWECiphertext<&mut [u8]> = &mut res.to_mut(); - let lhs: &GLWECiphertext<&[u8]> = &lhs.to_ref(); + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let lhs: &GLWE<&[u8]> = &lhs.to_ref(); - let rhs: &GGSWCiphertextPrepared<&[u8], BE> = &rhs.to_ref(); + let rhs: &GGSWPrepared<&[u8], BE> = &rhs.to_ref(); let basek_in: usize = lhs.base2k().into(); let basek_ggsw: usize = rhs.base2k().into();

@@ -251,7 +225,7 @@ assert_eq!(rhs.rank(), lhs.rank());

assert_eq!(rhs.rank(), res.rank()); assert_eq!(rhs.n(), res.n()); assert_eq!(lhs.n(), res.n()); - assert!(scratch.available() >= GLWECiphertext::external_product_scratch_space(self, res, lhs, rhs)); + assert!(scratch.available() >= self.glwe_external_product_tmp_bytes(res, lhs, rhs)); } let cols: usize = (rhs.rank() + 1).into();

@@ -259,8 +233,8 @@ let dsize: usize = rhs.dsize().into();

let a_size: usize = (lhs.size() * basek_in).div_ceil(basek_ggsw); - let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n(), cols, rhs.size()); // Todo optimise - let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self.n(), cols, a_size.div_ceil(dsize)); + let (mut res_dft, scratch_1) = scratch.take_vec_znx_dft(self, cols, rhs.size()); // Todo optimise + let (mut a_dft, scratch_2) = scratch_1.take_vec_znx_dft(self, cols, a_size.div_ceil(dsize)); a_dft.data_mut().fill(0); if basek_in == basek_ggsw {

@@ -288,7 +262,7 @@ self.vmp_apply_dft_to_dft_add(&mut res_dft, &a_dft, &rhs.data, di, scratch_2);

} } } else { - let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(self.n(), cols, a_size); + let (mut a_conv, scratch_3) = scratch_2.take_vec_znx(self, cols, a_size); for j in 0..cols { self.vec_znx_normalize(

@@ -342,3 +316,20 @@ );

}); } } + +impl<BE: Backend> GLWEExternalProduct<BE> for Module<BE> where + Self: ModuleN + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxNormalizeTmpBytes + + VecZnxDftApply<BE> + + VmpApplyDftToDft<BE> + + VmpApplyDftToDftAdd<BE> + + VecZnxIdftApplyConsume<BE> + + VecZnxBigNormalize<BE> + + VecZnxNormalize<BE> + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxNormalizeTmpBytes +{ +}
M poulpy-core/src/external_product/mod.rs → poulpy-core/src/external_product/mod.rs

@@ -1,23 +1,8 @@

-use poulpy_hal::layouts::{Backend, Scratch}; - -use crate::layouts::{GLWECiphertextToMut, GLWECiphertextToRef, prepared::GGSWCiphertextPreparedToRef}; - mod gglwe_atk; mod gglwe_ksk; mod ggsw_ct; mod glwe_ct; -pub trait GLWEExternalProduct<BE: Backend> { - fn external_product<R, A, D>(&self, res: &mut R, a: &A, ggsw: &D, scratch: &mut Scratch<BE>) - where - R: GLWECiphertextToMut, - A: GLWECiphertextToRef, - D: GGSWCiphertextPreparedToRef<BE>; -} - -pub trait GLWEExternalProductInplace<BE: Backend> { - fn external_product_inplace<R, D>(&self, res: &mut R, ggsw: &D, scratch: &mut Scratch<BE>) - where - R: GLWECiphertextToMut, - D: GGSWCiphertextPreparedToRef<BE>; -} +pub use gglwe_ksk::*; +pub use ggsw_ct::*; +pub use glwe_ct::*;
M poulpy-core/src/glwe_packing.rs → poulpy-core/src/glwe_packing.rs

@@ -2,18 +2,18 @@ use std::collections::HashMap;

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, - VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, - VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, - VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + ScratchAvailable, VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, + VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, + VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, + VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch}, }; use crate::{ - GLWEOperations, TakeGLWECt, - layouts::{GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared}, + GLWEOperations, + layouts::{GGLWEInfos, GLWE, GLWEInfos, LWEInfos, prepared::AutomorphismKeyPrepared}, }; /// [GLWEPacker] enables only the fly GLWE packing

@@ -29,7 +29,7 @@

/// [Accumulator] stores intermediate packing result. /// There are Log(N) such accumulators in a [GLWEPacker]. struct Accumulator { - data: GLWECiphertext<Vec<u8>>, + data: GLWE<Vec<u8>>, value: bool, // Implicit flag for zero ciphertext control: bool, // Can be combined with incoming value }

@@ -43,12 +43,12 @@ /// * `module`: static backend FFT tables.

/// * `base2k`: base 2 logarithm of the GLWE ciphertext in memory digit representation. /// * `k`: base 2 precision of the GLWE ciphertext precision over the Torus. /// * `rank`: rank of the GLWE ciphertext. - pub fn alloc<A>(infos: &A) -> Self + pub fn alloc<A, B: Backend>(module: &Module<B>, infos: &A) -> Self where A: GLWEInfos, { Self { - data: GLWECiphertext::alloc(infos), + data: GLWE::alloc_from_infos(module, infos), value: false, control: false, }

@@ -66,13 +66,13 @@ /// i.e. with `log_batch=0` only the constant coefficient is packed

/// and N GLWE ciphertext can be packed. With `log_batch=2` all coefficients /// which are multiples of X^{N/4} are packed. Meaning that N/4 ciphertexts /// can be packed. - pub fn new<A>(infos: &A, log_batch: usize) -> Self + pub fn new<A, B: Backend>(module: Module<B>, infos: &A, log_batch: usize) -> Self where A: GLWEInfos, { let mut accumulators: Vec<Accumulator> = Vec::<Accumulator>::new(); let log_n: usize = infos.n().log2(); - (0..log_n - log_batch).for_each(|_| accumulators.push(Accumulator::alloc(infos))); + (0..log_n - log_batch).for_each(|_| accumulators.push(Accumulator::alloc(module, infos))); Self { accumulators, log_batch,

@@ -90,17 +90,17 @@ self.counter = 0;

} /// Number of scratch space bytes required to call [Self::add]. - pub fn scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize + pub fn tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize where OUT: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - pack_core_scratch_space(module, out_infos, key_infos) + pack_core_tmp_bytes(module, out_infos, key_infos) } pub fn galois_elements<B: Backend>(module: &Module<B>) -> Vec<i64> { - GLWECiphertext::trace_galois_elements(module) + GLWE::trace_galois_elements(module) } /// Adds a GLWE ciphertext to the [GLWEPacker].

@@ -111,15 +111,15 @@ /// * `res`: space to append fully packed ciphertext. Only when the number

/// of packed ciphertexts reaches N/2^log_batch is a result written. /// * `a`: ciphertext to pack. Can optionally give None to pack a 0 ciphertext. /// * `auto_keys`: a [HashMap] containing the [AutomorphismKeyExec]s. - /// * `scratch`: scratch space of size at least [Self::scratch_space]. + /// * `scratch`: scratch space of size at least [Self::tmp_bytes]. pub fn add<DataA: DataRef, DataAK: DataRef, B: Backend>( &mut self, module: &Module<B>, - a: Option<&GLWECiphertext<DataA>>, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, + a: Option<&GLWE<DataA>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -142,7 +142,7 @@ + VecZnxBigSubSmallNegateInplace<B>

+ VecZnxBigAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { assert!( (self.counter as u32) < self.accumulators[0].data.n(),

@@ -162,7 +162,7 @@ self.counter += 1 << self.log_batch;

} /// Flush result to`res`. - pub fn flush<Data: DataMut, B: Backend>(&mut self, module: &Module<B>, res: &mut GLWECiphertext<Data>) + pub fn flush<Data: DataMut, B: Backend>(&mut self, module: &Module<B>, res: &mut GLWE<Data>) where Module<B>: VecZnxCopy, {

@@ -177,24 +177,24 @@ self.reset();

} } -fn pack_core_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize +fn pack_core_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize where OUT: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - combine_scratch_space(module, out_infos, key_infos) + combine_tmp_bytes(module, out_infos, key_infos) } fn pack_core<D: DataRef, DataAK: DataRef, B: Backend>( module: &Module<B>, - a: Option<&GLWECiphertext<D>>, + a: Option<&GLWE<D>>, accumulators: &mut [Accumulator], i: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -217,7 +217,7 @@ + VecZnxBigSubSmallNegateInplace<B>

+ VecZnxBigAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { let log_n: usize = module.log_n();

@@ -258,7 +258,7 @@ );

} else { pack_core( module, - None::<&GLWECiphertext<Vec<u8>>>, + None::<&GLWE<Vec<u8>>>, acc_next, i + 1, auto_keys,

@@ -268,27 +268,26 @@ }

} } -fn combine_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize +fn combine_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize where OUT: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - GLWECiphertext::alloc_bytes(out_infos) - + (GLWECiphertext::rsh_scratch_space(module.n()) - | GLWECiphertext::automorphism_inplace_scratch_space(module, out_infos, key_infos)) + GLWE::bytes_of_from_infos(module, out_infos) + + (GLWE::rsh_tmp_bytes(module.n()) | GLWE::automorphism_inplace_tmp_bytes(module, out_infos, key_infos)) } /// [combine] merges two ciphertexts together. fn combine<D: DataRef, DataAK: DataRef, B: Backend>( module: &Module<B>, acc: &mut Accumulator, - b: Option<&GLWECiphertext<D>>, + b: Option<&GLWE<D>>, i: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -311,10 +310,10 @@ + VecZnxBigSubSmallNegateInplace<B>

+ VecZnxBigAutomorphismInplace<B> + VecZnxNormalize<B> + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeGLWECt, + Scratch<B>: ScratchAvailable, { let log_n: usize = acc.data.n().log2(); - let a: &mut GLWECiphertext<Vec<u8>> = &mut acc.data; + let a: &mut GLWE<Vec<u8>> = &mut acc.data; let gal_el: i64 = if i == 0 { -1

@@ -395,9 +394,9 @@ /// Packs [x_0: GLWE(m_0), x_1: GLWE(m_1), ..., x_i: GLWE(m_i)]

/// to [0: GLWE(m_0 * X^x_0 + m_1 * X^x_1 + ... + m_i * X^x_i)] pub fn glwe_packing<D: DataMut, ATK, B: Backend>( module: &Module<B>, - cts: &mut HashMap<usize, &mut GLWECiphertext<D>>, + cts: &mut HashMap<usize, &mut GLWE<D>>, log_gap_out: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<ATK, B>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<ATK, B>>, scratch: &mut Scratch<B>, ) where ATK: DataRef,

@@ -414,7 +413,7 @@ + VecZnxAddInplace

+ VecZnxNegateInplace + VecZnxCopy + VecZnxSubInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -427,7 +426,7 @@ + VecZnxAutomorphismInplace<B>

+ VecZnxBigSubSmallNegateInplace<B> + VecZnxRotate + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable, + Scratch<B>: ScratchAvailable, { #[cfg(debug_assertions)] {

@@ -439,15 +438,15 @@

(0..log_n - log_gap_out).for_each(|i| { let t: usize = (1 << log_n).min(1 << (log_n - 1 - i)); - let auto_key: &GGLWEAutomorphismKeyPrepared<ATK, B> = if i == 0 { + let auto_key: &AutomorphismKeyPrepared<ATK, B> = if i == 0 { auto_keys.get(&-1).unwrap() } else { auto_keys.get(&module.galois_element(1 << (i - 1))).unwrap() }; (0..t).for_each(|j| { - let mut a: Option<&mut GLWECiphertext<D>> = cts.remove(&j); - let mut b: Option<&mut GLWECiphertext<D>> = cts.remove(&(j + t)); + let mut a: Option<&mut GLWE<D>> = cts.remove(&j); + let mut b: Option<&mut GLWE<D>> = cts.remove(&(j + t)); pack_internal(module, &mut a, &mut b, i, auto_key, scratch);

@@ -463,10 +462,10 @@

#[allow(clippy::too_many_arguments)] fn pack_internal<A: DataMut, D: DataMut, DataAK: DataRef, B: Backend>( module: &Module<B>, - a: &mut Option<&mut GLWECiphertext<A>>, - b: &mut Option<&mut GLWECiphertext<D>>, + a: &mut Option<&mut GLWE<A>>, + b: &mut Option<&mut GLWE<D>>, i: usize, - auto_key: &GGLWEAutomorphismKeyPrepared<DataAK, B>, + auto_key: &AutomorphismKeyPrepared<DataAK, B>, scratch: &mut Scratch<B>, ) where Module<B>: VecZnxRotateInplace<B>

@@ -481,7 +480,7 @@ + VecZnxAddInplace

+ VecZnxNegateInplace + VecZnxCopy + VecZnxSubInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -494,7 +493,7 @@ + VecZnxAutomorphismInplace<B>

+ VecZnxBigSubSmallNegateInplace<B> + VecZnxRotate + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnx + TakeVecZnxDft<B> + ScratchAvailable, + Scratch<B>: ScratchAvailable, { // Goal is to evaluate: a = a + b*X^t + phi(a - b*X^t)) // We also use the identity: AUTO(a * X^t, g) = -X^t * AUTO(a, g)
M poulpy-core/src/glwe_trace.rs → poulpy-core/src/glwe_trace.rs

@@ -2,22 +2,19 @@ use std::collections::HashMap;

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, - VecZnxNormalizeTmpBytes, VecZnxRshInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, + ScratchAvailable, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, + VecZnxRshInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx}, }; use crate::{ - TakeGLWECt, - layouts::{ - Base2K, GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, GLWEInfos, LWEInfos, prepared::GGLWEAutomorphismKeyPrepared, - }, + layouts::{Base2K, GGLWEInfos, GLWE, GLWEInfos, GLWELayout, LWEInfos, prepared::AutomorphismKeyPrepared}, operations::GLWEOperations, }; -impl GLWECiphertext<Vec<u8>> { +impl GLWE<Vec<u8>> { pub fn trace_galois_elements<B: Backend>(module: &Module<B>) -> Vec<i64> { let mut gal_els: Vec<i64> = Vec::new(); (0..module.log_n()).for_each(|i| {

@@ -30,21 +27,16 @@ });

gal_els } - pub fn trace_scratch_space<B: Backend, OUT, IN, KEY>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - key_infos: &KEY, - ) -> usize + pub fn trace_tmp_bytes<B: Backend, OUT, IN, KEY>(module: &Module<B>, out_infos: &OUT, in_infos: &IN, key_infos: &KEY) -> usize where OUT: GLWEInfos, IN: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - let trace: usize = Self::automorphism_inplace_scratch_space(module, out_infos, key_infos); + let trace: usize = Self::automorphism_inplace_tmp_bytes(module, out_infos, key_infos); if in_infos.base2k() != key_infos.base2k() { - let glwe_conv: usize = VecZnx::alloc_bytes( + let glwe_conv: usize = VecZnx::bytes_of( module.n(), (key_infos.rank_out() + 1).into(), out_infos.k().min(in_infos.k()).div_ceil(key_infos.base2k()) as usize,

@@ -55,27 +47,27 @@

trace } - pub fn trace_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize + pub fn trace_inplace_tmp_bytes<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize where OUT: GLWEInfos, KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, { - Self::trace_scratch_space(module, out_infos, out_infos, key_infos) + Self::trace_tmp_bytes(module, out_infos, out_infos, key_infos) } } -impl<DataSelf: DataMut> GLWECiphertext<DataSelf> { +impl<DataSelf: DataMut> GLWE<DataSelf> { pub fn trace<DataLhs: DataRef, DataAK: DataRef, B: Backend>( &mut self, module: &Module<B>, start: usize, end: usize, - lhs: &GLWECiphertext<DataLhs>, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, + lhs: &GLWE<DataLhs>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -89,7 +81,7 @@ + VecZnxRshInplace<B>

+ VecZnxCopy + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { self.copy(module, lhs); self.trace_inplace(module, start, end, auto_keys, scratch);

@@ -100,10 +92,10 @@ &mut self,

module: &Module<B>, start: usize, end: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<DataAK, B>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<DataAK, B>>, scratch: &mut Scratch<B>, ) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -116,7 +108,7 @@ + VecZnxBigAutomorphismInplace<B>

+ VecZnxRshInplace<B> + VecZnxNormalizeTmpBytes + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + Scratch<B>: ScratchAvailable, { let basek_ksk: Base2K = auto_keys .get(auto_keys.keys().next().unwrap())

@@ -137,7 +129,7 @@ }

} if self.base2k() != basek_ksk { - let (mut self_conv, scratch_1) = scratch.take_glwe_ct(&GLWECiphertextLayout { + let (mut self_conv, scratch_1) = scratch.take_glwe_ct(&GLWELayout { n: module.n().into(), base2k: basek_ksk, k: self.k(),
M poulpy-core/src/keyswitching/gglwe_ct.rs → poulpy-core/src/keyswitching/gglwe_ct.rs

@@ -1,224 +1,205 @@

-use poulpy_hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, - VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, +use poulpy_hal::layouts::{Backend, DataMut, Module, Scratch}; + +use crate::{ + ScratchTakeCore, + keyswitching::glwe_ct::GLWEKeySwitch, + layouts::{ + AutomorphismKey, AutomorphismKeyToRef, GGLWE, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWESwitchingKey, + GLWESwitchingKeyToRef, + prepared::{GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedToRef}, }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxZero}, }; -use crate::layouts::{ - GGLWEAutomorphismKey, GGLWEInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos, - prepared::{GGLWEAutomorphismKeyPrepared, GGLWESwitchingKeyPrepared}, -}; +impl AutomorphismKey<Vec<u8>> { + pub fn keyswitch_inplace_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize + where + R: GGLWEInfos, + A: GGLWEInfos, + K: GGLWEInfos, + M: GGLWEKeySwitch<BE>, + { + module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos) + } +} -impl GGLWEAutomorphismKey<Vec<u8>> { - pub fn keyswitch_scratch_space<B: Backend, OUT, IN, KEY>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - key_infos: &KEY, - ) -> usize +impl<DataSelf: DataMut> AutomorphismKey<DataSelf> { + pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) + where + A: AutomorphismKeyToRef, + B: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGLWEKeySwitch<BE>, + { + module.gglwe_keyswitch(&mut self.key.key, &a.to_ref().key.key, b, scratch); + } + + pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) where - OUT: GGLWEInfos, - IN: GGLWEInfos, - KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + A: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGLWEKeySwitch<BE>, { - GGLWESwitchingKey::keyswitch_scratch_space(module, out_infos, in_infos, key_infos) + module.gglwe_keyswitch_inplace(&mut self.key.key, a, scratch); } +} - pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_infos: &KEY) -> usize +impl GLWESwitchingKey<Vec<u8>> { + pub fn keyswitch_inplace_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where - OUT: GGLWEInfos, - KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + R: GGLWEInfos, + A: GGLWEInfos, + K: GGLWEInfos, + M: GGLWEKeySwitch<BE>, { - GGLWESwitchingKey::keyswitch_inplace_scratch_space(module, out_infos, key_infos) + module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos) } } -impl<DataSelf: DataMut> GGLWEAutomorphismKey<DataSelf> { - pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GGLWEAutomorphismKey<DataLhs>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, +impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> { + pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) + where + A: GLWESwitchingKeyToRef, + B: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGLWEKeySwitch<BE>, + { + module.gglwe_keyswitch(&mut self.key, &a.to_ref().key, b, scratch); + } + + pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) + where + A: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGLWEKeySwitch<BE>, { - self.key.keyswitch(module, &lhs.key, rhs, scratch); + module.gglwe_keyswitch_inplace(&mut self.key, a, scratch); } +} - pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGLWEAutomorphismKeyPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, +impl GGLWE<Vec<u8>> { + pub fn keyswitch_inplace_tmp_bytes<R, A, K, M, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize + where + R: GGLWEInfos, + A: GGLWEInfos, + K: GGLWEInfos, + M: GGLWEKeySwitch<BE>, { - self.key.keyswitch_inplace(module, &rhs.key, scratch); + module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos) } } -impl GGLWESwitchingKey<Vec<u8>> { - pub fn keyswitch_scratch_space<B: Backend, OUT, IN, KEY>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - key_apply: &KEY, - ) -> usize +impl<DataSelf: DataMut> GGLWE<DataSelf> { + pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) where - OUT: GGLWEInfos, - IN: GGLWEInfos, - KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + A: GGLWEToRef, + B: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGLWEKeySwitch<BE>, { - GLWECiphertext::keyswitch_scratch_space(module, out_infos, in_infos, key_apply) + module.gglwe_keyswitch(self, a, b, scratch); } - pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_apply: &KEY) -> usize + pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) where - OUT: GGLWEInfos + GLWEInfos, - KEY: GGLWEInfos + GLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + A: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGLWEKeySwitch<BE>, { - GLWECiphertext::keyswitch_inplace_scratch_space(module, out_infos, key_apply) + module.gglwe_keyswitch_inplace(self, a, scratch); } } -impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> { - pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GGLWESwitchingKey<DataLhs>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnx, +impl<BE: Backend> GGLWEKeySwitch<BE> for Module<BE> where Self: GLWEKeySwitch<BE> {} + +pub trait GGLWEKeySwitch<BE: Backend> +where + Self: GLWEKeySwitch<BE>, +{ + fn gglwe_keyswitch_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize + where + R: GGLWEInfos, + A: GGLWEInfos, + K: GGLWEInfos, { - #[cfg(debug_assertions)] - { - assert_eq!( - self.rank_in(), - lhs.rank_in(), - "ksk_out input rank: {} != ksk_in input rank: {}", - self.rank_in(), - lhs.rank_in() - ); - assert_eq!( - lhs.rank_out(), - rhs.rank_in(), - "ksk_in output rank: {} != ksk_apply input rank: {}", - self.rank_out(), - rhs.rank_in() - ); - assert_eq!( - self.rank_out(), - rhs.rank_out(), - "ksk_out output rank: {} != ksk_apply output rank: {}", - self.rank_out(), - rhs.rank_out() - ); - assert!( - self.dnum() <= lhs.dnum(), - "self.dnum()={} > lhs.dnum()={}", - self.dnum(), - lhs.dnum() - ); - assert_eq!( - self.dsize(), - lhs.dsize(), - "ksk_out dsize: {} != ksk_in dsize: {}", - self.dsize(), - lhs.dsize() - ) - } + self.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos) + } - (0..self.rank_in().into()).for_each(|col_i| { - (0..self.dnum().into()).for_each(|row_j| { - self.at_mut(row_j, col_i) - .keyswitch(module, &lhs.at(row_j, col_i), rhs, scratch); - }); - }); + fn gglwe_keyswitch<R, A, B>(&self, res: &mut R, a: &A, b: &B, scratch: &mut Scratch<BE>) + where + R: GGLWEToMut, + A: GGLWEToRef, + B: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GGLWE<&[u8]> = &a.to_ref(); + let b: &GLWESwitchingKeyPrepared<&[u8], BE> = &b.to_ref(); - (self.dnum().min(lhs.dnum()).into()..self.dnum().into()).for_each(|row_i| { - (0..self.rank_in().into()).for_each(|col_j| { - self.at_mut(row_i, col_j).data.zero(); - }); - }); + assert_eq!( + res.rank_in(), + a.rank_in(), + "res input rank: {} != a input rank: {}", + res.rank_in(), + a.rank_in() + ); + assert_eq!( + a.rank_out(), + b.rank_in(), + "res output rank: {} != b input rank: {}", + a.rank_out(), + b.rank_in() + ); + assert_eq!( + res.rank_out(), + b.rank_out(), + "res output rank: {} != b output rank: {}", + res.rank_out(), + b.rank_out() + ); + assert!( + res.dnum() <= a.dnum(), + "res.dnum()={} > a.dnum()={}", + res.dnum(), + a.dnum() + ); + assert_eq!( + res.dsize(), + a.dsize(), + "res dsize: {} != a dsize: {}", + res.dsize(), + a.dsize() + ); + + for row in 0..res.dnum().into() { + for col in 0..res.rank_in().into() { + self.glwe_keyswitch(&mut res.at_mut(row, col), &a.at(row, col), b, scratch); + } + } } - pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnx, + fn gglwe_keyswitch_inplace<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<BE>) + where + R: GGLWEToMut, + A: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - assert_eq!( - self.rank_out(), - rhs.rank_out(), - "ksk_out output rank: {} != ksk_apply output rank: {}", - self.rank_out(), - rhs.rank_out() - ); - } + let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GLWESwitchingKeyPrepared<&[u8], BE> = &a.to_ref(); - (0..self.rank_in().into()).for_each(|col_i| { - (0..self.dnum().into()).for_each(|row_j| { - self.at_mut(row_j, col_i) - .keyswitch_inplace(module, rhs, scratch) - }); - }); + assert_eq!( + res.rank_out(), + a.rank_out(), + "res output rank: {} != a output rank: {}", + res.rank_out(), + a.rank_out() + ); + + for row in 0..res.dnum().into() { + for col in 0..res.rank_in().into() { + self.glwe_keyswitch_inplace(&mut res.at_mut(row, col), a, scratch); + } + } } } + +impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {}
M poulpy-core/src/keyswitching/ggsw_ct.rs → poulpy-core/src/keyswitching/ggsw_ct.rs

@@ -1,366 +1,131 @@

-use poulpy_hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, - VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAddInplace, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, - VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, - }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, VecZnx, VmpPMat, ZnxInfos}, -}; +use poulpy_hal::layouts::{Backend, DataMut, Scratch, VecZnx}; use crate::{ + GGSWExpandRows, ScratchTakeCore, + keyswitching::glwe_ct::GLWEKeySwitch, layouts::{ - GGLWECiphertext, GGLWEInfos, GGSWCiphertext, GGSWInfos, GLWECiphertext, GLWEInfos, LWEInfos, - prepared::{GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared}, + GGLWEInfos, GGSW, GGSWInfos, GGSWToMut, GGSWToRef, + prepared::{GLWESwitchingKeyPreparedToRef, TensorKeyPreparedToRef}, }, - operations::GLWEOperations, }; -impl GGSWCiphertext<Vec<u8>> { - pub(crate) fn expand_row_scratch_space<B: Backend, OUT, TSK>(module: &Module<B>, out_infos: &OUT, tsk_infos: &TSK) -> usize +impl GGSW<Vec<u8>> { + pub fn keyswitch_tmp_bytes<R, A, K, T, M, BE: Backend>( + module: &M, + res_infos: &R, + a_infos: &A, + key_infos: &K, + tsk_infos: &T, + ) -> usize where - OUT: GGSWInfos, - TSK: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigAllocBytes + VecZnxNormalizeTmpBytes, + R: GGSWInfos, + A: GGSWInfos, + K: GGLWEInfos, + T: GGLWEInfos, + M: GGSWKeySwitch<BE>, { - let tsk_size: usize = tsk_infos.k().div_ceil(tsk_infos.base2k()) as usize; - let size_in: usize = out_infos - .k() - .div_ceil(tsk_infos.base2k()) - .div_ceil(tsk_infos.dsize().into()) as usize; + module.ggsw_keyswitch_tmp_bytes(res_infos, a_infos, key_infos, tsk_infos) + } +} - let tmp_dft_i: usize = module.vec_znx_dft_alloc_bytes((tsk_infos.rank_out() + 1).into(), tsk_size); - let tmp_a: usize = module.vec_znx_dft_alloc_bytes(1, size_in); - let vmp: usize = module.vmp_apply_dft_to_dft_tmp_bytes( - tsk_size, - size_in, - size_in, - (tsk_infos.rank_in()).into(), // Verify if rank+1 - (tsk_infos.rank_out()).into(), // Verify if rank+1 - tsk_size, - ); - let tmp_idft: usize = module.vec_znx_big_alloc_bytes(1, tsk_size); - let norm: usize = module.vec_znx_normalize_tmp_bytes(); +impl<D: DataMut> GGSW<D> { + pub fn keyswitch<M, A, K, T, BE: Backend>(&mut self, module: &M, a: &A, key: &K, tsk: &T, scratch: &mut Scratch<BE>) + where + A: GGSWToRef, + K: GLWESwitchingKeyPreparedToRef<BE>, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGSWKeySwitch<BE>, + { + module.ggsw_keyswitch(self, a, key, tsk, scratch); + } - tmp_dft_i + ((tmp_a + vmp) | (tmp_idft + norm)) + pub fn keyswitch_inplace<M, K, T, BE: Backend>(&mut self, module: &M, key: &K, tsk: &T, scratch: &mut Scratch<BE>) + where + K: GLWESwitchingKeyPreparedToRef<BE>, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: GGSWKeySwitch<BE>, + { + module.ggsw_keyswitch_inplace(self, key, tsk, scratch); } +} - #[allow(clippy::too_many_arguments)] - pub fn keyswitch_scratch_space<B: Backend, OUT, IN, KEY, TSK>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - apply_infos: &KEY, - tsk_infos: &TSK, - ) -> usize +pub trait GGSWKeySwitch<BE: Backend> +where + Self: GLWEKeySwitch<BE> + GGSWExpandRows<BE>, +{ + fn ggsw_keyswitch_tmp_bytes<R, A, K, T>(&self, res_infos: &R, a_infos: &A, key_infos: &K, tsk_infos: &T) -> usize where - OUT: GGSWInfos, - IN: GGSWInfos, - KEY: GGLWEInfos, - TSK: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxBigNormalizeTmpBytes, + R: GGSWInfos, + A: GGSWInfos, + K: GGLWEInfos, + T: GGLWEInfos, { - #[cfg(debug_assertions)] - { - assert_eq!(apply_infos.rank_in(), apply_infos.rank_out()); - assert_eq!(tsk_infos.rank_in(), tsk_infos.rank_out()); - assert_eq!(apply_infos.rank_in(), tsk_infos.rank_in()); - } + assert_eq!(key_infos.rank_in(), key_infos.rank_out()); + assert_eq!(tsk_infos.rank_in(), tsk_infos.rank_out()); + assert_eq!(key_infos.rank_in(), tsk_infos.rank_in()); - let rank: usize = apply_infos.rank_out().into(); + let rank: usize = key_infos.rank_out().into(); - let size_out: usize = out_infos.k().div_ceil(out_infos.base2k()) as usize; - let res_znx: usize = VecZnx::alloc_bytes(module.n(), rank + 1, size_out); - let ci_dft: usize = module.vec_znx_dft_alloc_bytes(rank + 1, size_out); - let ks: usize = GLWECiphertext::keyswitch_scratch_space(module, out_infos, in_infos, apply_infos); - let expand_rows: usize = GGSWCiphertext::expand_row_scratch_space(module, out_infos, tsk_infos); - let res_dft: usize = module.vec_znx_dft_alloc_bytes(rank + 1, size_out); + let size_out: usize = res_infos.k().div_ceil(res_infos.base2k()) as usize; + let res_znx: usize = VecZnx::bytes_of(self.n(), rank + 1, size_out); + let ci_dft: usize = self.bytes_of_vec_znx_dft(rank + 1, size_out); + let ks: usize = self.glwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos); + let expand_rows: usize = self.ggsw_expand_rows_tmp_bytes(res_infos, tsk_infos); + let res_dft: usize = self.bytes_of_vec_znx_dft(rank + 1, size_out); - if in_infos.base2k() == tsk_infos.base2k() { + if a_infos.base2k() == tsk_infos.base2k() { res_znx + ci_dft + (ks | expand_rows | res_dft) } else { - let a_conv: usize = VecZnx::alloc_bytes( - module.n(), + let a_conv: usize = VecZnx::bytes_of( + self.n(), 1, - out_infos.k().div_ceil(tsk_infos.base2k()) as usize, - ) + module.vec_znx_normalize_tmp_bytes(); + res_infos.k().div_ceil(tsk_infos.base2k()) as usize, + ) + self.vec_znx_normalize_tmp_bytes(); res_znx + ci_dft + (a_conv | ks | expand_rows | res_dft) } } - #[allow(clippy::too_many_arguments)] - pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY, TSK>( - module: &Module<B>, - out_infos: &OUT, - apply_infos: &KEY, - tsk_infos: &TSK, - ) -> usize + fn ggsw_keyswitch<R, A, K, T>(&self, res: &mut R, a: &A, key: &K, tsk: &T, scratch: &mut Scratch<BE>) where - OUT: GGSWInfos, - KEY: GGLWEInfos, - TSK: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxBigNormalizeTmpBytes, + R: GGSWToMut, + A: GGSWToRef, + K: GLWESwitchingKeyPreparedToRef<BE>, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - GGSWCiphertext::keyswitch_scratch_space(module, out_infos, out_infos, apply_infos, tsk_infos) - } -} + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let a: &GGSW<&[u8]> = &a.to_ref(); -impl<DataSelf: DataMut> GGSWCiphertext<DataSelf> { - pub fn from_gglwe<DataA, DataTsk, B: Backend>( - &mut self, - module: &Module<B>, - a: &GGLWECiphertext<DataA>, - tsk: &GGLWETensorKeyPrepared<DataTsk, B>, - scratch: &mut Scratch<B>, - ) where - DataA: DataRef, - DataTsk: DataRef, - Module<B>: VecZnxCopy - + VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VecZnxDftCopy<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftAddInplace<B> - + VecZnxBigNormalize<B> - + VecZnxIdftApplyTmpA<B> - + VecZnxNormalize<B>, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - use crate::layouts::{GLWEInfos, LWEInfos}; + assert_eq!(res.ggsw_layout(), a.ggsw_layout()); - assert_eq!(self.rank(), a.rank_out()); - assert_eq!(self.dnum(), a.dnum()); - assert_eq!(self.n(), module.n() as u32); - assert_eq!(a.n(), module.n() as u32); - assert_eq!(tsk.n(), module.n() as u32); + for row in 0..a.dnum().into() { + // Key-switch column 0, i.e. + // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0s0' + a1s1' + a2s2') + M[i], a0, a1, a2) + self.glwe_keyswitch(&mut res.at_mut(row, 0), &a.at(row, 0), key, scratch); } - (0..self.dnum().into()).for_each(|row_i| { - self.at_mut(row_i, 0).copy(module, &a.at(row_i, 0)); - }); - self.expand_row(module, tsk, scratch); + + self.ggsw_expand_row(res, tsk, scratch); } - pub fn keyswitch<DataLhs: DataRef, DataKsk: DataRef, DataTsk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - lhs: &GGSWCiphertext<DataLhs>, - ksk: &GGLWESwitchingKeyPrepared<DataKsk, B>, - tsk: &GGLWETensorKeyPrepared<DataTsk, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxDftAllocBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftCopy<B> - + VecZnxDftAddInplace<B> - + VecZnxIdftApplyTmpA<B> - + VecZnxNormalize<B>, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx, + fn ggsw_keyswitch_inplace<R, K, T>(&self, res: &mut R, key: &K, tsk: &T, scratch: &mut Scratch<BE>) + where + R: GGSWToMut, + K: GLWESwitchingKeyPreparedToRef<BE>, + T: TensorKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - (0..lhs.dnum().into()).for_each(|row_i| { - // Key-switch column 0, i.e. - // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0s0' + a1s1' + a2s2') + M[i], a0, a1, a2) - self.at_mut(row_i, 0) - .keyswitch(module, &lhs.at(row_i, 0), ksk, scratch); - }); - self.expand_row(module, tsk, scratch); - } + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); - pub fn keyswitch_inplace<DataKsk: DataRef, DataTsk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - ksk: &GGLWESwitchingKeyPrepared<DataKsk, B>, - tsk: &GGLWETensorKeyPrepared<DataTsk, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxDftAllocBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftCopy<B> - + VecZnxDftAddInplace<B> - + VecZnxIdftApplyTmpA<B> - + VecZnxNormalize<B>, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx, - { - (0..self.dnum().into()).for_each(|row_i| { + for row in 0..res.dnum().into() { // Key-switch column 0, i.e. // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0, a1, a2) -> (-(a0s0' + a1s1' + a2s2') + M[i], a0, a1, a2) - self.at_mut(row_i, 0) - .keyswitch_inplace(module, ksk, scratch); - }); - self.expand_row(module, tsk, scratch); - } - - pub fn expand_row<DataTsk: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - tsk: &GGLWETensorKeyPrepared<DataTsk, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigAllocBytes - + VecZnxNormalizeTmpBytes - + VecZnxDftApply<B> - + VecZnxDftCopy<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftAddInplace<B> - + VecZnxBigNormalize<B> - + VecZnxIdftApplyTmpA<B> - + VecZnxNormalize<B>, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnx, - { - let basek_in: usize = self.base2k().into(); - let basek_tsk: usize = tsk.base2k().into(); - - assert!(scratch.available() >= GGSWCiphertext::expand_row_scratch_space(module, self, tsk)); - - let n: usize = self.n().into(); - let rank: usize = self.rank().into(); - let cols: usize = rank + 1; - - let a_size: usize = (self.size() * basek_in).div_ceil(basek_tsk); - - // Keyswitch the j-th row of the col 0 - for row_i in 0..self.dnum().into() { - let a = &self.at(row_i, 0).data; - - // Pre-compute DFT of (a0, a1, a2) - let (mut ci_dft, scratch_1) = scratch.take_vec_znx_dft(n, cols, a_size); - - if basek_in == basek_tsk { - for i in 0..cols { - module.vec_znx_dft_apply(1, 0, &mut ci_dft, i, a, i); - } - } else { - let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(n, 1, a_size); - for i in 0..cols { - module.vec_znx_normalize(basek_tsk, &mut a_conv, 0, basek_in, a, i, scratch_2); - module.vec_znx_dft_apply(1, 0, &mut ci_dft, i, &a_conv, 0); - } - } + self.glwe_keyswitch_inplace(&mut res.at_mut(row, 0), key, scratch); + } - for col_j in 1..cols { - // Example for rank 3: - // - // Note: M is a vector (m, Bm, B^2m, B^3m, ...), so each column is - // actually composed of that many dnum and we focus on a specific row here - // implicitely given ci_dft. - // - // # Input - // - // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0 , a1 , a2 ) - // col 1: (0, 0, 0, 0) - // col 2: (0, 0, 0, 0) - // col 3: (0, 0, 0, 0) - // - // # Output - // - // col 0: (-(a0s0 + a1s1 + a2s2) + M[i], a0 , a1 , a2 ) - // col 1: (-(b0s0 + b1s1 + b2s2) , b0 + M[i], b1 , b2 ) - // col 2: (-(c0s0 + c1s1 + c2s2) , c0 , c1 + M[i], c2 ) - // col 3: (-(d0s0 + d1s1 + d2s2) , d0 , d1 , d2 + M[i]) - - let dsize: usize = tsk.dsize().into(); - - let (mut tmp_dft_i, scratch_2) = scratch_1.take_vec_znx_dft(n, cols, tsk.size()); - let (mut tmp_a, scratch_3) = scratch_2.take_vec_znx_dft(n, 1, ci_dft.size().div_ceil(dsize)); - - { - // Performs a key-switch for each combination of s[i]*s[j], i.e. for a0, a1, a2 - // - // # Example for col=1 - // - // a0 * (-(f0s0 + f1s1 + f1s2) + s0^2, f0, f1, f2) = (-(a0f0s0 + a0f1s1 + a0f1s2) + a0s0^2, a0f0, a0f1, a0f2) - // + - // a1 * (-(g0s0 + g1s1 + g1s2) + s0s1, g0, g1, g2) = (-(a1g0s0 + a1g1s1 + a1g1s2) + a1s0s1, a1g0, a1g1, a1g2) - // + - // a2 * (-(h0s0 + h1s1 + h1s2) + s0s2, h0, h1, h2) = (-(a2h0s0 + a2h1s1 + a2h1s2) + a2s0s2, a2h0, a2h1, a2h2) - // = - // (-(x0s0 + x1s1 + x2s2) + s0(a0s0 + a1s1 + a2s2), x0, x1, x2) - for col_i in 1..cols { - let pmat: &VmpPMat<DataTsk, B> = &tsk.at(col_i - 1, col_j - 1).key.data; // Selects Enc(s[i]s[j]) - - // Extracts a[i] and multipies with Enc(s[i]s[j]) - for di in 0..dsize { - tmp_a.set_size((ci_dft.size() + di) / dsize); - - // Small optimization for dsize > 2 - // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then - // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}. - // As such we can ignore the last dsize-2 limbs safely of the sum of vmp products. - // It is possible to further ignore the last dsize-1 limbs, but this introduce - // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same - // noise is kept with respect to the ideal functionality. - tmp_dft_i.set_size(tsk.size() - ((dsize - di) as isize - 2).max(0) as usize); - - module.vec_znx_dft_copy(dsize, dsize - 1 - di, &mut tmp_a, 0, &ci_dft, col_i); - if di == 0 && col_i == 1 { - module.vmp_apply_dft_to_dft(&mut tmp_dft_i, &tmp_a, pmat, scratch_3); - } else { - module.vmp_apply_dft_to_dft_add(&mut tmp_dft_i, &tmp_a, pmat, di, scratch_3); - } - } - } - } - - // Adds -(sum a[i] * s[i]) + m) on the i-th column of tmp_idft_i - // - // (-(x0s0 + x1s1 + x2s2) + a0s0s0 + a1s0s1 + a2s0s2, x0, x1, x2) - // + - // (0, -(a0s0 + a1s1 + a2s2) + M[i], 0, 0) - // = - // (-(x0s0 + x1s1 + x2s2) + s0(a0s0 + a1s1 + a2s2), x0 -(a0s0 + a1s1 + a2s2) + M[i], x1, x2) - // = - // (-(x0s0 + x1s1 + x2s2), x0 + M[i], x1, x2) - module.vec_znx_dft_add_inplace(&mut tmp_dft_i, col_j, &ci_dft, 0); - let (mut tmp_idft, scratch_3) = scratch_2.take_vec_znx_big(n, 1, tsk.size()); - for i in 0..cols { - module.vec_znx_idft_apply_tmpa(&mut tmp_idft, 0, &mut tmp_dft_i, i); - module.vec_znx_big_normalize( - basek_in, - &mut self.at_mut(row_i, col_j).data, - i, - basek_tsk, - &tmp_idft, - 0, - scratch_3, - ); - } - } - } + self.ggsw_expand_row(res, tsk, scratch); } } + +impl<DataSelf: DataMut> GGSW<DataSelf> {}
M poulpy-core/src/keyswitching/glwe_ct.rs → poulpy-core/src/keyswitching/glwe_ct.rs

@@ -1,186 +1,179 @@

use poulpy_hal::{ api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, + ModuleN, ScratchAvailable, ScratchTakeBasic, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, }, layouts::{Backend, DataMut, DataRef, DataViewMut, Module, Scratch, VecZnx, VecZnxBig, VecZnxDft, VmpPMat, ZnxInfos}, }; -use crate::layouts::{GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, prepared::GGLWESwitchingKeyPrepared}; +use crate::{ + ScratchTakeCore, + layouts::{ + GGLWEInfos, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, LWEInfos, + prepared::{GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedToRef}, + }, +}; + +impl GLWE<Vec<u8>> { + pub fn keyswitch_tmp_bytes<M, R, A, B, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, b_infos: &B) -> usize + where + R: GLWEInfos, + A: GLWEInfos, + B: GGLWEInfos, + M: GLWEKeySwitch<BE>, + { + module.glwe_keyswitch_tmp_bytes(res_infos, a_infos, b_infos) + } +} + +impl<D: DataMut> GLWE<D> { + pub fn keyswitch<A, B, M, BE: Backend>(&mut self, module: &M, a: &A, b: &B, scratch: &mut Scratch<BE>) + where + A: GLWEToRef, + B: GLWESwitchingKeyPreparedToRef<BE>, + M: GLWEKeySwitch<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + { + module.glwe_keyswitch(self, a, b, scratch); + } -impl GLWECiphertext<Vec<u8>> { - pub fn keyswitch_scratch_space<B: Backend, OUT, IN, KEY>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - key_apply: &KEY, - ) -> usize + pub fn keyswitch_inplace<A, M, BE: Backend>(&mut self, module: &M, a: &A, scratch: &mut Scratch<BE>) where - OUT: GLWEInfos, - IN: GLWEInfos, - KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + A: GLWESwitchingKeyPreparedToRef<BE>, + M: GLWEKeySwitch<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - let in_size: usize = in_infos + module.glwe_keyswitch_inplace(self, a, scratch); + } +} + +impl<BE: Backend> GLWEKeySwitch<BE> for Module<BE> where + Self: Sized + + ModuleN + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigNormalizeTmpBytes + + VecZnxNormalizeTmpBytes + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigNormalizeTmpBytes + + VmpApplyDftToDft<BE> + + VmpApplyDftToDftAdd<BE> + + VecZnxDftApply<BE> + + VecZnxIdftApplyConsume<BE> + + VecZnxBigAddSmallInplace<BE> + + VecZnxBigNormalize<BE> + + VecZnxNormalize<BE> + + VecZnxNormalizeTmpBytes +{ +} + +pub trait GLWEKeySwitch<BE: Backend> +where + Self: Sized + + ModuleN + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigNormalizeTmpBytes + + VecZnxNormalizeTmpBytes + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigNormalizeTmpBytes + + VmpApplyDftToDft<BE> + + VmpApplyDftToDftAdd<BE> + + VecZnxDftApply<BE> + + VecZnxIdftApplyConsume<BE> + + VecZnxBigAddSmallInplace<BE> + + VecZnxBigNormalize<BE> + + VecZnxNormalize<BE> + + VecZnxNormalizeTmpBytes, +{ + fn glwe_keyswitch_tmp_bytes<R, A, B>(&self, res_infos: &R, a_infos: &A, b_infos: &B) -> usize + where + R: GLWEInfos, + A: GLWEInfos, + B: GGLWEInfos, + { + let in_size: usize = a_infos .k() - .div_ceil(key_apply.base2k()) - .div_ceil(key_apply.dsize().into()) as usize; - let out_size: usize = out_infos.size(); - let ksk_size: usize = key_apply.size(); - let res_dft: usize = module.vec_znx_dft_alloc_bytes((key_apply.rank_out() + 1).into(), ksk_size); // TODO OPTIMIZE - let ai_dft: usize = module.vec_znx_dft_alloc_bytes((key_apply.rank_in()).into(), in_size); - let vmp: usize = module.vmp_apply_dft_to_dft_tmp_bytes( + .div_ceil(b_infos.base2k()) + .div_ceil(b_infos.dsize().into()) as usize; + let out_size: usize = res_infos.size(); + let ksk_size: usize = b_infos.size(); + let res_dft: usize = self.bytes_of_vec_znx_dft((b_infos.rank_out() + 1).into(), ksk_size); // TODO OPTIMIZE + let ai_dft: usize = self.bytes_of_vec_znx_dft((b_infos.rank_in()).into(), in_size); + let vmp: usize = self.vmp_apply_dft_to_dft_tmp_bytes( out_size, in_size, in_size, - (key_apply.rank_in()).into(), - (key_apply.rank_out() + 1).into(), + (b_infos.rank_in()).into(), + (b_infos.rank_out() + 1).into(), ksk_size, - ) + module.vec_znx_dft_alloc_bytes((key_apply.rank_in()).into(), in_size); - let normalize_big: usize = module.vec_znx_big_normalize_tmp_bytes(); - if in_infos.base2k() == key_apply.base2k() { + ) + self.bytes_of_vec_znx_dft((b_infos.rank_in()).into(), in_size); + let normalize_big: usize = self.vec_znx_big_normalize_tmp_bytes(); + if a_infos.base2k() == b_infos.base2k() { res_dft + ((ai_dft + vmp) | normalize_big) - } else if key_apply.dsize() == 1 { + } else if b_infos.dsize() == 1 { // In this case, we only need one column, temporary, that we can drop once a_dft is computed. - let normalize_conv: usize = VecZnx::alloc_bytes(module.n(), 1, in_size) + module.vec_znx_normalize_tmp_bytes(); + let normalize_conv: usize = VecZnx::bytes_of(self.n(), 1, in_size) + self.vec_znx_normalize_tmp_bytes(); res_dft + (((ai_dft + normalize_conv) | vmp) | normalize_big) } else { // Since we stride over a to get a_dft when dsize > 1, we need to store the full columns of a with in the base conversion. - let normalize_conv: usize = VecZnx::alloc_bytes(module.n(), (key_apply.rank_in()).into(), in_size); - res_dft + ((ai_dft + normalize_conv + (module.vec_znx_normalize_tmp_bytes() | vmp)) | normalize_big) + let normalize_conv: usize = VecZnx::bytes_of(self.n(), (b_infos.rank_in()).into(), in_size); + res_dft + ((ai_dft + normalize_conv + (self.vec_znx_normalize_tmp_bytes() | vmp)) | normalize_big) } } - pub fn keyswitch_inplace_scratch_space<B: Backend, OUT, KEY>(module: &Module<B>, out_infos: &OUT, key_apply: &KEY) -> usize + fn glwe_keyswitch<R, A, B>(&self, res: &mut R, a: &A, b: &B, scratch: &mut Scratch<BE>) where - OUT: GLWEInfos, - KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, + R: GLWEToMut, + A: GLWEToRef, + B: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - Self::keyswitch_scratch_space(module, out_infos, out_infos, key_apply) - } -} + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GLWE<&[u8]> = &a.to_ref(); + let b: &GLWESwitchingKeyPrepared<&[u8], BE> = &b.to_ref(); -impl<DataSelf: DataRef> GLWECiphertext<DataSelf> { - #[allow(dead_code)] - pub(crate) fn assert_keyswitch<B: Backend, DataLhs, DataRhs>( - &self, - module: &Module<B>, - lhs: &GLWECiphertext<DataLhs>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &Scratch<B>, - ) where - DataLhs: DataRef, - DataRhs: DataRef, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable, - { assert_eq!( - lhs.rank(), - rhs.rank_in(), - "lhs.rank(): {} != rhs.rank_in(): {}", - lhs.rank(), - rhs.rank_in() + a.rank(), + b.rank_in(), + "a.rank(): {} != b.rank_in(): {}", + a.rank(), + b.rank_in() ); assert_eq!( - self.rank(), - rhs.rank_out(), - "self.rank(): {} != rhs.rank_out(): {}", - self.rank(), - rhs.rank_out() + res.rank(), + b.rank_out(), + "res.rank(): {} != b.rank_out(): {}", + res.rank(), + b.rank_out() ); - assert_eq!(rhs.n(), self.n()); - assert_eq!(lhs.n(), self.n()); - let scrach_needed: usize = GLWECiphertext::keyswitch_scratch_space(module, self, lhs, rhs); + assert_eq!(res.n(), self.n() as u32); + assert_eq!(a.n(), self.n() as u32); + assert_eq!(b.n(), self.n() as u32); - assert!( - scratch.available() >= scrach_needed, - "scratch.available()={} < GLWECiphertext::keyswitch_scratch_space( - module, - self.base2k(), - self.k(), - lhs.base2k(), - lhs.k(), - rhs.base2k(), - rhs.k(), - rhs.dsize(), - rhs.rank_in(), - rhs.rank_out(), - )={scrach_needed}", - scratch.available(), - ); - } - - #[allow(dead_code)] - pub(crate) fn assert_keyswitch_inplace<B: Backend, DataRhs>( - &self, - module: &Module<B>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &Scratch<B>, - ) where - DataRhs: DataRef, - Module<B>: VecZnxDftAllocBytes + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable, - { - assert_eq!( - self.rank(), - rhs.rank_out(), - "self.rank(): {} != rhs.rank_out(): {}", - self.rank(), - rhs.rank_out() - ); - - assert_eq!(rhs.n(), self.n()); - - let scrach_needed: usize = GLWECiphertext::keyswitch_inplace_scratch_space(module, self, rhs); + let scrach_needed: usize = self.glwe_keyswitch_tmp_bytes(res, a, b); assert!( scratch.available() >= scrach_needed, - "scratch.available()={} < GLWECiphertext::keyswitch_scratch_space()={scrach_needed}", + "scratch.available()={} < glwe_keyswitch_tmp_bytes={scrach_needed}", scratch.available(), ); - } -} -impl<DataSelf: DataMut> GLWECiphertext<DataSelf> { - pub fn keyswitch<DataLhs: DataRef, DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - glwe_in: &GLWECiphertext<DataLhs>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnx, - { - #[cfg(debug_assertions)] - { - self.assert_keyswitch(module, glwe_in, rhs, scratch); - } + let basek_out: usize = res.base2k().into(); + let base2k_out: usize = b.base2k().into(); - let basek_out: usize = self.base2k().into(); - let basek_ksk: usize = rhs.base2k().into(); - - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // Todo optimise - let res_big: VecZnxBig<_, B> = glwe_in.keyswitch_internal(module, res_dft, rhs, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_normalize( + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), b.size()); // Todo optimise + let res_big: VecZnxBig<&mut [u8], BE> = keyswitch_internal(self, res_dft, a, b, scratch_1); + (0..(res.rank() + 1).into()).for_each(|i| { + self.vec_znx_big_normalize( basek_out, - &mut self.data, + &mut res.data, i, - basek_ksk, + base2k_out, &res_big, i, scratch_1,

@@ -188,42 +181,52 @@ );

}) } - pub fn keyswitch_inplace<DataRhs: DataRef, B: Backend>( - &mut self, - module: &Module<B>, - rhs: &GGLWESwitchingKeyPrepared<DataRhs, B>, - scratch: &mut Scratch<B>, - ) where - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDftTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes, - Scratch<B>: ScratchAvailable + TakeVecZnxDft<B> + TakeVecZnx, + fn glwe_keyswitch_inplace<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<BE>) + where + R: GLWEToMut, + A: GLWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - self.assert_keyswitch_inplace(module, rhs, scratch); - } + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let a: &GLWESwitchingKeyPrepared<&[u8], BE> = &a.to_ref(); - let basek_in: usize = self.base2k().into(); - let basek_ksk: usize = rhs.base2k().into(); + assert_eq!( + res.rank(), + a.rank_in(), + "res.rank(): {} != a.rank_in(): {}", + res.rank(), + a.rank_in() + ); + assert_eq!( + res.rank(), + a.rank_out(), + "res.rank(): {} != b.rank_out(): {}", + res.rank(), + a.rank_out() + ); + + assert_eq!(res.n(), self.n() as u32); + assert_eq!(a.n(), self.n() as u32); + + let scrach_needed: usize = self.glwe_keyswitch_tmp_bytes(res, res, a); + + assert!( + scratch.available() >= scrach_needed, + "scratch.available()={} < glwe_keyswitch_tmp_bytes={scrach_needed}", + scratch.available(), + ); - let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self.n().into(), (self.rank() + 1).into(), rhs.size()); // Todo optimise - let res_big: VecZnxBig<_, B> = self.keyswitch_internal(module, res_dft, rhs, scratch_1); - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_big_normalize( - basek_in, - &mut self.data, + let base2k_in: usize = res.base2k().into(); + let base2k_out: usize = a.base2k().into(); + + let (res_dft, scratch_1) = scratch.take_vec_znx_dft(self, (res.rank() + 1).into(), a.size()); // Todo optimise + let res_big: VecZnxBig<&mut [u8], BE> = keyswitch_internal(self, res_dft, res, a, scratch_1); + (0..(res.rank() + 1).into()).for_each(|i| { + self.vec_znx_big_normalize( + base2k_in, + &mut res.data, i, - basek_ksk, + base2k_out, &res_big, i, scratch_1,

@@ -232,183 +235,136 @@ })

} } -impl<D: DataRef> GLWECiphertext<D> { - pub(crate) fn keyswitch_internal<B: Backend, DataRes, DataKey>( - &self, - module: &Module<B>, - res_dft: VecZnxDft<DataRes, B>, - rhs: &GGLWESwitchingKeyPrepared<DataKey, B>, - scratch: &mut Scratch<B>, - ) -> VecZnxBig<DataRes, B> - where - DataRes: DataMut, - DataKey: DataRef, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDftTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnx, - { - if rhs.dsize() == 1 { - return keyswitch_vmp_one_digit( - module, - self.base2k().into(), - rhs.base2k().into(), - res_dft, - &self.data, - &rhs.key.data, - scratch, - ); - } +impl GLWE<Vec<u8>> {} - keyswitch_vmp_multiple_digits( - module, - self.base2k().into(), - rhs.base2k().into(), - res_dft, - &self.data, - &rhs.key.data, - rhs.dsize().into(), - scratch, - ) - } -} +impl<DataSelf: DataMut> GLWE<DataSelf> {} -fn keyswitch_vmp_one_digit<B: Backend, DataRes, DataIn, DataVmp>( - module: &Module<B>, - basek_in: usize, - basek_ksk: usize, - mut res_dft: VecZnxDft<DataRes, B>, - a: &VecZnx<DataIn>, - mat: &VmpPMat<DataVmp, B>, - scratch: &mut Scratch<B>, -) -> VecZnxBig<DataRes, B> +fn keyswitch_internal<BE: Backend, M, DR, DA, DB>( + module: &M, + mut res: VecZnxDft<DR, BE>, + a: &GLWE<DA>, + b: &GLWESwitchingKeyPrepared<DB, BE>, + scratch: &mut Scratch<BE>, +) -> VecZnxBig<DR, BE> where - DataRes: DataMut, - DataIn: DataRef, - DataVmp: DataRef, - Module<B>: VecZnxDftAllocBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnx, + DR: DataMut, + DA: DataRef, + DB: DataRef, + M: ModuleN + + VecZnxDftBytesOf + + VmpApplyDftToDftTmpBytes + + VecZnxBigNormalizeTmpBytes + + VmpApplyDftToDftTmpBytes + + VmpApplyDftToDft<BE> + + VmpApplyDftToDftAdd<BE> + + VecZnxDftApply<BE> + + VecZnxIdftApplyConsume<BE> + + VecZnxBigAddSmallInplace<BE> + + VecZnxBigNormalize<BE> + + VecZnxNormalize<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - let cols: usize = a.cols(); + let base2k_in: usize = a.base2k().into(); + let base2k_out: usize = b.base2k().into(); + let cols: usize = (a.rank() + 1).into(); + let a_size: usize = (a.size() * base2k_in).div_ceil(base2k_out); + let pmat: &VmpPMat<DB, BE> = &b.key.data; - let a_size: usize = (a.size() * basek_in).div_ceil(basek_ksk); - let (mut ai_dft, scratch_1) = scratch.take_vec_znx_dft(a.n(), cols - 1, a.size()); + if b.dsize() == 1 { + let (mut ai_dft, scratch_1) = scratch.take_vec_znx_dft(module, cols - 1, a.size()); - if basek_in == basek_ksk { - (0..cols - 1).for_each(|col_i| { - module.vec_znx_dft_apply(1, 0, &mut ai_dft, col_i, a, col_i + 1); - }); + if base2k_in == base2k_out { + (0..cols - 1).for_each(|col_i| { + module.vec_znx_dft_apply(1, 0, &mut ai_dft, col_i, a.data(), col_i + 1); + }); + } else { + let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(module, 1, a_size); + (0..cols - 1).for_each(|col_i| { + module.vec_znx_normalize( + base2k_out, + &mut a_conv, + 0, + base2k_in, + a.data(), + col_i + 1, + scratch_2, + ); + module.vec_znx_dft_apply(1, 0, &mut ai_dft, col_i, &a_conv, 0); + }); + } + + module.vmp_apply_dft_to_dft(&mut res, &ai_dft, pmat, scratch_1); } else { - let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(a.n(), 1, a_size); - (0..cols - 1).for_each(|col_i| { - module.vec_znx_normalize(basek_ksk, &mut a_conv, 0, basek_in, a, col_i + 1, scratch_2); - module.vec_znx_dft_apply(1, 0, &mut ai_dft, col_i, &a_conv, 0); - }); - } + let dsize: usize = b.dsize().into(); - module.vmp_apply_dft_to_dft(&mut res_dft, &ai_dft, mat, scratch_1); - let mut res_big: VecZnxBig<DataRes, B> = module.vec_znx_idft_apply_consume(res_dft); - module.vec_znx_big_add_small_inplace(&mut res_big, 0, a, 0); - res_big -} + let (mut ai_dft, scratch_1) = scratch.take_vec_znx_dft(module, cols - 1, a_size.div_ceil(dsize)); + ai_dft.data_mut().fill(0); -#[allow(clippy::too_many_arguments)] -fn keyswitch_vmp_multiple_digits<B: Backend, DataRes, DataIn, DataVmp>( - module: &Module<B>, - basek_in: usize, - basek_ksk: usize, - mut res_dft: VecZnxDft<DataRes, B>, - a: &VecZnx<DataIn>, - mat: &VmpPMat<DataVmp, B>, - dsize: usize, - scratch: &mut Scratch<B>, -) -> VecZnxBig<DataRes, B> -where - DataRes: DataMut, - DataIn: DataRef, - DataVmp: DataRef, - Module<B>: VecZnxDftAllocBytes - + VecZnxDftApply<B> - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnx, -{ - let cols: usize = a.cols(); - let a_size: usize = (a.size() * basek_in).div_ceil(basek_ksk); - let (mut ai_dft, scratch_1) = scratch.take_vec_znx_dft(a.n(), cols - 1, a_size.div_ceil(dsize)); - ai_dft.data_mut().fill(0); + if base2k_in == base2k_out { + for di in 0..dsize { + ai_dft.set_size((a_size + di) / dsize); - if basek_in == basek_ksk { - for di in 0..dsize { - ai_dft.set_size((a_size + di) / dsize); + // Small optimization for dsize > 2 + // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then + // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}. + // As such we can ignore the last dsize-2 limbs safely of the sum of vmp products. + // It is possible to further ignore the last dsize-1 limbs, but this introduce + // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same + // noise is kept with respect to the ideal functionality. + res.set_size(pmat.size() - ((dsize - di) as isize - 2).max(0) as usize); - // Small optimization for dsize > 2 - // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then - // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}. - // As such we can ignore the last dsize-2 limbs safely of the sum of vmp products. - // It is possible to further ignore the last dsize-1 limbs, but this introduce - // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same - // noise is kept with respect to the ideal functionality. - res_dft.set_size(mat.size() - ((dsize - di) as isize - 2).max(0) as usize); + for j in 0..cols - 1 { + module.vec_znx_dft_apply(dsize, dsize - di - 1, &mut ai_dft, j, a.data(), j + 1); + } + if di == 0 { + module.vmp_apply_dft_to_dft(&mut res, &ai_dft, pmat, scratch_1); + } else { + module.vmp_apply_dft_to_dft_add(&mut res, &ai_dft, pmat, di, scratch_1); + } + } + } else { + let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(module, cols - 1, a_size); for j in 0..cols - 1 { - module.vec_znx_dft_apply(dsize, dsize - di - 1, &mut ai_dft, j, a, j + 1); + module.vec_znx_normalize( + base2k_out, + &mut a_conv, + j, + base2k_in, + a.data(), + j + 1, + scratch_2, + ); } - if di == 0 { - module.vmp_apply_dft_to_dft(&mut res_dft, &ai_dft, mat, scratch_1); - } else { - module.vmp_apply_dft_to_dft_add(&mut res_dft, &ai_dft, mat, di, scratch_1); - } - } - } else { - let (mut a_conv, scratch_2) = scratch_1.take_vec_znx(a.n(), cols - 1, a_size); - for j in 0..cols - 1 { - module.vec_znx_normalize(basek_ksk, &mut a_conv, j, basek_in, a, j + 1, scratch_2); - } + for di in 0..dsize { + ai_dft.set_size((a_size + di) / dsize); - for di in 0..dsize { - ai_dft.set_size((a_size + di) / dsize); + // Small optimization for dsize > 2 + // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then + // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}. + // As such we can ignore the last dsize-2 limbs safely of the sum of vmp products. + // It is possible to further ignore the last dsize-1 limbs, but this introduce + // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same + // noise is kept with respect to the ideal functionality. + res.set_size(pmat.size() - ((dsize - di) as isize - 2).max(0) as usize); - // Small optimization for dsize > 2 - // VMP produce some error e, and since we aggregate vmp * 2^{di * B}, then - // we also aggregate ei * 2^{di * B}, with the largest error being ei * 2^{(dsize-1) * B}. - // As such we can ignore the last dsize-2 limbs safely of the sum of vmp products. - // It is possible to further ignore the last dsize-1 limbs, but this introduce - // ~0.5 to 1 bit of additional noise, and thus not chosen here to ensure that the same - // noise is kept with respect to the ideal functionality. - res_dft.set_size(mat.size() - ((dsize - di) as isize - 2).max(0) as usize); - - for j in 0..cols - 1 { - module.vec_znx_dft_apply(dsize, dsize - di - 1, &mut ai_dft, j, &a_conv, j); - } + for j in 0..cols - 1 { + module.vec_znx_dft_apply(dsize, dsize - di - 1, &mut ai_dft, j, &a_conv, j); + } - if di == 0 { - module.vmp_apply_dft_to_dft(&mut res_dft, &ai_dft, mat, scratch_2); - } else { - module.vmp_apply_dft_to_dft_add(&mut res_dft, &ai_dft, mat, di, scratch_2); + if di == 0 { + module.vmp_apply_dft_to_dft(&mut res, &ai_dft, pmat, scratch_2); + } else { + module.vmp_apply_dft_to_dft_add(&mut res, &ai_dft, pmat, di, scratch_2); + } } } + + res.set_size(res.max_size()); } - res_dft.set_size(res_dft.max_size()); - let mut res_big: VecZnxBig<DataRes, B> = module.vec_znx_idft_apply_consume(res_dft); - module.vec_znx_big_add_small_inplace(&mut res_big, 0, a, 0); + let mut res_big: VecZnxBig<DR, BE> = module.vec_znx_idft_apply_consume(res); + module.vec_znx_big_add_small_inplace(&mut res_big, 0, a.data(), 0); res_big }
M poulpy-core/src/keyswitching/lwe_ct.rs → poulpy-core/src/keyswitching/lwe_ct.rs

@@ -1,116 +1,116 @@

use poulpy_hal::{ - api::{ - ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeTmpBytes, - VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, - }, - layouts::{Backend, DataMut, DataRef, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero}, + api::ScratchAvailable, + layouts::{Backend, DataMut, Module, Scratch, ZnxView, ZnxViewMut, ZnxZero}, }; use crate::{ - TakeGLWECt, + ScratchTakeCore, + keyswitching::glwe_ct::GLWEKeySwitch, layouts::{ - GGLWEInfos, GLWECiphertext, GLWECiphertextLayout, LWECiphertext, LWEInfos, Rank, TorusPrecision, - prepared::LWESwitchingKeyPrepared, + GGLWEInfos, GLWE, GLWEAlloc, GLWELayout, LWE, LWEInfos, LWEToMut, LWEToRef, Rank, TorusPrecision, + prepared::{LWESwitchingKeyPrepared, LWESwitchingKeyPreparedToRef}, }, }; -impl LWECiphertext<Vec<u8>> { - pub fn keyswitch_scratch_space<B: Backend, OUT, IN, KEY>( - module: &Module<B>, - out_infos: &OUT, - in_infos: &IN, - key_infos: &KEY, - ) -> usize +impl LWE<Vec<u8>> { + pub fn keyswitch_tmp_bytes<M, R, A, K, BE: Backend>(module: &M, res_infos: &R, a_infos: &A, key_infos: &K) -> usize + where + R: LWEInfos, + A: LWEInfos, + K: GGLWEInfos, + M: LWEKeySwitch<BE>, + { + module.lwe_keyswitch_tmp_bytes(res_infos, a_infos, key_infos) + } +} + +impl<D: DataMut> LWE<D> { + pub fn keyswitch<M, A, K, BE: Backend>(&mut self, module: &M, a: &A, ksk: &K, scratch: &mut Scratch<BE>) + where + A: LWEToRef, + K: LWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, + M: LWEKeySwitch<BE>, + { + module.lwe_keyswitch(self, a, ksk, scratch); + } +} + +impl<BE: Backend> LWEKeySwitch<BE> for Module<BE> where Self: LWEKeySwitch<BE> {} + +pub trait LWEKeySwitch<BE: Backend> +where + Self: GLWEKeySwitch<BE> + GLWEAlloc, +{ + fn lwe_keyswitch_tmp_bytes<R, A, K>(&self, res_infos: &R, a_infos: &A, key_infos: &K) -> usize where - OUT: LWEInfos, - IN: LWEInfos, - KEY: GGLWEInfos, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDftTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalizeTmpBytes, + R: LWEInfos, + A: LWEInfos, + K: GGLWEInfos, { - let max_k: TorusPrecision = in_infos.k().max(out_infos.k()); + let max_k: TorusPrecision = a_infos.k().max(res_infos.k()); - let glwe_in_infos: GLWECiphertextLayout = GLWECiphertextLayout { - n: module.n().into(), - base2k: in_infos.base2k(), + let glwe_a_infos: GLWELayout = GLWELayout { + n: self.ring_degree(), + base2k: a_infos.base2k(), k: max_k, rank: Rank(1), }; - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { - n: module.n().into(), - base2k: out_infos.base2k(), + let glwe_res_infos: GLWELayout = GLWELayout { + n: self.ring_degree(), + base2k: res_infos.base2k(), k: max_k, rank: Rank(1), }; - let glwe_in: usize = GLWECiphertext::alloc_bytes(&glwe_in_infos); - let glwe_out: usize = GLWECiphertext::alloc_bytes(&glwe_out_infos); - let ks: usize = GLWECiphertext::keyswitch_scratch_space(module, &glwe_out_infos, &glwe_in_infos, key_infos); + let glwe_in: usize = GLWE::bytes_of_from_infos(self, &glwe_a_infos); + let glwe_out: usize = GLWE::bytes_of_from_infos(self, &glwe_res_infos); + let ks: usize = self.glwe_keyswitch_tmp_bytes(&glwe_res_infos, &glwe_a_infos, key_infos); glwe_in + glwe_out + ks } -} -impl<DLwe: DataMut> LWECiphertext<DLwe> { - pub fn keyswitch<A, DKs, B: Backend>( - &mut self, - module: &Module<B>, - a: &LWECiphertext<A>, - ksk: &LWESwitchingKeyPrepared<DKs, B>, - scratch: &mut Scratch<B>, - ) where - A: DataRef, - DKs: DataRef, - Module<B>: VecZnxDftAllocBytes - + VmpApplyDftToDftTmpBytes - + VecZnxBigNormalizeTmpBytes - + VmpApplyDftToDft<B> - + VmpApplyDftToDftAdd<B> - + VecZnxDftApply<B> - + VecZnxIdftApplyConsume<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxBigNormalize<B> - + VecZnxNormalize<B> - + VecZnxNormalizeTmpBytes - + VecZnxCopy, - Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx, + fn lwe_keyswitch<R, A, K>(&self, res: &mut R, a: &A, ksk: &K, scratch: &mut Scratch<BE>) + where + R: LWEToMut, + A: LWEToRef, + K: LWESwitchingKeyPreparedToRef<BE>, + Scratch<BE>: ScratchTakeCore<BE>, { - #[cfg(debug_assertions)] - { - assert!(self.n() <= module.n() as u32); - assert!(a.n() <= module.n() as u32); - assert!(scratch.available() >= LWECiphertext::keyswitch_scratch_space(module, self, a, ksk)); - } + let res: &mut LWE<&mut [u8]> = &mut res.to_mut(); + let a: &LWE<&[u8]> = &a.to_ref(); + let ksk: &LWESwitchingKeyPrepared<&[u8], BE> = &ksk.to_ref(); + + assert!(res.n().as_usize() <= self.n()); + assert!(a.n().as_usize() <= self.n()); + assert_eq!(ksk.n(), self.n() as u32); + assert!(scratch.available() >= self.lwe_keyswitch_tmp_bytes(res, a, ksk)); - let max_k: TorusPrecision = self.k().max(a.k()); + let max_k: TorusPrecision = res.k().max(a.k()); let a_size: usize = a.k().div_ceil(ksk.base2k()) as usize; - let (mut glwe_in, scratch_1) = scratch.take_glwe_ct(&GLWECiphertextLayout { - n: ksk.n(), - base2k: a.base2k(), - k: max_k, - rank: Rank(1), - }); + let (mut glwe_in, scratch_1) = scratch.take_glwe_ct( + self, + &GLWELayout { + n: ksk.n(), + base2k: a.base2k(), + k: max_k, + rank: Rank(1), + }, + ); glwe_in.data.zero(); - let (mut glwe_out, scratch_1) = scratch_1.take_glwe_ct(&GLWECiphertextLayout { - n: ksk.n(), - base2k: self.base2k(), - k: max_k, - rank: Rank(1), - }); + let (mut glwe_out, scratch_1) = scratch_1.take_glwe_ct( + self, + &GLWELayout { + n: ksk.n(), + base2k: res.base2k(), + k: max_k, + rank: Rank(1), + }, + ); let n_lwe: usize = a.n().into();

@@ -120,7 +120,7 @@ glwe_in.data.at_mut(0, i)[0] = data_lwe[0];

glwe_in.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]); } - glwe_out.keyswitch(module, &glwe_in, &ksk.0, scratch_1); - self.sample_extract(&glwe_out); + self.glwe_keyswitch(&mut glwe_out, &glwe_in, &ksk.0, scratch_1); + res.sample_extract(&glwe_out); } }
M poulpy-core/src/layouts/compressed/gglwe_atk.rs → poulpy-core/src/layouts/compressed/gglwe_atk.rs

@@ -1,24 +1,28 @@

use poulpy_hal::{ - api::{VecZnxCopy, VecZnxFillUniform}, layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - compressed::{Decompress, GGLWESwitchingKeyCompressed}, + AutomorphismKey, AutomorphismKeyToMut, Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, + TorusPrecision, + compressed::{ + GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut, + GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress, + }, + prepared::{GetAutomorphismGaloisElement, SetAutomorphismGaloisElement}, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct GGLWEAutomorphismKeyCompressed<D: Data> { - pub(crate) key: GGLWESwitchingKeyCompressed<D>, +pub struct AutomorphismKeyCompressed<D: Data> { + pub(crate) key: GLWESwitchingKeyCompressed<D>, pub(crate) p: i64, } -impl<D: Data> LWEInfos for GGLWEAutomorphismKeyCompressed<D> { - fn n(&self) -> Degree { +impl<D: Data> LWEInfos for AutomorphismKeyCompressed<D> { + fn n(&self) -> RingDegree { self.key.n() }

@@ -34,13 +38,13 @@ fn size(&self) -> usize {

self.key.size() } } -impl<D: Data> GLWEInfos for GGLWEAutomorphismKeyCompressed<D> { +impl<D: Data> GLWEInfos for AutomorphismKeyCompressed<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWEAutomorphismKeyCompressed<D> { +impl<D: Data> GGLWEInfos for AutomorphismKeyCompressed<D> { fn rank_in(&self) -> Rank { self.key.rank_in() }

@@ -58,76 +62,185 @@ self.key.dnum()

} } -impl<D: DataRef> fmt::Debug for GGLWEAutomorphismKeyCompressed<D> { +impl<D: DataRef> fmt::Debug for AutomorphismKeyCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWEAutomorphismKeyCompressed<D> { +impl<D: DataMut> FillUniform for AutomorphismKeyCompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.key.fill_uniform(log_bound, source); } } -impl<D: DataRef> fmt::Display for GGLWEAutomorphismKeyCompressed<D> { +impl<D: DataRef> fmt::Display for AutomorphismKeyCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(AutomorphismKeyCompressed: p={}) {}", self.p, self.key) } } -impl GGLWEAutomorphismKeyCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait AutomorphismKeyCompressedAlloc +where + Self: GLWESwitchingKeyCompressedAlloc, +{ + fn alloc_automorphism_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> AutomorphismKeyCompressed<Vec<u8>> { + AutomorphismKeyCompressed { + key: self.alloc_glwe_switching_key_compressed(base2k, k, rank, rank, dnum, dsize), + p: 0, + } + } + + fn alloc_automorphism_key_compressed_from_infos<A>(&self, infos: &A) -> AutomorphismKeyCompressed<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!(infos.rank_in(), infos.rank_out()); - Self { - key: GGLWESwitchingKeyCompressed::alloc(infos), - p: 0, - } + assert_eq!(infos.rank_in(), infos.rank_out()); + self.alloc_automorphism_key_compressed( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) + } + + fn bytes_of_automorphism_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize { + self.bytes_of_glwe_switching_key_compressed(base2k, k, rank, dnum, dsize) + } + + fn bytes_of_automorphism_key_compressed_from_infos<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + assert_eq!(infos.rank_in(), infos.rank_out()); + self.bytes_of_automorphism_key_compressed( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) + } +} + +impl AutomorphismKeyCompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: AutomorphismKeyCompressedAlloc, + { + module.alloc_automorphism_key_compressed_from_infos(infos) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self { - Self { - key: GGLWESwitchingKeyCompressed::alloc_with(n, base2k, k, rank, rank, dnum, dsize), - p: 0, - } + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: AutomorphismKeyCompressedAlloc, + { + module.alloc_automorphism_key_compressed(base2k, k, rank, dnum, dsize) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GGLWEInfos, + M: AutomorphismKeyCompressedAlloc, { - debug_assert_eq!(infos.rank_in(), infos.rank_out()); - GGLWESwitchingKeyCompressed::alloc_bytes(infos) + module.bytes_of_automorphism_key_compressed_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { - GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rank, dnum, dsize) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: AutomorphismKeyCompressedAlloc, + { + module.bytes_of_automorphism_key_compressed(base2k, k, rank, dnum, dsize) } } -impl<D: DataMut> ReaderFrom for GGLWEAutomorphismKeyCompressed<D> { +impl<D: DataMut> ReaderFrom for AutomorphismKeyCompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.p = reader.read_u64::<LittleEndian>()? as i64; self.key.read_from(reader) } } -impl<D: DataRef> WriterTo for GGLWEAutomorphismKeyCompressed<D> { +impl<D: DataRef> WriterTo for AutomorphismKeyCompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::<LittleEndian>(self.p as u64)?; self.key.write_to(writer) } } -impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWEAutomorphismKeyCompressed<DR>> for GGLWEAutomorphismKey<D> +pub trait AutomorphismKeyDecompress where - Module<B>: VecZnxFillUniform + VecZnxCopy, + Self: GLWESwitchingKeyDecompress, { - fn decompress(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKeyCompressed<DR>) { - self.key.decompress(module, &other.key); - self.p = other.p; + fn decompress_automorphism_key<R, O>(&self, res: &mut R, other: &O) + where + R: AutomorphismKeyToMut + SetAutomorphismGaloisElement, + O: AutomorphismKeyCompressedToRef + GetAutomorphismGaloisElement, + { + self.decompress_glwe_switching_key(&mut res.to_mut().key, &other.to_ref().key); + res.set_p(other.p()); + } +} + +impl<B: Backend> AutomorphismKeyDecompress for Module<B> where Self: AutomorphismKeyDecompress {} + +impl<D: DataMut> AutomorphismKey<D> +where + Self: SetAutomorphismGaloisElement, +{ + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: AutomorphismKeyCompressedToRef + GetAutomorphismGaloisElement, + M: AutomorphismKeyDecompress, + { + module.decompress_automorphism_key(self, other); + } +} + +pub trait AutomorphismKeyCompressedToRef { + fn to_ref(&self) -> AutomorphismKeyCompressed<&[u8]>; +} + +impl<D: DataRef> AutomorphismKeyCompressedToRef for AutomorphismKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef, +{ + fn to_ref(&self) -> AutomorphismKeyCompressed<&[u8]> { + AutomorphismKeyCompressed { + key: self.key.to_ref(), + p: self.p, + } + } +} + +pub trait AutomorphismKeyCompressedToMut { + fn to_mut(&mut self) -> AutomorphismKeyCompressed<&mut [u8]>; +} + +impl<D: DataMut> AutomorphismKeyCompressedToMut for AutomorphismKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut, +{ + fn to_mut(&mut self) -> AutomorphismKeyCompressed<&mut [u8]> { + AutomorphismKeyCompressed { + p: self.p, + key: self.key.to_mut(), + } } }
M poulpy-core/src/layouts/compressed/gglwe_ct.rs → poulpy-core/src/layouts/compressed/gglwe_ct.rs

@@ -1,18 +1,20 @@

use poulpy_hal::{ api::{VecZnxCopy, VecZnxFillUniform}, - layouts::{Backend, Data, DataMut, DataRef, FillUniform, MatZnx, Module, ReaderFrom, WriterTo, ZnxInfos}, + layouts::{ + Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos, + }, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - compressed::{Decompress, GLWECiphertextCompressed}, + Base2K, Dnum, Dsize, GGLWE, GGLWEInfos, GGLWEToMut, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision, + compressed::{GLWECompressed, GLWEDecompress}, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct GGLWECiphertextCompressed<D: Data> { +pub struct GGLWECompressed<D: Data> { pub(crate) data: MatZnx<D>, pub(crate) base2k: Base2K, pub(crate) k: TorusPrecision,

@@ -21,9 +23,9 @@ pub(crate) dsize: Dsize,

pub(crate) seed: Vec<[u8; 32]>, } -impl<D: Data> LWEInfos for GGLWECiphertextCompressed<D> { - fn n(&self) -> Degree { - Degree(self.data.n() as u32) +impl<D: Data> LWEInfos for GGLWECompressed<D> { + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn base2k(&self) -> Base2K {

@@ -38,13 +40,13 @@ fn size(&self) -> usize {

self.data.size() } } -impl<D: Data> GLWEInfos for GGLWECiphertextCompressed<D> { +impl<D: Data> GLWEInfos for GGLWECompressed<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWECiphertextCompressed<D> { +impl<D: Data> GGLWEInfos for GGLWECompressed<D> { fn rank_in(&self) -> Rank { Rank(self.data.cols_in() as u32) }

@@ -62,53 +64,41 @@ Dnum(self.data.rows() as u32)

} } -impl<D: DataRef> fmt::Debug for GGLWECiphertextCompressed<D> { +impl<D: DataRef> fmt::Debug for GGLWECompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWECiphertextCompressed<D> { +impl<D: DataMut> FillUniform for GGLWECompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl<D: DataRef> fmt::Display for GGLWECiphertextCompressed<D> { +impl<D: DataRef> fmt::Display for GGLWECompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "(GGLWECiphertextCompressed: base2k={} k={} dsize={}) {}", + "(GGLWECompressed: base2k={} k={} dsize={}) {}", self.base2k.0, self.k.0, self.dsize.0, self.data ) } } -impl GGLWECiphertextCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: GGLWEInfos, - { - Self::alloc_with( - infos.n(), - infos.base2k(), - infos.k(), - infos.rank_in(), - infos.rank_out(), - infos.dnum(), - infos.dsize(), - ) - } - - pub fn alloc_with( - n: Degree, +pub trait GGLWECompressedAlloc +where + Self: GetRingDegree, +{ + fn alloc_gglwe_compressed( + &self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> Self { + ) -> GGLWECompressed<Vec<u8>> { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -123,9 +113,9 @@ dnum.0,

dsize.0, ); - Self { + GGLWECompressed { data: MatZnx::alloc( - n.into(), + self.ring_degree().into(), dnum.into(), rank_in.into(), 1,

@@ -139,21 +129,22 @@ seed: vec![[0u8; 32]; (dnum.0 * rank_in.0) as usize],

} } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn alloc_gglwe_compressed_from_infos<A>(&self, infos: &A) -> GGLWECompressed<Vec<u8>> where A: GGLWEInfos, { - Self::alloc_bytes_with( - infos.n(), + assert_eq!(infos.n(), self.ring_degree()); + self.alloc_gglwe_compressed( infos.base2k(), infos.k(), infos.rank_in(), + infos.rank_out(), infos.dnum(), infos.dsize(), ) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize { + fn bytes_of_gglwe_compressed(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -168,20 +159,76 @@ dnum.0,

dsize.0, ); - MatZnx::alloc_bytes( - n.into(), + MatZnx::bytes_of( + self.ring_degree().into(), dnum.into(), rank_in.into(), 1, k.0.div_ceil(base2k.0) as usize, ) + } + + fn bytes_of_gglwe_compressed_from_infos<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + assert_eq!(infos.n(), self.ring_degree()); + self.bytes_of_gglwe_compressed( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.dnum(), + infos.dsize(), + ) + } +} + +impl<B: Backend> GGLWECompressedAlloc for Module<B> where Self: GetRingDegree {} + +impl GGLWECompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GGLWECompressedAlloc, + { + module.alloc_gglwe_compressed_from_infos(infos) + } + + pub fn alloc<M>( + module: &M, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> Self + where + M: GGLWECompressedAlloc, + { + module.alloc_gglwe_compressed(base2k, k, rank_in, rank_out, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GGLWECompressedAlloc, + { + module.bytes_of_gglwe_compressed_from_infos(infos) + } + + pub fn byte_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: GGLWECompressedAlloc, + { + module.bytes_of_gglwe_compressed(base2k, k, rank_in, dnum, dsize) } } -impl<D: DataRef> GGLWECiphertextCompressed<D> { - pub(crate) fn at(&self, row: usize, col: usize) -> GLWECiphertextCompressed<&[u8]> { +impl<D: DataRef> GGLWECompressed<D> { + pub(crate) fn at(&self, row: usize, col: usize) -> GLWECompressed<&[u8]> { let rank_in: usize = self.rank_in().into(); - GLWECiphertextCompressed { + GLWECompressed { data: self.data.at(row, col), k: self.k, base2k: self.base2k,

@@ -191,10 +238,10 @@ }

} } -impl<D: DataMut> GGLWECiphertextCompressed<D> { - pub(crate) fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertextCompressed<&mut [u8]> { +impl<D: DataMut> GGLWECompressed<D> { + pub(crate) fn at_mut(&mut self, row: usize, col: usize) -> GLWECompressed<&mut [u8]> { let rank_in: usize = self.rank_in().into(); - GLWECiphertextCompressed { + GLWECompressed { k: self.k, base2k: self.base2k, rank: self.rank_out,

@@ -204,7 +251,7 @@ }

} } -impl<D: DataMut> ReaderFrom for GGLWECiphertextCompressed<D> { +impl<D: DataMut> ReaderFrom for GGLWECompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -219,7 +266,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for GGLWECiphertextCompressed<D> { +impl<D: DataRef> WriterTo for GGLWECompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.into())?; writer.write_u32::<LittleEndian>(self.base2k.into())?;

@@ -233,59 +280,73 @@ self.data.write_to(writer)

} } -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGLWECiphertextCompressed<DR>> for GGLWECiphertext<D> +pub trait GGLWEDecompress where - Module<B>: VecZnxFillUniform + VecZnxCopy, + Self: GLWEDecompress, { - fn decompress(&mut self, module: &Module<B>, other: &GGLWECiphertextCompressed<DR>) { - #[cfg(debug_assertions)] - { - assert_eq!( - self.n(), - other.n(), - "invalid receiver: self.n()={} != other.n()={}", - self.n(), - other.n() - ); - assert_eq!( - self.size(), - other.size(), - "invalid receiver: self.size()={} != other.size()={}", - self.size(), - other.size() - ); - assert_eq!( - self.rank_in(), - other.rank_in(), - "invalid receiver: self.rank_in()={} != other.rank_in()={}", - self.rank_in(), - other.rank_in() - ); - assert_eq!( - self.rank_out(), - other.rank_out(), - "invalid receiver: self.rank_out()={} != other.rank_out()={}", - self.rank_out(), - other.rank_out() - ); + fn decompress_gglwe<R, O>(&self, res: &mut R, other: &O) + where + R: GGLWEToMut, + O: GGLWECompressedToRef, + { + let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut(); + let other: &GGLWECompressed<&[u8]> = &other.to_ref(); - assert_eq!( - self.dnum(), - other.dnum(), - "invalid receiver: self.dnum()={} != other.dnum()={}", - self.dnum(), - other.dnum() - ); + assert_eq!(res.gglwe_layout(), other.gglwe_layout()); + + let rank_in: usize = res.rank_in().into(); + let dnum: usize = res.dnum().into(); + + for row_i in 0..dnum { + for col_i in 0..rank_in { + self.decompress_glwe(&mut res.at_mut(row_i, col_i), &other.at(row_i, col_i)); + } + } + } +} + +impl<B: Backend> GGLWEDecompress for Module<B> where Self: VecZnxFillUniform + VecZnxCopy {} + +impl<D: DataMut> GGLWE<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: GGLWECompressedToRef, + M: GGLWEDecompress, + { + module.decompress_gglwe(self, other); + } +} + +pub trait GGLWECompressedToMut { + fn to_mut(&mut self) -> GGLWECompressed<&mut [u8]>; +} + +impl<D: DataMut> GGLWECompressedToMut for GGLWECompressed<D> { + fn to_mut(&mut self) -> GGLWECompressed<&mut [u8]> { + GGLWECompressed { + k: self.k(), + base2k: self.base2k(), + dsize: self.dsize(), + seed: self.seed.clone(), + rank_out: self.rank_out, + data: self.data.to_mut(), } + } +} - let rank_in: usize = self.rank_in().into(); - let dnum: usize = self.dnum().into(); +pub trait GGLWECompressedToRef { + fn to_ref(&self) -> GGLWECompressed<&[u8]>; +} - (0..rank_in).for_each(|col_i| { - (0..dnum).for_each(|row_i| { - self.at_mut(row_i, col_i) - .decompress(module, &other.at(row_i, col_i)); - }); - }); +impl<D: DataRef> GGLWECompressedToRef for GGLWECompressed<D> { + fn to_ref(&self) -> GGLWECompressed<&[u8]> { + GGLWECompressed { + k: self.k(), + base2k: self.base2k(), + dsize: self.dsize(), + seed: self.seed.clone(), + rank_out: self.rank_out, + data: self.data.to_ref(), + } } }
M poulpy-core/src/layouts/compressed/gglwe_ksk.rs → poulpy-core/src/layouts/compressed/gglwe_ksk.rs

@@ -1,25 +1,25 @@

use poulpy_hal::{ - api::{VecZnxCopy, VecZnxFillUniform}, layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision, - compressed::{Decompress, GGLWECiphertextCompressed}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeySetMetaData, GLWESwitchingKeyToMut, LWEInfos, + Rank, RingDegree, TorusPrecision, + compressed::{GGLWECompressed, GGLWECompressedAlloc, GGLWECompressedToMut, GGLWECompressedToRef, GGLWEDecompress}, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct GGLWESwitchingKeyCompressed<D: Data> { - pub(crate) key: GGLWECiphertextCompressed<D>, +pub struct GLWESwitchingKeyCompressed<D: Data> { + pub(crate) key: GGLWECompressed<D>, pub(crate) sk_in_n: usize, // Degree of sk_in pub(crate) sk_out_n: usize, // Degree of sk_out } -impl<D: Data> LWEInfos for GGLWESwitchingKeyCompressed<D> { - fn n(&self) -> Degree { +impl<D: Data> LWEInfos for GLWESwitchingKeyCompressed<D> { + fn n(&self) -> RingDegree { self.key.n() }

@@ -35,13 +35,13 @@ fn size(&self) -> usize {

self.key.size() } } -impl<D: Data> GLWEInfos for GGLWESwitchingKeyCompressed<D> { +impl<D: Data> GLWEInfos for GLWESwitchingKeyCompressed<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWESwitchingKeyCompressed<D> { +impl<D: Data> GGLWEInfos for GLWESwitchingKeyCompressed<D> { fn rank_in(&self) -> Rank { self.key.rank_in() }

@@ -59,19 +59,19 @@ self.key.dnum()

} } -impl<D: DataRef> fmt::Debug for GGLWESwitchingKeyCompressed<D> { +impl<D: DataRef> fmt::Debug for GLWESwitchingKeyCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWESwitchingKeyCompressed<D> { +impl<D: DataMut> FillUniform for GLWESwitchingKeyCompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.key.fill_uniform(log_bound, source); } } -impl<D: DataRef> fmt::Display for GGLWESwitchingKeyCompressed<D> { +impl<D: DataRef> fmt::Display for GLWESwitchingKeyCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f,

@@ -81,47 +81,100 @@ )

} } -impl GGLWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait GLWESwitchingKeyCompressedAlloc +where + Self: GGLWECompressedAlloc, +{ + fn alloc_glwe_switching_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> GLWESwitchingKeyCompressed<Vec<u8>> { + GLWESwitchingKeyCompressed { + key: self.alloc_gglwe_compressed(base2k, k, rank_in, rank_out, dnum, dsize), + sk_in_n: 0, + sk_out_n: 0, + } + } + + fn alloc_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> GLWESwitchingKeyCompressed<Vec<u8>> where A: GGLWEInfos, { - GGLWESwitchingKeyCompressed { - key: GGLWECiphertextCompressed::alloc(infos), - sk_in_n: 0, - sk_out_n: 0, - } + self.alloc_glwe_switching_key_compressed( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.rank_out(), + infos.dnum(), + infos.dsize(), + ) } - pub fn alloc_with( - n: Degree, + fn bytes_of_glwe_switching_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize { + self.bytes_of_gglwe_compressed(base2k, k, rank_in, dnum, dsize) + } + + fn bytes_of_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.bytes_of_gglwe_compressed_from_infos(infos) + } +} + +impl GLWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GLWESwitchingKeyCompressedAlloc, + { + module.alloc_glwe_switching_key_compressed_from_infos(infos) + } + + pub fn alloc<M>( + module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> Self { - GGLWESwitchingKeyCompressed { - key: GGLWECiphertextCompressed::alloc_with(n, base2k, k, rank_in, rank_out, dnum, dsize), - sk_in_n: 0, - sk_out_n: 0, - } + ) -> Self + where + M: GLWESwitchingKeyCompressedAlloc, + { + module.alloc_glwe_switching_key_compressed(base2k, k, rank_in, rank_out, dnum, dsize) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GGLWEInfos, + M: GLWESwitchingKeyCompressedAlloc, { - GGLWECiphertextCompressed::alloc_bytes(infos) + module.bytes_of_glwe_switching_key_compressed_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize { - GGLWECiphertextCompressed::alloc_bytes_with(n, base2k, k, rank_in, dnum, dsize) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: GLWESwitchingKeyCompressedAlloc, + { + module.bytes_of_glwe_switching_key_compressed(base2k, k, rank_in, dnum, dsize) } } -impl<D: DataMut> ReaderFrom for GGLWESwitchingKeyCompressed<D> { +impl<D: DataMut> ReaderFrom for GLWESwitchingKeyCompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize; self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize;

@@ -129,7 +182,7 @@ self.key.read_from(reader)

} } -impl<D: DataRef> WriterTo for GGLWESwitchingKeyCompressed<D> { +impl<D: DataRef> WriterTo for GLWESwitchingKeyCompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?; writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?;

@@ -137,13 +190,64 @@ self.key.write_to(writer)

} } -impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWESwitchingKeyCompressed<DR>> for GGLWESwitchingKey<D> +pub trait GLWESwitchingKeyDecompress +where + Self: GGLWEDecompress, +{ + fn decompress_glwe_switching_key<R, O>(&self, res: &mut R, other: &O) + where + R: GLWESwitchingKeyToMut + GLWESwitchingKeySetMetaData, + O: GLWESwitchingKeyCompressedToRef, + { + let other: &GLWESwitchingKeyCompressed<&[u8]> = &other.to_ref(); + self.decompress_gglwe(&mut res.to_mut().key, &other.key); + res.set_sk_in_n(other.sk_in_n); + res.set_sk_out_n(other.sk_out_n); + } +} + +impl<B: Backend> GLWESwitchingKeyDecompress for Module<B> where Self: GGLWEDecompress {} + +impl<D: DataMut> GLWESwitchingKey<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: GLWESwitchingKeyCompressedToRef, + M: GLWESwitchingKeyDecompress, + { + module.decompress_glwe_switching_key(self, other); + } +} + +pub trait GLWESwitchingKeyCompressedToMut { + fn to_mut(&mut self) -> GLWESwitchingKeyCompressed<&mut [u8]>; +} + +impl<D: DataMut> GLWESwitchingKeyCompressedToMut for GLWESwitchingKeyCompressed<D> +where + GGLWECompressed<D>: GGLWECompressedToMut, +{ + fn to_mut(&mut self) -> GLWESwitchingKeyCompressed<&mut [u8]> { + GLWESwitchingKeyCompressed { + sk_in_n: self.sk_in_n, + sk_out_n: self.sk_out_n, + key: self.key.to_mut(), + } + } +} + +pub trait GLWESwitchingKeyCompressedToRef { + fn to_ref(&self) -> GLWESwitchingKeyCompressed<&[u8]>; +} + +impl<D: DataRef> GLWESwitchingKeyCompressedToRef for GLWESwitchingKeyCompressed<D> where - Module<B>: VecZnxFillUniform + VecZnxCopy, + GGLWECompressed<D>: GGLWECompressedToRef, { - fn decompress(&mut self, module: &Module<B>, other: &GGLWESwitchingKeyCompressed<DR>) { - self.key.decompress(module, &other.key); - self.sk_in_n = other.sk_in_n; - self.sk_out_n = other.sk_out_n; + fn to_ref(&self) -> GLWESwitchingKeyCompressed<&[u8]> { + GLWESwitchingKeyCompressed { + sk_in_n: self.sk_in_n, + sk_out_n: self.sk_out_n, + key: self.key.to_ref(), + } } }
M poulpy-core/src/layouts/compressed/gglwe_tsk.rs → poulpy-core/src/layouts/compressed/gglwe_tsk.rs

@@ -1,23 +1,25 @@

use poulpy_hal::{ - api::{VecZnxCopy, VecZnxFillUniform}, layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision, - compressed::{Decompress, GGLWESwitchingKeyCompressed}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TensorKey, TensorKeyToMut, TorusPrecision, + compressed::{ + GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut, + GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress, + }, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct GGLWETensorKeyCompressed<D: Data> { - pub(crate) keys: Vec<GGLWESwitchingKeyCompressed<D>>, +pub struct TensorKeyCompressed<D: Data> { + pub(crate) keys: Vec<GLWESwitchingKeyCompressed<D>>, } -impl<D: Data> LWEInfos for GGLWETensorKeyCompressed<D> { - fn n(&self) -> Degree { +impl<D: Data> LWEInfos for TensorKeyCompressed<D> { + fn n(&self) -> RingDegree { self.keys[0].n() }

@@ -32,13 +34,13 @@ fn size(&self) -> usize {

self.keys[0].size() } } -impl<D: Data> GLWEInfos for GGLWETensorKeyCompressed<D> { +impl<D: Data> GLWEInfos for TensorKeyCompressed<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWETensorKeyCompressed<D> { +impl<D: Data> GGLWEInfos for TensorKeyCompressed<D> { fn rank_in(&self) -> Rank { self.rank_out() }

@@ -56,21 +58,21 @@ self.keys[0].dnum()

} } -impl<D: DataRef> fmt::Debug for GGLWETensorKeyCompressed<D> { +impl<D: DataRef> fmt::Debug for TensorKeyCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWETensorKeyCompressed<D> { +impl<D: DataMut> FillUniform for TensorKeyCompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.keys .iter_mut() - .for_each(|key: &mut GGLWESwitchingKeyCompressed<D>| key.fill_uniform(log_bound, source)) + .for_each(|key: &mut GLWESwitchingKeyCompressed<D>| key.fill_uniform(log_bound, source)) } } -impl<D: DataRef> fmt::Display for GGLWETensorKeyCompressed<D> { +impl<D: DataRef> fmt::Display for TensorKeyCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "(GLWETensorKeyCompressed)",)?; for (i, key) in self.keys.iter().enumerate() {

@@ -80,8 +82,27 @@ Ok(())

} } -impl GGLWETensorKeyCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait TensorKeyCompressedAlloc +where + Self: GLWESwitchingKeyCompressedAlloc, +{ + fn alloc_tensor_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> TensorKeyCompressed<Vec<u8>> { + let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1); + TensorKeyCompressed { + keys: (0..pairs) + .map(|_| self.alloc_glwe_switching_key_compressed(base2k, k, Rank(1), rank, dnum, dsize)) + .collect(), + } + } + + fn alloc_tensor_key_compressed_from_infos<A>(&self, infos: &A) -> TensorKeyCompressed<Vec<u8>> where A: GGLWEInfos, {

@@ -90,62 +111,67 @@ infos.rank_in(),

infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKeyCompressed" ); - Self::alloc_with( - infos.n(), + self.alloc_tensor_key_compressed( infos.base2k(), infos.k(), - infos.rank_out(), + infos.rank(), infos.dnum(), infos.dsize(), ) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self { - let mut keys: Vec<GGLWESwitchingKeyCompressed<Vec<u8>>> = Vec::new(); - let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1); - (0..pairs).for_each(|_| { - keys.push(GGLWESwitchingKeyCompressed::alloc_with( - n, - base2k, - k, - Rank(1), - rank, - dnum, - dsize, - )); - }); - Self { keys } + fn bytes_of_tensor_key_compressed(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { + let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize; + pairs * self.bytes_of_glwe_switching_key_compressed(base2k, k, Rank(1), dnum, dsize) + } + + fn bytes_of_tensor_key_compressed_from_infos<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.bytes_of_tensor_key_compressed( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) + } +} + +impl TensorKeyCompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: TensorKeyCompressedAlloc, + { + module.alloc_tensor_key_compressed_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: TensorKeyCompressedAlloc, + { + module.alloc_tensor_key_compressed(base2k, k, rank, dnum, dsize) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GGLWEInfos, + M: TensorKeyCompressedAlloc, { - assert_eq!( - infos.rank_in(), - infos.rank_out(), - "rank_in != rank_out is not supported for GGLWETensorKeyCompressed" - ); - let rank_out: usize = infos.rank_out().into(); - let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1); - pairs - * GGLWESwitchingKeyCompressed::alloc_bytes_with( - infos.n(), - infos.base2k(), - infos.k(), - Rank(1), - infos.dnum(), - infos.dsize(), - ) + module.bytes_of_tensor_key_compressed_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { - let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize; - pairs * GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, dsize) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: TensorKeyCompressedAlloc, + { + module.bytes_of_tensor_key_compressed(base2k, k, rank, dnum, dsize) } } -impl<D: DataMut> ReaderFrom for GGLWETensorKeyCompressed<D> { +impl<D: DataMut> ReaderFrom for TensorKeyCompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { let len: usize = reader.read_u64::<LittleEndian>()? as usize; if self.keys.len() != len {

@@ -161,7 +187,7 @@ Ok(())

} } -impl<D: DataRef> WriterTo for GGLWETensorKeyCompressed<D> { +impl<D: DataRef> WriterTo for TensorKeyCompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; for key in &self.keys {

@@ -171,8 +197,8 @@ Ok(())

} } -impl<D: DataMut> GGLWETensorKeyCompressed<D> { - pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyCompressed<D> { +impl<D: DataMut> TensorKeyCompressed<D> { + pub(crate) fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyCompressed<D> { if i > j { std::mem::swap(&mut i, &mut j); };

@@ -181,27 +207,70 @@ &mut self.keys[i * rank + j - (i * (i + 1) / 2)]

} } -impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, GGLWETensorKeyCompressed<DR>> for GGLWETensorKey<D> +pub trait TensorKeyDecompress +where + Self: GLWESwitchingKeyDecompress, +{ + fn decompress_tensor_key<R, O>(&self, res: &mut R, other: &O) + where + R: TensorKeyToMut, + O: TensorKeyCompressedToRef, + { + let res: &mut TensorKey<&mut [u8]> = &mut res.to_mut(); + let other: &TensorKeyCompressed<&[u8]> = &other.to_ref(); + + assert_eq!( + res.keys.len(), + other.keys.len(), + "invalid receiver: res.keys.len()={} != other.keys.len()={}", + res.keys.len(), + other.keys.len() + ); + + for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) { + self.decompress_glwe_switching_key(a, b); + } + } +} + +impl<B: Backend> TensorKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {} + +impl<D: DataMut> TensorKey<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: TensorKeyCompressedToRef, + M: TensorKeyDecompress, + { + module.decompress_tensor_key(self, other); + } +} + +pub trait TensorKeyCompressedToMut { + fn to_mut(&mut self) -> TensorKeyCompressed<&mut [u8]>; +} + +impl<D: DataMut> TensorKeyCompressedToMut for TensorKeyCompressed<D> where - Module<B>: VecZnxFillUniform + VecZnxCopy, + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut, { - fn decompress(&mut self, module: &Module<B>, other: &GGLWETensorKeyCompressed<DR>) { - #[cfg(debug_assertions)] - { - assert_eq!( - self.keys.len(), - other.keys.len(), - "invalid receiver: self.keys.len()={} != other.keys.len()={}", - self.keys.len(), - other.keys.len() - ); + fn to_mut(&mut self) -> TensorKeyCompressed<&mut [u8]> { + TensorKeyCompressed { + keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(), } + } +} - self.keys - .iter_mut() - .zip(other.keys.iter()) - .for_each(|(a, b)| { - a.decompress(module, b); - }); +pub trait TensorKeyCompressedToRef { + fn to_ref(&self) -> TensorKeyCompressed<&[u8]>; +} + +impl<D: DataRef> TensorKeyCompressedToRef for TensorKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef, +{ + fn to_ref(&self) -> TensorKeyCompressed<&[u8]> { + TensorKeyCompressed { + keys: self.keys.iter().map(|c| c.to_ref()).collect(), + } } }
M poulpy-core/src/layouts/compressed/ggsw_ct.rs → poulpy-core/src/layouts/compressed/ggsw_ct.rs

@@ -1,18 +1,19 @@

use poulpy_hal::{ - api::{VecZnxCopy, VecZnxFillUniform}, - layouts::{Backend, Data, DataMut, DataRef, FillUniform, MatZnx, Module, ReaderFrom, WriterTo, ZnxInfos}, + layouts::{ + Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos, + }, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - compressed::{Decompress, GLWECiphertextCompressed}, + Base2K, Dnum, Dsize, GGSW, GGSWInfos, GGSWToMut, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision, + compressed::{GLWECompressed, GLWEDecompress}, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct GGSWCiphertextCompressed<D: Data> { +pub struct GGSWCompressed<D: Data> { pub(crate) data: MatZnx<D>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K,

@@ -21,9 +22,9 @@ pub(crate) rank: Rank,

pub(crate) seed: Vec<[u8; 32]>, } -impl<D: Data> LWEInfos for GGSWCiphertextCompressed<D> { - fn n(&self) -> Degree { - Degree(self.data.n() as u32) +impl<D: Data> LWEInfos for GGSWCompressed<D> { + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn base2k(&self) -> Base2K {

@@ -37,13 +38,13 @@ fn size(&self) -> usize {

self.data.size() } } -impl<D: Data> GLWEInfos for GGSWCiphertextCompressed<D> { +impl<D: Data> GLWEInfos for GGSWCompressed<D> { fn rank(&self) -> Rank { self.rank } } -impl<D: Data> GGSWInfos for GGSWCiphertextCompressed<D> { +impl<D: Data> GGSWInfos for GGSWCompressed<D> { fn dsize(&self) -> Dsize { self.dsize }

@@ -53,46 +54,42 @@ Dnum(self.data.rows() as u32)

} } -impl<D: DataRef> fmt::Debug for GGSWCiphertextCompressed<D> { +impl<D: DataRef> fmt::Debug for GGSWCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.data) } } -impl<D: DataRef> fmt::Display for GGSWCiphertextCompressed<D> { +impl<D: DataRef> fmt::Display for GGSWCompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "(GGSWCiphertextCompressed: base2k={} k={} dsize={}) {}", + "(GGSWCompressed: base2k={} k={} dsize={}) {}", self.base2k, self.k, self.dsize, self.data ) } } -impl<D: DataMut> FillUniform for GGSWCiphertextCompressed<D> { +impl<D: DataMut> FillUniform for GGSWCompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl GGSWCiphertextCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: GGSWInfos, - { - Self::alloc_with( - infos.n(), - infos.base2k(), - infos.k(), - infos.rank(), - infos.dnum(), - infos.dsize(), - ) - } - - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self { +pub trait GGSWCompressedAlloc +where + Self: GetRingDegree, +{ + fn alloc_ggsw_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> GGSWCompressed<Vec<u8>> { let size: usize = k.0.div_ceil(base2k.0) as usize; - debug_assert!( + assert!( size as u32 > dsize.0, "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}", dsize.0

@@ -105,9 +102,9 @@ dnum.0,

dsize.0, ); - Self { + GGSWCompressed { data: MatZnx::alloc( - n.into(), + self.ring_degree().into(), dnum.into(), (rank + 1).into(), 1,

@@ -121,12 +118,11 @@ seed: Vec::new(),

} } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn alloc_ggsw_compressed_from_infos<A>(&self, infos: &A) -> GGSWCompressed<Vec<u8>> where A: GGSWInfos, { - Self::alloc_bytes_with( - infos.n(), + self.alloc_ggsw_compressed( infos.base2k(), infos.k(), infos.rank(),

@@ -135,9 +131,9 @@ infos.dsize(),

) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { + fn bytes_of_ggsw_compressed(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { let size: usize = k.0.div_ceil(base2k.0) as usize; - debug_assert!( + assert!( size as u32 > dsize.0, "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}", dsize.0

@@ -150,20 +146,65 @@ dnum.0,

dsize.0, ); - MatZnx::alloc_bytes( - n.into(), + MatZnx::bytes_of( + self.ring_degree().into(), dnum.into(), (rank + 1).into(), 1, k.0.div_ceil(base2k.0) as usize, ) } + + fn bytes_of_ggsw_compressed_key_from_infos<A>(&self, infos: &A) -> usize + where + A: GGSWInfos, + { + self.bytes_of_ggsw_compressed( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) + } } -impl<D: DataRef> GGSWCiphertextCompressed<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertextCompressed<&[u8]> { +impl GGSWCompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGSWInfos, + M: GGSWCompressedAlloc, + { + module.alloc_ggsw_compressed_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: GGSWCompressedAlloc, + { + module.alloc_ggsw_compressed(base2k, k, rank, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGSWInfos, + M: GGSWCompressedAlloc, + { + module.bytes_of_ggsw_compressed_key_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: GGSWCompressedAlloc, + { + module.bytes_of_ggsw_compressed(base2k, k, rank, dnum, dsize) + } +} + +impl<D: DataRef> GGSWCompressed<D> { + pub fn at(&self, row: usize, col: usize) -> GLWECompressed<&[u8]> { let rank: usize = self.rank().into(); - GLWECiphertextCompressed { + GLWECompressed { data: self.data.at(row, col), k: self.k, base2k: self.base2k,

@@ -173,10 +214,10 @@ }

} } -impl<D: DataMut> GGSWCiphertextCompressed<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertextCompressed<&mut [u8]> { +impl<D: DataMut> GGSWCompressed<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECompressed<&mut [u8]> { let rank: usize = self.rank().into(); - GLWECiphertextCompressed { + GLWECompressed { data: self.data.at_mut(row, col), k: self.k, base2k: self.base2k,

@@ -186,7 +227,7 @@ }

} } -impl<D: DataMut> ReaderFrom for GGSWCiphertextCompressed<D> { +impl<D: DataMut> ReaderFrom for GGSWCompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -201,7 +242,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for GGSWCiphertextCompressed<D> { +impl<D: DataRef> WriterTo for GGSWCompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.into())?; writer.write_u32::<LittleEndian>(self.base2k.into())?;

@@ -215,23 +256,72 @@ self.data.write_to(writer)

} } -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GGSWCiphertextCompressed<DR>> for GGSWCiphertext<D> +pub trait GGSWDecompress where - Module<B>: VecZnxFillUniform + VecZnxCopy, + Self: GLWEDecompress, { - fn decompress(&mut self, module: &Module<B>, other: &GGSWCiphertextCompressed<DR>) { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), other.rank()) + fn decompress_ggsw<R, O>(&self, res: &mut R, other: &O) + where + R: GGSWToMut, + O: GGSWCompressedToRef, + { + let res: &mut GGSW<&mut [u8]> = &mut res.to_mut(); + let other: &GGSWCompressed<&[u8]> = &other.to_ref(); + + assert_eq!(res.rank(), other.rank()); + let dnum: usize = res.dnum().into(); + let rank: usize = res.rank().into(); + + for row_i in 0..dnum { + for col_j in 0..rank + 1 { + self.decompress_glwe(&mut res.at_mut(row_i, col_j), &other.at(row_i, col_j)); + } + } + } +} + +impl<B: Backend> GGSWDecompress for Module<B> where Self: GGSWDecompress {} + +impl<D: DataMut> GGSW<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: GGSWCompressedToRef, + M: GGSWDecompress, + { + module.decompress_ggsw(self, other); + } +} + +pub trait GGSWCompressedToMut { + fn to_mut(&mut self) -> GGSWCompressed<&mut [u8]>; +} + +impl<D: DataMut> GGSWCompressedToMut for GGSWCompressed<D> { + fn to_mut(&mut self) -> GGSWCompressed<&mut [u8]> { + GGSWCompressed { + k: self.k(), + base2k: self.base2k(), + dsize: self.dsize(), + rank: self.rank(), + seed: self.seed.clone(), + data: self.data.to_mut(), } + } +} - let dnum: usize = self.dnum().into(); - let rank: usize = self.rank().into(); - (0..dnum).for_each(|row_i| { - (0..rank + 1).for_each(|col_j| { - self.at_mut(row_i, col_j) - .decompress(module, &other.at(row_i, col_j)); - }); - }); +pub trait GGSWCompressedToRef { + fn to_ref(&self) -> GGSWCompressed<&[u8]>; +} + +impl<D: DataRef> GGSWCompressedToRef for GGSWCompressed<D> { + fn to_ref(&self) -> GGSWCompressed<&[u8]> { + GGSWCompressed { + k: self.k(), + base2k: self.base2k(), + dsize: self.dsize(), + rank: self.rank(), + seed: self.seed.clone(), + data: self.data.to_ref(), + } } }
M poulpy-core/src/layouts/compressed/glwe_ct.rs → poulpy-core/src/layouts/compressed/glwe_ct.rs

@@ -1,15 +1,19 @@

use poulpy_hal::{ api::{VecZnxCopy, VecZnxFillUniform}, - layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, VecZnx, WriterTo, ZnxInfos}, + layouts::{ + Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo, ZnxInfos, + }, source::Source, }; -use crate::layouts::{Base2K, Degree, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision, compressed::Decompress}; +use crate::layouts::{ + Base2K, GLWE, GLWEInfos, GLWEToMut, GetRingDegree, LWEInfos, Rank, RingDegree, SetGLWEInfos, TorusPrecision, +}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct GLWECiphertextCompressed<D: Data> { +pub struct GLWECompressed<D: Data> { pub(crate) data: VecZnx<D>, pub(crate) base2k: Base2K, pub(crate) k: TorusPrecision,

@@ -17,7 +21,7 @@ pub(crate) rank: Rank,

pub(crate) seed: [u8; 32], } -impl<D: Data> LWEInfos for GLWECiphertextCompressed<D> { +impl<D: Data> LWEInfos for GLWECompressed<D> { fn base2k(&self) -> Base2K { self.base2k }

@@ -30,27 +34,27 @@ fn size(&self) -> usize {

self.data.size() } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } } -impl<D: Data> GLWEInfos for GLWECiphertextCompressed<D> { +impl<D: Data> GLWEInfos for GLWECompressed<D> { fn rank(&self) -> Rank { self.rank } } -impl<D: DataRef> fmt::Debug for GLWECiphertextCompressed<D> { +impl<D: DataRef> fmt::Debug for GLWECompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataRef> fmt::Display for GLWECiphertextCompressed<D> { +impl<D: DataRef> fmt::Display for GLWECompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "GLWECiphertextCompressed: base2k={} k={} rank={} seed={:?}: {}", + "GLWECompressed: base2k={} k={} rank={} seed={:?}: {}", self.base2k(), self.k(), self.rank(),

@@ -60,43 +64,90 @@ )

} } -impl<D: DataMut> FillUniform for GLWECiphertextCompressed<D> { +impl<D: DataMut> FillUniform for GLWECompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl GLWECiphertextCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait GLWECompressedAlloc +where + Self: GetRingDegree, +{ + fn alloc_glwe_compressed(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWECompressed<Vec<u8>> { + GLWECompressed { + data: VecZnx::alloc( + self.ring_degree().into(), + 1, + k.0.div_ceil(base2k.0) as usize, + ), + base2k, + k, + rank, + seed: [0u8; 32], + } + } + + fn alloc_glwe_compressed_from_infos<A>(&self, infos: &A) -> GLWECompressed<Vec<u8>> + where + A: GLWEInfos, + { + assert_eq!(self.ring_degree(), infos.n()); + self.alloc_glwe_compressed(infos.base2k(), infos.k(), infos.rank()) + } + + fn bytes_of_glwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> usize { + VecZnx::bytes_of( + self.ring_degree().into(), + 1, + k.0.div_ceil(base2k.0) as usize, + ) + } + + fn bytes_of_glwe_compressed_from_infos<A>(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + assert_eq!(self.ring_degree(), infos.n()); + self.bytes_of_glwe_compressed(infos.base2k(), infos.k()) + } +} + +impl<B: Backend> GLWECompressedAlloc for Module<B> where Self: GetRingDegree {} + +impl GLWECompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GLWEInfos, + M: GLWECompressedAlloc, { - Self::alloc_with(infos.n(), infos.base2k(), infos.k(), infos.rank()) + module.alloc_glwe_compressed_from_infos(infos) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self { - Self { - data: VecZnx::alloc(n.into(), 1, k.0.div_ceil(base2k.0) as usize), - base2k, - k, - rank, - seed: [0u8; 32], - } + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self + where + M: GLWECompressedAlloc, + { + module.alloc_glwe_compressed(base2k, k, rank) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GLWEInfos, + M: GLWECompressedAlloc, { - Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k()) + module.bytes_of_glwe_compressed_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision) -> usize { - VecZnx::alloc_bytes(n.into(), 1, k.0.div_ceil(base2k.0) as usize) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> usize + where + M: GLWECompressedAlloc, + { + module.bytes_of_glwe_compressed(base2k, k) } } -impl<D: DataMut> ReaderFrom for GLWECiphertextCompressed<D> { +impl<D: DataMut> ReaderFrom for GLWECompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -106,7 +157,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for GLWECiphertextCompressed<D> { +impl<D: DataRef> WriterTo for GLWECompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.into())?; writer.write_u32::<LittleEndian>(self.base2k.into())?;

@@ -116,63 +167,82 @@ self.data.write_to(writer)

} } -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, GLWECiphertextCompressed<DR>> for GLWECiphertext<D> +pub trait GLWEDecompress where - Module<B>: VecZnxFillUniform + VecZnxCopy, + Self: GetRingDegree + VecZnxFillUniform + VecZnxCopy, { - fn decompress(&mut self, module: &Module<B>, other: &GLWECiphertextCompressed<DR>) { - #[cfg(debug_assertions)] + fn decompress_glwe<R, O>(&self, res: &mut R, other: &O) + where + R: GLWEToMut + SetGLWEInfos, + O: GLWECompressedToRef + GLWEInfos, + { { - assert_eq!( - self.n(), - other.n(), - "invalid receiver: self.n()={} != other.n()={}", - self.n(), - other.n() - ); - assert_eq!( - self.size(), - other.size(), - "invalid receiver: self.size()={} != other.size()={}", - self.size(), - other.size() - ); + let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let other: &GLWECompressed<&[u8]> = &other.to_ref(); assert_eq!( - self.rank(), - other.rank(), - "invalid receiver: self.rank()={} != other.rank()={}", - self.rank(), - other.rank() + res.n(), + self.ring_degree(), + "invalid receiver: res.n()={} != other.n()={}", + res.n(), + self.ring_degree() ); + + assert_eq!(res.lwe_layout(), other.lwe_layout()); + assert_eq!(res.glwe_layout(), other.glwe_layout()); + + let mut source: Source = Source::new(other.seed); + + self.vec_znx_copy(&mut res.data, 0, &other.data, 0); + (1..(other.rank() + 1).into()).for_each(|i| { + self.vec_znx_fill_uniform(other.base2k.into(), &mut res.data, i, &mut source); + }); } - let mut source: Source = Source::new(other.seed); - self.decompress_internal(module, other, &mut source); + res.set_base2k(other.base2k()); + res.set_k(other.k()); } } -impl<D: DataMut> GLWECiphertext<D> { - pub(crate) fn decompress_internal<DataOther, B: Backend>( - &mut self, - module: &Module<B>, - other: &GLWECiphertextCompressed<DataOther>, - source: &mut Source, - ) where - DataOther: DataRef, - Module<B>: VecZnxCopy + VecZnxFillUniform, +impl<B: Backend> GLWEDecompress for Module<B> where Self: GetRingDegree + VecZnxFillUniform + VecZnxCopy {} + +impl<D: DataMut> GLWE<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: GLWECompressedToRef + GLWEInfos, + M: GLWEDecompress, { - #[cfg(debug_assertions)] - { - assert_eq!(self.rank(), other.rank()); - debug_assert_eq!(self.size(), other.size()); + module.decompress_glwe(self, other); + } +} + +pub trait GLWECompressedToRef { + fn to_ref(&self) -> GLWECompressed<&[u8]>; +} + +impl<D: DataRef> GLWECompressedToRef for GLWECompressed<D> { + fn to_ref(&self) -> GLWECompressed<&[u8]> { + GLWECompressed { + seed: self.seed.clone(), + base2k: self.base2k, + k: self.k, + rank: self.rank, + data: self.data.to_ref(), } + } +} - module.vec_znx_copy(&mut self.data, 0, &other.data, 0); - (1..(other.rank() + 1).into()).for_each(|i| { - module.vec_znx_fill_uniform(other.base2k.into(), &mut self.data, i, source); - }); +pub trait GLWECompressedToMut { + fn to_mut(&mut self) -> GLWECompressed<&mut [u8]>; +} - self.base2k = other.base2k; - self.k = other.k; +impl<D: DataMut> GLWECompressedToMut for GLWECompressed<D> { + fn to_mut(&mut self) -> GLWECompressed<&mut [u8]> { + GLWECompressed { + seed: self.seed.clone(), + base2k: self.base2k, + k: self.k, + rank: self.rank, + data: self.data.to_mut(), + } } }
M poulpy-core/src/layouts/compressed/glwe_to_lwe_ksk.rs → poulpy-core/src/layouts/compressed/glwe_to_lwe_ksk.rs

@@ -1,16 +1,21 @@

use std::fmt; use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, compressed::GGLWESwitchingKeyCompressed, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWESwitchingKey, GLWEToLWESwitchingKeyToMut, LWEInfos, Rank, RingDegree, + TorusPrecision, + compressed::{ + GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut, + GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress, + }, }; #[derive(PartialEq, Eq, Clone)] -pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>); +pub struct GLWEToLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>); impl<D: Data> LWEInfos for GLWEToLWESwitchingKeyCompressed<D> { fn base2k(&self) -> Base2K {

@@ -21,7 +26,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() } fn size(&self) -> usize {

@@ -83,54 +88,146 @@ self.0.write_to(writer)

} } -impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait GLWEToLWESwitchingKeyCompressedAlloc +where + Self: GLWESwitchingKeyCompressedAlloc, +{ + fn alloc_glwe_to_lwe_switching_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + dnum: Dnum, + ) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> { + GLWEToLWESwitchingKeyCompressed(self.alloc_glwe_switching_key_compressed(base2k, k, rank_in, Rank(1), dnum, Dsize(1))) + } + + fn alloc_glwe_to_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> GLWEToLWESwitchingKeyCompressed<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is unsupported for GLWEToLWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is unsupported for GLWEToLWESwitchingKeyCompressed" ); - Self(GGLWESwitchingKeyCompressed::alloc(infos)) + self.alloc_glwe_to_lwe_switching_key_compressed(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self { - Self(GGLWESwitchingKeyCompressed::alloc_with( - n, - base2k, - k, - rank_in, - Rank(1), - dnum, - Dsize(1), - )) + fn bytes_of_glwe_to_lwe_switching_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + dnum: Dnum, + ) -> usize { + self.bytes_of_glwe_switching_key_compressed(base2k, k, rank_in, dnum, Dsize(1)) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_glwe_to_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is unsupported for GLWEToLWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is unsupported for GLWEToLWESwitchingKeyCompressed" ); - GGLWESwitchingKeyCompressed::alloc_bytes(infos) + self.bytes_of_glwe_switching_key_compressed_from_infos(infos) + } +} + +impl<B: Backend> GLWEToLWESwitchingKeyCompressedAlloc for Module<B> where Self: GLWESwitchingKeyCompressedAlloc {} + +impl GLWEToLWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyCompressedAlloc, + { + module.alloc_glwe_to_lwe_switching_key_compressed_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self + where + M: GLWEToLWESwitchingKeyCompressedAlloc, + { + module.alloc_glwe_to_lwe_switching_key_compressed(base2k, k, rank_in, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyCompressedAlloc, + { + module.bytes_of_glwe_to_lwe_switching_key_compressed_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_in: Rank) -> usize + where + M: GLWEToLWESwitchingKeyCompressedAlloc, + { + module.bytes_of_glwe_to_lwe_switching_key_compressed(base2k, k, rank_in, dnum) + } +} + +pub trait GLWEToLWESwitchingKeyDecompress +where + Self: GLWESwitchingKeyDecompress, +{ + fn decompress_glwe_to_lwe_switching_key<R, O>(&self, res: &mut R, other: &O) + where + R: GLWEToLWESwitchingKeyToMut, + O: GLWEToLWESwitchingKeyCompressedToRef, + { + self.decompress_glwe_switching_key(&mut res.to_mut().0, &other.to_ref().0); + } +} + +impl<B: Backend> GLWEToLWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {} + +impl<D: DataMut> GLWEToLWESwitchingKey<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: GLWEToLWESwitchingKeyCompressedToRef, + M: GLWEToLWESwitchingKeyDecompress, + { + module.decompress_glwe_to_lwe_switching_key(self, other); } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_in: Rank) -> usize { - GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, rank_in, dnum, Dsize(1)) +pub trait GLWEToLWESwitchingKeyCompressedToRef { + fn to_ref(&self) -> GLWEToLWESwitchingKeyCompressed<&[u8]>; +} + +impl<D: DataRef> GLWEToLWESwitchingKeyCompressedToRef for GLWEToLWESwitchingKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef, +{ + fn to_ref(&self) -> GLWEToLWESwitchingKeyCompressed<&[u8]> { + GLWEToLWESwitchingKeyCompressed(self.0.to_ref()) + } +} + +pub trait GLWEToLWESwitchingKeyCompressedToMut { + fn to_mut(&mut self) -> GLWEToLWESwitchingKeyCompressed<&mut [u8]>; +} + +impl<D: DataMut> GLWEToLWESwitchingKeyCompressedToMut for GLWEToLWESwitchingKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut, +{ + fn to_mut(&mut self) -> GLWEToLWESwitchingKeyCompressed<&mut [u8]> { + GLWEToLWESwitchingKeyCompressed(self.0.to_mut()) } }
M poulpy-core/src/layouts/compressed/lwe_ct.rs → poulpy-core/src/layouts/compressed/lwe_ct.rs

@@ -2,21 +2,24 @@ use std::fmt;

use poulpy_hal::{ api::ZnFillUniform, - layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnxInfos, ZnxView, ZnxViewMut}, + layouts::{ + Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos, ZnxView, + ZnxViewMut, + }, source::Source, }; -use crate::layouts::{Base2K, Degree, LWECiphertext, LWEInfos, TorusPrecision, compressed::Decompress}; +use crate::layouts::{Base2K, LWE, LWEInfos, LWEToMut, RingDegree, TorusPrecision}; #[derive(PartialEq, Eq, Clone)] -pub struct LWECiphertextCompressed<D: Data> { +pub struct LWECompressed<D: Data> { pub(crate) data: Zn<D>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K, pub(crate) seed: [u8; 32], } -impl<D: Data> LWEInfos for LWECiphertextCompressed<D> { +impl<D: Data> LWEInfos for LWECompressed<D> { fn base2k(&self) -> Base2K { self.base2k }

@@ -25,8 +28,8 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -34,17 +37,17 @@ self.data.size()

} } -impl<D: DataRef> fmt::Debug for LWECiphertextCompressed<D> { +impl<D: DataRef> fmt::Debug for LWECompressed<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataRef> fmt::Display for LWECiphertextCompressed<D> { +impl<D: DataRef> fmt::Display for LWECompressed<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "LWECiphertextCompressed: base2k={} k={} seed={:?}: {}", + "LWECompressed: base2k={} k={} seed={:?}: {}", self.base2k(), self.k(), self.seed,

@@ -53,22 +56,15 @@ )

} } -impl<D: DataMut> FillUniform for LWECiphertextCompressed<D> { +impl<D: DataMut> FillUniform for LWECompressed<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl LWECiphertextCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: LWEInfos, - { - Self::alloc_with(infos.base2k(), infos.k()) - } - - pub fn alloc_with(base2k: Base2K, k: TorusPrecision) -> Self { - Self { +pub trait LWECompressedAlloc { + fn alloc_lwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> LWECompressed<Vec<u8>> { + LWECompressed { data: Zn::alloc(1, 1, k.0.div_ceil(base2k.0) as usize), k, base2k,

@@ -76,21 +72,62 @@ seed: [0u8; 32],

} } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn alloc_lwe_compressed_from_infos<A>(&self, infos: &A) -> LWECompressed<Vec<u8>> where A: LWEInfos, { - Self::alloc_bytes_with(infos.base2k(), infos.k()) + self.alloc_lwe_compressed(infos.base2k(), infos.k()) } - pub fn alloc_bytes_with(base2k: Base2K, k: TorusPrecision) -> usize { - Zn::alloc_bytes(1, 1, k.0.div_ceil(base2k.0) as usize) + fn bytes_of_lwe_compressed(&self, base2k: Base2K, k: TorusPrecision) -> usize { + Zn::bytes_of(1, 1, k.0.div_ceil(base2k.0) as usize) + } + + fn bytes_of_lwe_compressed_from_infos<A>(&self, infos: &A) -> usize + where + A: LWEInfos, + { + self.bytes_of_lwe_compressed(infos.base2k(), infos.k()) + } +} + +impl<B: Backend> LWECompressedAlloc for Module<B> {} + +impl LWECompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: LWEInfos, + M: LWECompressedAlloc, + { + module.alloc_lwe_compressed_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> Self + where + M: LWECompressedAlloc, + { + module.alloc_lwe_compressed(base2k, k) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: LWEInfos, + M: LWECompressedAlloc, + { + module.bytes_of_lwe_compressed_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> usize + where + M: LWECompressedAlloc, + { + module.bytes_of_lwe_compressed(base2k, k) } } use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -impl<D: DataMut> ReaderFrom for LWECiphertextCompressed<D> { +impl<D: DataMut> ReaderFrom for LWECompressed<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -99,7 +136,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for LWECiphertextCompressed<D> { +impl<D: DataRef> WriterTo for LWECompressed<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.into())?; writer.write_u32::<LittleEndian>(self.base2k.into())?;

@@ -108,22 +145,72 @@ self.data.write_to(writer)

} } -impl<D: DataMut, B: Backend, DR: DataRef> Decompress<B, LWECiphertextCompressed<DR>> for LWECiphertext<D> +pub trait LWEDecompress where - Module<B>: ZnFillUniform, + Self: ZnFillUniform, { - fn decompress(&mut self, module: &Module<B>, other: &LWECiphertextCompressed<DR>) { - debug_assert_eq!(self.size(), other.size()); + fn decompress_lwe<R, O>(&self, res: &mut R, other: &O) + where + R: LWEToMut, + O: LWECompressedToRef, + { + let res: &mut LWE<&mut [u8]> = &mut res.to_mut(); + let other: &LWECompressed<&[u8]> = &other.to_ref(); + + assert_eq!(res.lwe_layout(), other.lwe_layout()); + let mut source: Source = Source::new(other.seed); - module.zn_fill_uniform( - self.n().into(), + self.zn_fill_uniform( + res.n().into(), other.base2k().into(), - &mut self.data, + &mut res.data, 0, &mut source, ); - (0..self.size()).for_each(|i| { - self.data.at_mut(0, i)[0] = other.data.at(0, i)[0]; - }); + for i in 0..res.size() { + res.data.at_mut(0, i)[0] = other.data.at(0, i)[0]; + } + } +} + +impl<B: Backend> LWEDecompress for Module<B> where Self: ZnFillUniform {} + +impl<D: DataMut> LWE<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: LWECompressedToRef, + M: LWEDecompress, + { + module.decompress_lwe(self, other); + } +} + +pub trait LWECompressedToRef { + fn to_ref(&self) -> LWECompressed<&[u8]>; +} + +impl<D: DataRef> LWECompressedToRef for LWECompressed<D> { + fn to_ref(&self) -> LWECompressed<&[u8]> { + LWECompressed { + k: self.k, + base2k: self.base2k, + seed: self.seed, + data: self.data.to_ref(), + } + } +} + +pub trait LWECompressedToMut { + fn to_mut(&mut self) -> LWECompressed<&mut [u8]>; +} + +impl<D: DataMut> LWECompressedToMut for LWECompressed<D> { + fn to_mut(&mut self) -> LWECompressed<&mut [u8]> { + LWECompressed { + k: self.k, + base2k: self.base2k, + seed: self.seed, + data: self.data.to_mut(), + } } }
M poulpy-core/src/layouts/compressed/lwe_ksk.rs → poulpy-core/src/layouts/compressed/lwe_ksk.rs

@@ -1,17 +1,20 @@

use poulpy_hal::{ - api::{VecZnxCopy, VecZnxFillUniform}, layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, TorusPrecision, - compressed::{Decompress, GGLWESwitchingKeyCompressed}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, LWESwitchingKeyToMut, Rank, RingDegree, + TorusPrecision, + compressed::{ + GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut, + GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress, + }, }; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>); +pub struct LWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>); impl<D: Data> LWEInfos for LWESwitchingKeyCompressed<D> { fn base2k(&self) -> Base2K {

@@ -22,7 +25,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() } fn size(&self) -> usize {

@@ -83,73 +86,149 @@ self.0.write_to(writer)

} } -impl LWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait LWESwitchingKeyCompressedAlloc +where + Self: GLWESwitchingKeyCompressedAlloc, +{ + fn alloc_lwe_switching_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + dnum: Dnum, + ) -> LWESwitchingKeyCompressed<Vec<u8>> { + LWESwitchingKeyCompressed(self.alloc_glwe_switching_key_compressed(base2k, k, Rank(1), Rank(1), dnum, Dsize(1))) + } + + fn alloc_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> LWESwitchingKeyCompressed<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for LWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, "rank_in > 1 is not supported for LWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is not supported for LWESwitchingKeyCompressed" ); - Self(GGLWESwitchingKeyCompressed::alloc(infos)) + self.alloc_lwe_switching_key_compressed(infos.base2k(), infos.k(), infos.dnum()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self { - Self(GGLWESwitchingKeyCompressed::alloc_with( - n, - base2k, - k, - Rank(1), - Rank(1), - dnum, - Dsize(1), - )) + fn bytes_of_lwe_switching_key_compressed(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key_compressed(base2k, k, Rank(1), dnum, Dsize(1)) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_lwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, - "dsize > 1 is not supported for LWESwitchingKey" + "dsize > 1 is not supported for LWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, - "rank_in > 1 is not supported for LWESwitchingKey" + "rank_in > 1 is not supported for LWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, - "rank_out > 1 is not supported for LWESwitchingKey" + "rank_out > 1 is not supported for LWESwitchingKeyCompressed" ); - GGLWESwitchingKeyCompressed::alloc_bytes(infos) + self.bytes_of_glwe_switching_key_compressed_from_infos(infos) + } +} + +impl<B: Backend> LWESwitchingKeyCompressedAlloc for Module<B> where Self: GLWESwitchingKeyCompressedAlloc {} + +impl LWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: LWESwitchingKeyCompressedAlloc, + { + module.alloc_lwe_switching_key_compressed_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self + where + M: LWESwitchingKeyCompressedAlloc, + { + module.alloc_lwe_switching_key_compressed(base2k, k, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: LWESwitchingKeyCompressedAlloc, + { + module.bytes_of_lwe_switching_key_compressed_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { - GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, Dsize(1)) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize + where + M: LWESwitchingKeyCompressedAlloc, + { + module.bytes_of_lwe_switching_key_compressed(base2k, k, dnum) } } -impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, LWESwitchingKeyCompressed<DR>> for LWESwitchingKey<D> +pub trait LWESwitchingKeyDecompress where - Module<B>: VecZnxFillUniform + VecZnxCopy, + Self: GLWESwitchingKeyDecompress, { - fn decompress(&mut self, module: &Module<B>, other: &LWESwitchingKeyCompressed<DR>) { - self.0.decompress(module, &other.0); + fn decompress_lwe_switching_key<R, O>(&self, res: &mut R, other: &O) + where + R: LWESwitchingKeyToMut, + O: LWESwitchingKeyCompressedToRef, + { + self.decompress_glwe_switching_key(&mut res.to_mut().0, &other.to_ref().0); + } +} + +impl<B: Backend> LWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {} + +impl<D: DataMut> LWESwitchingKey<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: LWESwitchingKeyCompressedToRef, + M: LWESwitchingKeyDecompress, + { + module.decompress_lwe_switching_key(self, other); + } +} + +pub trait LWESwitchingKeyCompressedToRef { + fn to_ref(&self) -> LWESwitchingKeyCompressed<&[u8]>; +} + +impl<D: DataRef> LWESwitchingKeyCompressedToRef for LWESwitchingKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef, +{ + fn to_ref(&self) -> LWESwitchingKeyCompressed<&[u8]> { + LWESwitchingKeyCompressed(self.0.to_ref()) + } +} + +pub trait LWESwitchingKeyCompressedToMut { + fn to_mut(&mut self) -> LWESwitchingKeyCompressed<&mut [u8]>; +} + +impl<D: DataMut> LWESwitchingKeyCompressedToMut for LWESwitchingKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut, +{ + fn to_mut(&mut self) -> LWESwitchingKeyCompressed<&mut [u8]> { + LWESwitchingKeyCompressed(self.0.to_mut()) } }
M poulpy-core/src/layouts/compressed/lwe_to_glwe_ksk.rs → poulpy-core/src/layouts/compressed/lwe_to_glwe_ksk.rs

@@ -1,20 +1,23 @@

use poulpy_hal::{ - api::{VecZnxCopy, VecZnxFillUniform}, layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision, - compressed::{Decompress, GGLWESwitchingKeyCompressed}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyToMut, Rank, RingDegree, + TorusPrecision, + compressed::{ + GLWESwitchingKeyCompressed, GLWESwitchingKeyCompressedAlloc, GLWESwitchingKeyCompressedToMut, + GLWESwitchingKeyCompressedToRef, GLWESwitchingKeyDecompress, + }, }; use std::fmt; #[derive(PartialEq, Eq, Clone)] -pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GGLWESwitchingKeyCompressed<D>); +pub struct LWEToGLWESwitchingKeyCompressed<D: Data>(pub(crate) GLWESwitchingKeyCompressed<D>); impl<D: Data> LWEInfos for LWEToGLWESwitchingKeyCompressed<D> { - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -83,63 +86,138 @@ self.0.write_to(writer)

} } -impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait LWEToGLWESwitchingKeyCompressedAlloc +where + Self: GLWESwitchingKeyCompressedAlloc, +{ + fn alloc_lwe_to_glwe_switching_key_compressed( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_out: Rank, + dnum: Dnum, + ) -> LWEToGLWESwitchingKeyCompressed<Vec<u8>> { + LWEToGLWESwitchingKeyCompressed(self.alloc_glwe_switching_key_compressed(base2k, k, Rank(1), rank_out, dnum, Dsize(1))) + } + + fn alloc_lwe_to_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> LWEToGLWESwitchingKeyCompressed<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for LWEToGLWESwitchingKeyCompressed" ); - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, "rank_in > 1 is not supported for LWEToGLWESwitchingKeyCompressed" ); - Self(GGLWESwitchingKeyCompressed::alloc(infos)) + self.alloc_lwe_to_glwe_switching_key_compressed(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self { - Self(GGLWESwitchingKeyCompressed::alloc_with( - n, - base2k, - k, - Rank(1), - rank_out, - dnum, - Dsize(1), - )) + fn bytes_of_lwe_to_glwe_switching_key_compressed(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key_compressed(base2k, k, Rank(1), dnum, Dsize(1)) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_lwe_to_glwe_switching_key_compressed_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - debug_assert_eq!( - infos.rank_in().0, + assert_eq!( + infos.dsize().0, 1, - "rank_in > 1 is not supported for LWEToGLWESwitchingKey" + "dsize > 1 is not supported for LWEToGLWESwitchingKeyCompressed" ); - debug_assert_eq!( - infos.dsize().0, + assert_eq!( + infos.rank_in().0, 1, - "dsize > 1 is not supported for LWEToGLWESwitchingKey" + "rank_in > 1 is not supported for LWEToGLWESwitchingKeyCompressed" ); - GGLWESwitchingKeyCompressed::alloc_bytes(infos) + self.bytes_of_lwe_to_glwe_switching_key_compressed(infos.base2k(), infos.k(), infos.dnum()) } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { - GGLWESwitchingKeyCompressed::alloc_bytes_with(n, base2k, k, Rank(1), dnum, Dsize(1)) +impl LWEToGLWESwitchingKeyCompressed<Vec<u8>> { + pub fn alloc<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyCompressedAlloc, + { + module.alloc_lwe_to_glwe_switching_key_compressed_from_infos(infos) + } + + pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self + where + M: LWEToGLWESwitchingKeyCompressedAlloc, + { + module.alloc_lwe_to_glwe_switching_key_compressed(base2k, k, rank_out, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyCompressedAlloc, + { + module.bytes_of_lwe_to_glwe_switching_key_compressed_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize + where + M: LWEToGLWESwitchingKeyCompressedAlloc, + { + module.bytes_of_lwe_to_glwe_switching_key_compressed(base2k, k, dnum) } } -impl<D: DataMut, DR: DataRef, B: Backend> Decompress<B, LWEToGLWESwitchingKeyCompressed<DR>> for LWEToGLWESwitchingKey<D> +pub trait LWEToGLWESwitchingKeyDecompress +where + Self: GLWESwitchingKeyDecompress, +{ + fn decompress_lwe_to_glwe_switching_key<R, O>(&self, res: &mut R, other: &O) + where + R: LWEToGLWESwitchingKeyToMut, + O: LWEToGLWESwitchingKeyCompressedToRef, + { + self.decompress_glwe_switching_key(&mut res.to_mut().0, &other.to_ref().0); + } +} + +impl<B: Backend> LWEToGLWESwitchingKeyDecompress for Module<B> where Self: GLWESwitchingKeyDecompress {} + +impl<D: DataMut> LWEToGLWESwitchingKey<D> { + pub fn decompress<O, M>(&mut self, module: &M, other: &O) + where + O: LWEToGLWESwitchingKeyCompressedToRef, + M: LWEToGLWESwitchingKeyDecompress, + { + module.decompress_lwe_to_glwe_switching_key(self, other); + } +} + +pub trait LWEToGLWESwitchingKeyCompressedToRef { + fn to_ref(&self) -> LWEToGLWESwitchingKeyCompressed<&[u8]>; +} + +impl<D: DataRef> LWEToGLWESwitchingKeyCompressedToRef for LWEToGLWESwitchingKeyCompressed<D> where - Module<B>: VecZnxFillUniform + VecZnxCopy, + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToRef, { - fn decompress(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKeyCompressed<DR>) { - self.0.decompress(module, &other.0); + fn to_ref(&self) -> LWEToGLWESwitchingKeyCompressed<&[u8]> { + LWEToGLWESwitchingKeyCompressed(self.0.to_ref()) + } +} + +pub trait LWEToGLWESwitchingKeyCompressedToMut { + fn to_mut(&mut self) -> LWEToGLWESwitchingKeyCompressed<&mut [u8]>; +} + +impl<D: DataMut> LWEToGLWESwitchingKeyCompressedToMut for LWEToGLWESwitchingKeyCompressed<D> +where + GLWESwitchingKeyCompressed<D>: GLWESwitchingKeyCompressedToMut, +{ + fn to_mut(&mut self) -> LWEToGLWESwitchingKeyCompressed<&mut [u8]> { + LWEToGLWESwitchingKeyCompressed(self.0.to_mut()) } }
M poulpy-core/src/layouts/compressed/mod.rs → poulpy-core/src/layouts/compressed/mod.rs

@@ -19,9 +19,3 @@ pub use glwe_to_lwe_ksk::*;

pub use lwe_ct::*; pub use lwe_ksk::*; pub use lwe_to_glwe_ksk::*; - -use poulpy_hal::layouts::{Backend, Module}; - -pub trait Decompress<B: Backend, C> { - fn decompress(&mut self, module: &Module<B>, other: &C); -}
M poulpy-core/src/layouts/gglwe_atk.rs → poulpy-core/src/layouts/gglwe_atk.rs

@@ -1,18 +1,19 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision, + Base2K, Dnum, Dsize, GGLWEInfos, GLWE, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut, + GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct GGLWEAutomorphismKeyLayout { - pub n: Degree, +pub struct AutomorphismKeyLayout { + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank: Rank,

@@ -21,19 +22,19 @@ pub dsize: Dsize,

} #[derive(PartialEq, Eq, Clone)] -pub struct GGLWEAutomorphismKey<D: Data> { - pub(crate) key: GGLWESwitchingKey<D>, +pub struct AutomorphismKey<D: Data> { + pub(crate) key: GLWESwitchingKey<D>, pub(crate) p: i64, } -impl<D: Data> GGLWEAutomorphismKey<D> { +impl<D: Data> AutomorphismKey<D> { pub fn p(&self) -> i64 { self.p } } -impl<D: Data> LWEInfos for GGLWEAutomorphismKey<D> { - fn n(&self) -> Degree { +impl<D: Data> LWEInfos for AutomorphismKey<D> { + fn n(&self) -> RingDegree { self.key.n() }

@@ -50,13 +51,13 @@ self.key.size()

} } -impl<D: Data> GLWEInfos for GGLWEAutomorphismKey<D> { +impl<D: Data> GLWEInfos for AutomorphismKey<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWEAutomorphismKey<D> { +impl<D: Data> GGLWEInfos for AutomorphismKey<D> { fn rank_in(&self) -> Rank { self.key.rank_in() }

@@ -74,7 +75,7 @@ self.key.dnum()

} } -impl LWEInfos for GGLWEAutomorphismKeyLayout { +impl LWEInfos for AutomorphismKeyLayout { fn base2k(&self) -> Base2K { self.base2k }

@@ -83,18 +84,18 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n } } -impl GLWEInfos for GGLWEAutomorphismKeyLayout { +impl GLWEInfos for AutomorphismKeyLayout { fn rank(&self) -> Rank { self.rank } } -impl GGLWEInfos for GGLWEAutomorphismKeyLayout { +impl GGLWEInfos for AutomorphismKeyLayout { fn rank_in(&self) -> Rank { self.rank }

@@ -112,84 +113,164 @@ self.dnum

} } -impl<D: DataRef> fmt::Debug for GGLWEAutomorphismKey<D> { +impl<D: DataRef> fmt::Debug for AutomorphismKey<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWEAutomorphismKey<D> { +impl<D: DataMut> FillUniform for AutomorphismKey<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.key.fill_uniform(log_bound, source); } } -impl<D: DataRef> fmt::Display for GGLWEAutomorphismKey<D> { +impl<D: DataRef> fmt::Display for AutomorphismKey<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(AutomorphismKey: p={}) {}", self.p, self.key) } } -impl GGLWEAutomorphismKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +impl<B: Backend> AutomorphismKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {} + +pub trait AutomorphismKeyAlloc +where + Self: GLWESwitchingKeyAlloc, +{ + fn alloc_automorphism_key( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> AutomorphismKey<Vec<u8>> { + AutomorphismKey { + key: self.alloc_glwe_switching_key(base2k, k, rank, rank, dnum, dsize), + p: 0, + } + } + + fn alloc_automorphism_key_from_infos<A>(&self, infos: &A) -> AutomorphismKey<Vec<u8>> + where + A: GGLWEInfos, + { + self.alloc_automorphism_key( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) + } + + fn bytes_of_automorphism_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { + self.bytes_of_glwe_switching_key(base2k, k, rank, rank, dnum, dsize) + } + + fn bytes_of_automorphism_key_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { assert_eq!( infos.rank_in(), infos.rank_out(), - "rank_in != rank_out is not supported for GGLWEAutomorphismKey" + "rank_in != rank_out is not supported for AutomorphismKey" ); - GGLWEAutomorphismKey { - key: GGLWESwitchingKey::alloc(infos), - p: 0, - } + self.bytes_of_automorphism_key( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) } +} - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self { - GGLWEAutomorphismKey { - key: GGLWESwitchingKey::alloc_with(n, base2k, k, rank, rank, dnum, dsize), - p: 0, - } +impl AutomorphismKey<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: AutomorphismKeyAlloc, + { + module.alloc_automorphism_key_from_infos(infos) + } + + pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: AutomorphismKeyAlloc, + { + module.alloc_automorphism_key(base2k, k, rank, dnum, dsize) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GGLWEInfos, + M: AutomorphismKeyAlloc, { - assert_eq!( - infos.rank_in(), - infos.rank_out(), - "rank_in != rank_out is not supported for GGLWEAutomorphismKey" - ); - GGLWESwitchingKey::alloc_bytes(infos) + module.bytes_of_automorphism_key_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: AutomorphismKeyAlloc, + { + module.bytes_of_automorphism_key(base2k, k, rank, dnum, dsize) + } +} + +pub trait AutomorphismKeyToMut { + fn to_mut(&mut self) -> AutomorphismKey<&mut [u8]>; +} + +impl<D: DataMut> AutomorphismKeyToMut for AutomorphismKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToMut, +{ + fn to_mut(&mut self) -> AutomorphismKey<&mut [u8]> { + AutomorphismKey { + key: self.key.to_mut(), + p: self.p, + } } +} - pub fn bytes_of(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { - GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rank, rank, dnum, dsize) +pub trait AutomorphismKeyToRef { + fn to_ref(&self) -> AutomorphismKey<&[u8]>; +} + +impl<D: DataRef> AutomorphismKeyToRef for AutomorphismKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToRef, +{ + fn to_ref(&self) -> AutomorphismKey<&[u8]> { + AutomorphismKey { + p: self.p, + key: self.key.to_ref(), + } } } -impl<D: DataRef> GGLWEAutomorphismKey<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { +impl<D: DataRef> AutomorphismKey<D> { + pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> { self.key.at(row, col) } } -impl<D: DataMut> GGLWEAutomorphismKey<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { +impl<D: DataMut> AutomorphismKey<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> { self.key.at_mut(row, col) } } -impl<D: DataMut> ReaderFrom for GGLWEAutomorphismKey<D> { +impl<D: DataMut> ReaderFrom for AutomorphismKey<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.p = reader.read_u64::<LittleEndian>()? as i64; self.key.read_from(reader) } } -impl<D: DataRef> WriterTo for GGLWEAutomorphismKey<D> { +impl<D: DataRef> WriterTo for AutomorphismKey<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::<LittleEndian>(self.p as u64)?; self.key.write_to(writer)
M poulpy-core/src/layouts/gglwe_ct.rs → poulpy-core/src/layouts/gglwe_ct.rs

@@ -1,9 +1,11 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, MatZnx, ReaderFrom, WriterTo, ZnxInfos}, + layouts::{ + Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos, + }, source::Source, }; -use crate::layouts::{Base2K, BuildError, Degree, Dnum, Dsize, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{Base2K, Dnum, Dsize, GLWE, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt;

@@ -16,8 +18,8 @@ fn dnum(&self) -> Dnum;

fn dsize(&self) -> Dsize; fn rank_in(&self) -> Rank; fn rank_out(&self) -> Rank; - fn layout(&self) -> GGLWECiphertextLayout { - GGLWECiphertextLayout { + fn gglwe_layout(&self) -> GGLWELayout { + GGLWELayout { n: self.n(), base2k: self.base2k(), k: self.k(),

@@ -29,9 +31,13 @@ }

} } +pub trait SetGGLWEInfos { + fn set_dsize(&mut self, dsize: usize); +} + #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct GGLWECiphertextLayout { - pub n: Degree, +pub struct GGLWELayout { + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank_in: Rank,

@@ -40,7 +46,7 @@ pub dnum: Dnum,

pub dsize: Dsize, } -impl LWEInfos for GGLWECiphertextLayout { +impl LWEInfos for GGLWELayout { fn base2k(&self) -> Base2K { self.base2k }

@@ -49,18 +55,18 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n } } -impl GLWEInfos for GGLWECiphertextLayout { +impl GLWEInfos for GGLWELayout { fn rank(&self) -> Rank { self.rank_out } } -impl GGLWEInfos for GGLWECiphertextLayout { +impl GGLWEInfos for GGLWELayout { fn rank_in(&self) -> Rank { self.rank_in }

@@ -79,14 +85,14 @@ }

} #[derive(PartialEq, Eq, Clone)] -pub struct GGLWECiphertext<D: Data> { +pub struct GGLWE<D: Data> { pub(crate) data: MatZnx<D>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K, pub(crate) dsize: Dsize, } -impl<D: Data> LWEInfos for GGLWECiphertext<D> { +impl<D: Data> LWEInfos for GGLWE<D> { fn base2k(&self) -> Base2K { self.base2k }

@@ -95,8 +101,8 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -104,13 +110,13 @@ self.data.size()

} } -impl<D: Data> GLWEInfos for GGLWECiphertext<D> { +impl<D: Data> GLWEInfos for GGLWE<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWECiphertext<D> { +impl<D: Data> GGLWEInfos for GGLWE<D> { fn rank_in(&self) -> Rank { Rank(self.data.cols_in() as u32) }

@@ -128,136 +134,35 @@ Dnum(self.data.rows() as u32)

} } -pub struct GGLWECiphertextBuilder<D: Data> { - data: Option<MatZnx<D>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, - dsize: Option<Dsize>, -} - -impl<D: Data> GGLWECiphertext<D> { - #[inline] - pub fn builder() -> GGLWECiphertextBuilder<D> { - GGLWECiphertextBuilder { - data: None, - base2k: None, - k: None, - dsize: None, - } - } -} - -impl GGLWECiphertextBuilder<Vec<u8>> { - #[inline] - pub fn layout<A>(mut self, infos: &A) -> Self - where - A: GGLWEInfos, - { - self.data = Some(MatZnx::alloc( - infos.n().into(), - infos.dnum().into(), - infos.rank_in().into(), - (infos.rank_out() + 1).into(), - infos.size(), - )); - self.base2k = Some(infos.base2k()); - self.k = Some(infos.k()); - self.dsize = Some(infos.dsize()); - self - } -} - -impl<D: Data> GGLWECiphertextBuilder<D> { - #[inline] - pub fn data(mut self, data: MatZnx<D>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self - } - - #[inline] - pub fn dsize(mut self, dsize: Dsize) -> Self { - self.dsize = Some(dsize); - self - } - - pub fn build(self) -> Result<GGLWECiphertext<D>, BuildError> { - let data: MatZnx<D> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?; - - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if dsize == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GGLWECiphertext { - data, - base2k, - k, - dsize, - }) - } -} - -impl<D: DataRef> GGLWECiphertext<D> { +impl<D: DataRef> GGLWE<D> { pub fn data(&self) -> &MatZnx<D> { &self.data } } -impl<D: DataMut> GGLWECiphertext<D> { +impl<D: DataMut> GGLWE<D> { pub fn data_mut(&mut self) -> &mut MatZnx<D> { &mut self.data } } -impl<D: DataRef> fmt::Debug for GGLWECiphertext<D> { +impl<D: DataRef> fmt::Debug for GGLWE<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWECiphertext<D> { +impl<D: DataMut> FillUniform for GGLWE<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl<D: DataRef> fmt::Display for GGLWECiphertext<D> { +impl<D: DataRef> fmt::Display for GGLWE<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "(GGLWECiphertext: k={} base2k={} dsize={}) {}", + "(GGLWE: k={} base2k={} dsize={}) {}", self.k().0, self.base2k().0, self.dsize().0,

@@ -266,53 +171,39 @@ )

} } -impl<D: DataRef> GGLWECiphertext<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - GLWECiphertext::builder() - .data(self.data.at(row, col)) - .base2k(self.base2k()) - .k(self.k()) - .build() - .unwrap() +impl<D: DataRef> GGLWE<D> { + pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.at(row, col), + } } } -impl<D: DataMut> GGLWECiphertext<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext::builder() - .base2k(self.base2k()) - .k(self.k()) - .data(self.data.at_mut(row, col)) - .build() - .unwrap() +impl<D: DataMut> GGLWE<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.at_mut(row, col), + } } } -impl GGLWECiphertext<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: GGLWEInfos, - { - Self::alloc_with( - infos.n(), - infos.base2k(), - infos.k(), - infos.rank_in(), - infos.rank_out(), - infos.dnum(), - infos.dsize(), - ) - } - - pub fn alloc_with( - n: Degree, +pub trait GGLWEAlloc +where + Self: GetRingDegree, +{ + fn alloc_gglwe( + &self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> Self { + ) -> GGLWE<Vec<u8>> { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -327,9 +218,9 @@ dnum.0,

dsize.0, ); - Self { + GGLWE { data: MatZnx::alloc( - n.into(), + self.ring_degree().into(), dnum.into(), rank_in.into(), (rank_out + 1).into(),

@@ -341,12 +232,11 @@ dsize,

} } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn alloc_glwe_from_infos<A>(&self, infos: &A) -> GGLWE<Vec<u8>> where A: GGLWEInfos, { - Self::alloc_bytes_with( - infos.n(), + self.alloc_gglwe( infos.base2k(), infos.k(), infos.rank_in(),

@@ -356,8 +246,8 @@ infos.dsize(),

) } - pub fn alloc_bytes_with( - n: Degree, + fn bytes_of_gglwe( + &self, base2k: Base2K, k: TorusPrecision, rank_in: Rank,

@@ -379,17 +269,111 @@ dnum.0,

dsize.0, ); - MatZnx::alloc_bytes( - n.into(), + MatZnx::bytes_of( + self.ring_degree().into(), dnum.into(), rank_in.into(), (rank_out + 1).into(), k.0.div_ceil(base2k.0) as usize, ) } + + fn bytes_of_gglwe_from_infos<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.bytes_of_gglwe( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.rank_out(), + infos.dnum(), + infos.dsize(), + ) + } } -impl<D: DataMut> ReaderFrom for GGLWECiphertext<D> { +impl<B: Backend> GGLWEAlloc for Module<B> where Self: GetRingDegree {} + +impl GGLWE<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GGLWEAlloc, + { + module.alloc_glwe_from_infos(infos) + } + + pub fn alloc<M>( + module: &M, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> Self + where + M: GGLWEAlloc, + { + module.alloc_gglwe(base2k, k, rank_in, rank_out, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GGLWEAlloc, + { + module.bytes_of_gglwe_from_infos(infos) + } + + pub fn bytes_of<M>( + module: &M, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize + where + M: GGLWEAlloc, + { + module.bytes_of_gglwe(base2k, k, rank_in, rank_out, dnum, dsize) + } +} + +pub trait GGLWEToMut { + fn to_mut(&mut self) -> GGLWE<&mut [u8]>; +} + +impl<D: DataMut> GGLWEToMut for GGLWE<D> { + fn to_mut(&mut self) -> GGLWE<&mut [u8]> { + GGLWE { + k: self.k(), + base2k: self.base2k(), + dsize: self.dsize(), + data: self.data.to_mut(), + } + } +} + +pub trait GGLWEToRef { + fn to_ref(&self) -> GGLWE<&[u8]>; +} + +impl<D: DataRef> GGLWEToRef for GGLWE<D> { + fn to_ref(&self) -> GGLWE<&[u8]> { + GGLWE { + k: self.k(), + base2k: self.base2k(), + dsize: self.dsize(), + data: self.data.to_ref(), + } + } +} + +impl<D: DataMut> ReaderFrom for GGLWE<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -398,7 +382,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for GGLWECiphertext<D> { +impl<D: DataRef> WriterTo for GGLWE<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.0)?; writer.write_u32::<LittleEndian>(self.base2k.0)?;
M poulpy-core/src/layouts/gglwe_ksk.rs → poulpy-core/src/layouts/gglwe_ksk.rs

@@ -1,18 +1,19 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision, + Base2K, Dnum, Dsize, GGLWE, GGLWEAlloc, GGLWEInfos, GGLWEToMut, GGLWEToRef, GLWE, GLWEInfos, LWEInfos, Rank, RingDegree, + TorusPrecision, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct GGLWESwitchingKeyLayout { - pub n: Degree, +pub struct GLWESwitchingKeyLayout { + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank_in: Rank,

@@ -21,8 +22,8 @@ pub dnum: Dnum,

pub dsize: Dsize, } -impl LWEInfos for GGLWESwitchingKeyLayout { - fn n(&self) -> Degree { +impl LWEInfos for GLWESwitchingKeyLayout { + fn n(&self) -> RingDegree { self.n }

@@ -35,13 +36,13 @@ self.k

} } -impl GLWEInfos for GGLWESwitchingKeyLayout { +impl GLWEInfos for GLWESwitchingKeyLayout { fn rank(&self) -> Rank { self.rank_out() } } -impl GGLWEInfos for GGLWESwitchingKeyLayout { +impl GGLWEInfos for GLWESwitchingKeyLayout { fn rank_in(&self) -> Rank { self.rank_in }

@@ -60,14 +61,44 @@ }

} #[derive(PartialEq, Eq, Clone)] -pub struct GGLWESwitchingKey<D: Data> { - pub(crate) key: GGLWECiphertext<D>, +pub struct GLWESwitchingKey<D: Data> { + pub(crate) key: GGLWE<D>, pub(crate) sk_in_n: usize, // Degree of sk_in pub(crate) sk_out_n: usize, // Degree of sk_out } -impl<D: Data> LWEInfos for GGLWESwitchingKey<D> { - fn n(&self) -> Degree { +pub(crate) trait GLWESwitchingKeySetMetaData { + fn set_sk_in_n(&mut self, sk_in_n: usize); + fn set_sk_out_n(&mut self, sk_out_n: usize); +} + +impl<D: DataMut> GLWESwitchingKeySetMetaData for GLWESwitchingKey<D> { + fn set_sk_in_n(&mut self, sk_in_n: usize) { + self.sk_in_n = sk_in_n + } + + fn set_sk_out_n(&mut self, sk_out_n: usize) { + self.sk_out_n = sk_out_n + } +} + +pub(crate) trait GLWESwtichingKeyGetMetaData { + fn sk_in_n(&self) -> usize; + fn sk_out_n(&self) -> usize; +} + +impl<D: DataRef> GLWESwtichingKeyGetMetaData for GLWESwitchingKey<D> { + fn sk_in_n(&self) -> usize { + self.sk_in_n + } + + fn sk_out_n(&self) -> usize { + self.sk_out_n + } +} + +impl<D: Data> LWEInfos for GLWESwitchingKey<D> { + fn n(&self) -> RingDegree { self.key.n() }

@@ -84,13 +115,13 @@ self.key.size()

} } -impl<D: Data> GLWEInfos for GGLWESwitchingKey<D> { +impl<D: Data> GLWEInfos for GLWESwitchingKey<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GGLWESwitchingKey<D> { +impl<D: Data> GGLWEInfos for GLWESwitchingKey<D> { fn rank_in(&self) -> Rank { self.key.rank_in() }

@@ -108,13 +139,13 @@ self.key.dnum()

} } -impl<D: DataRef> fmt::Debug for GGLWESwitchingKey<D> { +impl<D: DataRef> fmt::Debug for GLWESwitchingKey<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataRef> fmt::Display for GGLWESwitchingKey<D> { +impl<D: DataRef> fmt::Display for GLWESwitchingKey<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f,

@@ -126,73 +157,170 @@ )

} } -impl<D: DataMut> FillUniform for GGLWESwitchingKey<D> { +impl<D: DataMut> FillUniform for GLWESwitchingKey<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.key.fill_uniform(log_bound, source); } } -impl GGLWESwitchingKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: GGLWEInfos, - { - GGLWESwitchingKey { - key: GGLWECiphertext::alloc(infos), +pub trait GLWESwitchingKeyAlloc +where + Self: GGLWEAlloc, +{ + fn alloc_glwe_switching_key( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> GLWESwitchingKey<Vec<u8>> { + GLWESwitchingKey { + key: self.alloc_gglwe(base2k, k, rank_in, rank_out, dnum, dsize), sk_in_n: 0, sk_out_n: 0, } } - pub fn alloc_with( - n: Degree, + fn alloc_glwe_switching_key_from_infos<A>(&self, infos: &A) -> GLWESwitchingKey<Vec<u8>> + where + A: GGLWEInfos, + { + self.alloc_glwe_switching_key( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.rank_out(), + infos.dnum(), + infos.dsize(), + ) + } + + fn bytes_of_glwe_switching_key( + &self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> Self { - GGLWESwitchingKey { - key: GGLWECiphertext::alloc_with(n, base2k, k, rank_in, rank_out, dnum, dsize), - sk_in_n: 0, - sk_out_n: 0, - } + ) -> usize { + self.bytes_of_gglwe(base2k, k, rank_in, rank_out, dnum, dsize) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_glwe_switching_key_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - GGLWECiphertext::alloc_bytes(infos) + self.bytes_of_glwe_switching_key( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.rank_out(), + infos.dnum(), + infos.dsize(), + ) } +} - pub fn alloc_bytes_with( - n: Degree, +impl<B: Backend> GLWESwitchingKeyAlloc for Module<B> where Self: GGLWEAlloc {} + +impl GLWESwitchingKey<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GLWESwitchingKeyAlloc, + { + module.alloc_glwe_switching_key_from_infos(infos) + } + + pub fn alloc<M>( + module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> usize { - GGLWECiphertext::alloc_bytes_with(n, base2k, k, rank_in, rank_out, dnum, dsize) + ) -> Self + where + M: GLWESwitchingKeyAlloc, + { + module.alloc_glwe_switching_key(base2k, k, rank_in, rank_out, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GLWESwitchingKeyAlloc, + { + module.bytes_of_glwe_switching_key_from_infos(infos) + } + + pub fn bytes_of<M>( + module: &M, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize + where + M: GLWESwitchingKeyAlloc, + { + module.bytes_of_glwe_switching_key(base2k, k, rank_in, rank_out, dnum, dsize) } } -impl<D: DataRef> GGLWESwitchingKey<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { +pub trait GLWESwitchingKeyToMut { + fn to_mut(&mut self) -> GLWESwitchingKey<&mut [u8]>; +} + +impl<D: DataMut> GLWESwitchingKeyToMut for GLWESwitchingKey<D> +where + GGLWE<D>: GGLWEToMut, +{ + fn to_mut(&mut self) -> GLWESwitchingKey<&mut [u8]> { + GLWESwitchingKey { + key: self.key.to_mut(), + sk_in_n: self.sk_in_n, + sk_out_n: self.sk_out_n, + } + } +} + +pub trait GLWESwitchingKeyToRef { + fn to_ref(&self) -> GLWESwitchingKey<&[u8]>; +} + +impl<D: DataRef> GLWESwitchingKeyToRef for GLWESwitchingKey<D> +where + GGLWE<D>: GGLWEToRef, +{ + fn to_ref(&self) -> GLWESwitchingKey<&[u8]> { + GLWESwitchingKey { + key: self.key.to_ref(), + sk_in_n: self.sk_in_n, + sk_out_n: self.sk_out_n, + } + } +} + +impl<D: DataRef> GLWESwitchingKey<D> { + pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> { self.key.at(row, col) } } -impl<D: DataMut> GGLWESwitchingKey<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { +impl<D: DataMut> GLWESwitchingKey<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> { self.key.at_mut(row, col) } } -impl<D: DataMut> ReaderFrom for GGLWESwitchingKey<D> { +impl<D: DataMut> ReaderFrom for GLWESwitchingKey<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.sk_in_n = reader.read_u64::<LittleEndian>()? as usize; self.sk_out_n = reader.read_u64::<LittleEndian>()? as usize;

@@ -200,7 +328,7 @@ self.key.read_from(reader)

} } -impl<D: DataRef> WriterTo for GGLWESwitchingKey<D> { +impl<D: DataRef> WriterTo for GLWESwitchingKey<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::<LittleEndian>(self.sk_in_n as u64)?; writer.write_u64::<LittleEndian>(self.sk_out_n as u64)?;
M poulpy-core/src/layouts/gglwe_tsk.rs → poulpy-core/src/layouts/gglwe_tsk.rs

@@ -1,16 +1,19 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; -use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{ + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut, + GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision, +}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt; #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct GGLWETensorKeyLayout { - pub n: Degree, +pub struct TensorKeyLayout { + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank: Rank,

@@ -19,12 +22,12 @@ pub dsize: Dsize,

} #[derive(PartialEq, Eq, Clone)] -pub struct GGLWETensorKey<D: Data> { - pub(crate) keys: Vec<GGLWESwitchingKey<D>>, +pub struct TensorKey<D: Data> { + pub(crate) keys: Vec<GLWESwitchingKey<D>>, } -impl<D: Data> LWEInfos for GGLWETensorKey<D> { - fn n(&self) -> Degree { +impl<D: Data> LWEInfos for TensorKey<D> { + fn n(&self) -> RingDegree { self.keys[0].n() }

@@ -41,13 +44,13 @@ self.keys[0].size()

} } -impl<D: Data> GLWEInfos for GGLWETensorKey<D> { +impl<D: Data> GLWEInfos for TensorKey<D> { fn rank(&self) -> Rank { self.keys[0].rank_out() } } -impl<D: Data> GGLWEInfos for GGLWETensorKey<D> { +impl<D: Data> GGLWEInfos for TensorKey<D> { fn rank_in(&self) -> Rank { self.rank_out() }

@@ -65,8 +68,8 @@ self.keys[0].dnum()

} } -impl LWEInfos for GGLWETensorKeyLayout { - fn n(&self) -> Degree { +impl LWEInfos for TensorKeyLayout { + fn n(&self) -> RingDegree { self.n }

@@ -79,13 +82,13 @@ self.k

} } -impl GLWEInfos for GGLWETensorKeyLayout { +impl GLWEInfos for TensorKeyLayout { fn rank(&self) -> Rank { self.rank_out() } } -impl GGLWEInfos for GGLWETensorKeyLayout { +impl GGLWEInfos for TensorKeyLayout { fn rank_in(&self) -> Rank { self.rank }

@@ -103,21 +106,21 @@ self.dnum

} } -impl<D: DataRef> fmt::Debug for GGLWETensorKey<D> { +impl<D: DataRef> fmt::Debug for TensorKey<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GGLWETensorKey<D> { +impl<D: DataMut> FillUniform for TensorKey<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.keys .iter_mut() - .for_each(|key: &mut GGLWESwitchingKey<D>| key.fill_uniform(log_bound, source)) + .for_each(|key: &mut GLWESwitchingKey<D>| key.fill_uniform(log_bound, source)) } } -impl<D: DataRef> fmt::Display for GGLWETensorKey<D> { +impl<D: DataRef> fmt::Display for TensorKey<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "(GLWETensorKey)",)?; for (i, key) in self.keys.iter().enumerate() {

@@ -127,8 +130,20 @@ Ok(())

} } -impl GGLWETensorKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait TensorKeyAlloc +where + Self: GLWESwitchingKeyAlloc, +{ + fn alloc_tensor_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> TensorKey<Vec<u8>> { + let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1); + TensorKey { + keys: (0..pairs) + .map(|_| self.alloc_glwe_switching_key(base2k, k, Rank(1), rank, dnum, dsize)) + .collect(), + } + } + + fn alloc_tensor_key_from_infos<A>(&self, infos: &A) -> TensorKey<Vec<u8>> where A: GGLWEInfos, {

@@ -137,34 +152,21 @@ infos.rank_in(),

infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKey" ); - Self::alloc_with( - infos.n(), + self.alloc_tensor_key( infos.base2k(), infos.k(), - infos.rank_out(), + infos.rank(), infos.dnum(), infos.dsize(), ) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self { - let mut keys: Vec<GGLWESwitchingKey<Vec<u8>>> = Vec::new(); - let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1); - (0..pairs).for_each(|_| { - keys.push(GGLWESwitchingKey::alloc_with( - n, - base2k, - k, - Rank(1), - rank, - dnum, - dsize, - )); - }); - Self { keys } + fn bytes_of_tensor_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { + let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize; + pairs * self.bytes_of_glwe_switching_key(base2k, k, Rank(1), rank, dnum, dsize) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_tensor_key_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, {

@@ -173,29 +175,53 @@ infos.rank_in(),

infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKey" ); - let rank_out: usize = infos.rank_out().into(); - let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1); - pairs - * GGLWESwitchingKey::alloc_bytes_with( - infos.n(), - infos.base2k(), - infos.k(), - Rank(1), - infos.rank_out(), - infos.dnum(), - infos.dsize(), - ) + self.bytes_of_tensor_key( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { - let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize; - pairs * GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), rank, dnum, dsize) +impl<B: Backend> TensorKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {} + +impl TensorKey<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: TensorKeyAlloc, + { + module.alloc_tensor_key_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: TensorKeyAlloc, + { + module.alloc_tensor_key(base2k, k, rank, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: TensorKeyAlloc, + { + module.bytes_of_tensor_key_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: TensorKeyAlloc, + { + module.bytes_of_tensor_key(base2k, k, rank, dnum, dsize) } } -impl<D: DataMut> GGLWETensorKey<D> { +impl<D: DataMut> TensorKey<D> { // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKey<D> { + pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKey<D> { if i > j { std::mem::swap(&mut i, &mut j); };

@@ -204,9 +230,9 @@ &mut self.keys[i * rank + j - (i * (i + 1) / 2)]

} } -impl<D: DataRef> GGLWETensorKey<D> { +impl<D: DataRef> TensorKey<D> { // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKey<D> { + pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKey<D> { if i > j { std::mem::swap(&mut i, &mut j); };

@@ -215,7 +241,7 @@ &self.keys[i * rank + j - (i * (i + 1) / 2)]

} } -impl<D: DataMut> ReaderFrom for GGLWETensorKey<D> { +impl<D: DataMut> ReaderFrom for TensorKey<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { let len: usize = reader.read_u64::<LittleEndian>()? as usize; if self.keys.len() != len {

@@ -231,7 +257,7 @@ Ok(())

} } -impl<D: DataRef> WriterTo for GGLWETensorKey<D> { +impl<D: DataRef> WriterTo for TensorKey<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u64::<LittleEndian>(self.keys.len() as u64)?; for key in &self.keys {

@@ -240,3 +266,33 @@ }

Ok(()) } } + +pub trait TensorKeyToRef { + fn to_ref(&self) -> TensorKey<&[u8]>; +} + +impl<D: DataRef> TensorKeyToRef for TensorKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToRef, +{ + fn to_ref(&self) -> TensorKey<&[u8]> { + TensorKey { + keys: self.keys.iter().map(|c| c.to_ref()).collect(), + } + } +} + +pub trait TensorKeyToMut { + fn to_mut(&mut self) -> TensorKey<&mut [u8]>; +} + +impl<D: DataMut> TensorKeyToMut for TensorKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToMut, +{ + fn to_mut(&mut self) -> TensorKey<&mut [u8]> { + TensorKey { + keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(), + } + } +}
M poulpy-core/src/layouts/ggsw_ct.rs → poulpy-core/src/layouts/ggsw_ct.rs

@@ -1,10 +1,12 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, MatZnx, ReaderFrom, WriterTo, ZnxInfos}, + layouts::{ + Backend, Data, DataMut, DataRef, FillUniform, MatZnx, MatZnxToMut, MatZnxToRef, Module, ReaderFrom, WriterTo, ZnxInfos, + }, source::Source, }; use std::fmt; -use crate::layouts::{Base2K, BuildError, Degree, Dnum, Dsize, GLWECiphertext, GLWEInfos, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{Base2K, Dnum, Dsize, GLWE, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision}; pub trait GGSWInfos where

@@ -12,8 +14,8 @@ Self: GLWEInfos,

{ fn dnum(&self) -> Dnum; fn dsize(&self) -> Dsize; - fn ggsw_layout(&self) -> GGSWCiphertextLayout { - GGSWCiphertextLayout { + fn ggsw_layout(&self) -> GGSWLayout { + GGSWLayout { n: self.n(), base2k: self.base2k(), k: self.k(),

@@ -25,8 +27,8 @@ }

} #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct GGSWCiphertextLayout { - pub n: Degree, +pub struct GGSWLayout { + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank: Rank,

@@ -34,7 +36,7 @@ pub dnum: Dnum,

pub dsize: Dsize, } -impl LWEInfos for GGSWCiphertextLayout { +impl LWEInfos for GGSWLayout { fn base2k(&self) -> Base2K { self.base2k }

@@ -43,17 +45,17 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n } } -impl GLWEInfos for GGSWCiphertextLayout { +impl GLWEInfos for GGSWLayout { fn rank(&self) -> Rank { self.rank } } -impl GGSWInfos for GGSWCiphertextLayout { +impl GGSWInfos for GGSWLayout { fn dsize(&self) -> Dsize { self.dsize }

@@ -64,16 +66,16 @@ }

} #[derive(PartialEq, Eq, Clone)] -pub struct GGSWCiphertext<D: Data> { +pub struct GGSW<D: Data> { pub(crate) data: MatZnx<D>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K, pub(crate) dsize: Dsize, } -impl<D: Data> LWEInfos for GGSWCiphertext<D> { - fn n(&self) -> Degree { - Degree(self.data.n() as u32) +impl<D: Data> LWEInfos for GGSW<D> { + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn base2k(&self) -> Base2K {

@@ -89,13 +91,13 @@ self.data.size()

} } -impl<D: Data> GLWEInfos for GGSWCiphertext<D> { +impl<D: Data> GLWEInfos for GGSW<D> { fn rank(&self) -> Rank { Rank(self.data.cols_out() as u32 - 1) } } -impl<D: Data> GGSWInfos for GGSWCiphertext<D> { +impl<D: Data> GGSWInfos for GGSW<D> { fn dsize(&self) -> Dsize { self.dsize }

@@ -105,133 +107,17 @@ Dnum(self.data.rows() as u32)

} } -pub struct GGSWCiphertextBuilder<D: Data> { - data: Option<MatZnx<D>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, - dsize: Option<Dsize>, -} - -impl<D: Data> GGSWCiphertext<D> { - #[inline] - pub fn builder() -> GGSWCiphertextBuilder<D> { - GGSWCiphertextBuilder { - data: None, - base2k: None, - k: None, - dsize: None, - } - } -} - -impl GGSWCiphertextBuilder<Vec<u8>> { - #[inline] - pub fn layout<A>(mut self, infos: &A) -> Self - where - A: GGSWInfos, - { - debug_assert!( - infos.size() as u32 > infos.dsize().0, - "invalid ggsw: ceil(k/base2k): {} <= dsize: {}", - infos.size(), - infos.dsize() - ); - - assert!( - infos.dnum().0 * infos.dsize().0 <= infos.size() as u32, - "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {}", - infos.dnum(), - infos.dsize(), - infos.size(), - ); - - self.data = Some(MatZnx::alloc( - infos.n().into(), - infos.dnum().into(), - (infos.rank() + 1).into(), - (infos.rank() + 1).into(), - infos.size(), - )); - self.base2k = Some(infos.base2k()); - self.k = Some(infos.k()); - self.dsize = Some(infos.dsize()); - self - } -} - -impl<D: Data> GGSWCiphertextBuilder<D> { - #[inline] - pub fn data(mut self, data: MatZnx<D>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self - } - - #[inline] - pub fn dsize(mut self, dsize: Dsize) -> Self { - self.dsize = Some(dsize); - self - } - - pub fn build(self) -> Result<GGSWCiphertext<D>, BuildError> { - let data: MatZnx<D> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?; - - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if dsize == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GGSWCiphertext { - data, - base2k, - k, - dsize, - }) - } -} - -impl<D: DataRef> fmt::Debug for GGSWCiphertext<D> { +impl<D: DataRef> fmt::Debug for GGSW<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.data) } } -impl<D: DataRef> fmt::Display for GGSWCiphertext<D> { +impl<D: DataRef> fmt::Display for GGSW<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "(GGSWCiphertext: k: {} base2k: {} dsize: {}) {}", + "(GGSW: k: {} base2k: {} dsize: {}) {}", self.k().0, self.base2k().0, self.dsize().0,

@@ -240,50 +126,39 @@ )

} } -impl<D: DataMut> FillUniform for GGSWCiphertext<D> { +impl<D: DataMut> FillUniform for GGSW<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl<D: DataRef> GGSWCiphertext<D> { - pub fn at(&self, row: usize, col: usize) -> GLWECiphertext<&[u8]> { - GLWECiphertext::builder() - .data(self.data.at(row, col)) - .base2k(self.base2k()) - .k(self.k()) - .build() - .unwrap() +impl<D: DataRef> GGSW<D> { + pub fn at(&self, row: usize, col: usize) -> GLWE<&[u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.at(row, col), + } } } -impl<D: DataMut> GGSWCiphertext<D> { - pub fn at_mut(&mut self, row: usize, col: usize) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext::builder() - .base2k(self.base2k()) - .k(self.k()) - .data(self.data.at_mut(row, col)) - .build() - .unwrap() +impl<D: DataMut> GGSW<D> { + pub fn at_mut(&mut self, row: usize, col: usize) -> GLWE<&mut [u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.at_mut(row, col), + } } } -impl GGSWCiphertext<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: GGSWInfos, - { - Self::alloc_with( - infos.n(), - infos.base2k(), - infos.k(), - infos.rank(), - infos.dnum(), - infos.dsize(), - ) - } +impl<B: Backend> GGSWAlloc for Module<B> where Self: GetRingDegree {} - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self { +pub trait GGSWAlloc +where + Self: GetRingDegree, +{ + fn alloc_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> GGSW<Vec<u8>> { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -298,9 +173,9 @@ dnum.0,

dsize.0, ); - Self { + GGSW { data: MatZnx::alloc( - n.into(), + self.ring_degree().into(), dnum.into(), (rank + 1).into(), (rank + 1).into(),

@@ -312,12 +187,11 @@ dsize,

} } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn alloc_ggsw_from_infos<A>(&self, infos: &A) -> GGSW<Vec<u8>> where A: GGSWInfos, { - Self::alloc_bytes_with( - infos.n(), + self.alloc_ggsw( infos.base2k(), infos.k(), infos.rank(),

@@ -326,7 +200,7 @@ infos.dsize(),

) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { + fn bytes_of_ggsw(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -341,19 +215,64 @@ dnum.0,

dsize.0, ); - MatZnx::alloc_bytes( - n.into(), + MatZnx::bytes_of( + self.ring_degree().into(), dnum.into(), (rank + 1).into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize, ) } + + fn bytes_of_ggsw_from_infos<A>(&self, infos: &A) -> usize + where + A: GGSWInfos, + { + self.bytes_of_ggsw( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) + } +} + +impl GGSW<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGSWInfos, + M: GGSWAlloc, + { + module.alloc_ggsw_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: GGSWAlloc, + { + module.alloc_ggsw(base2k, k, rank, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGSWInfos, + M: GGSWAlloc, + { + module.bytes_of_ggsw_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: GGSWAlloc, + { + module.bytes_of_ggsw(base2k, k, rank, dnum, dsize) + } } use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; -impl<D: DataMut> ReaderFrom for GGSWCiphertext<D> { +impl<D: DataMut> ReaderFrom for GGSW<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -362,7 +281,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for GGSWCiphertext<D> { +impl<D: DataRef> WriterTo for GGSW<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.into())?; writer.write_u32::<LittleEndian>(self.base2k.into())?;

@@ -370,3 +289,33 @@ writer.write_u32::<LittleEndian>(self.dsize.into())?;

self.data.write_to(writer) } } + +pub trait GGSWToMut { + fn to_mut(&mut self) -> GGSW<&mut [u8]>; +} + +impl<D: DataMut> GGSWToMut for GGSW<D> { + fn to_mut(&mut self) -> GGSW<&mut [u8]> { + GGSW { + dsize: self.dsize, + k: self.k, + base2k: self.base2k, + data: self.data.to_mut(), + } + } +} + +pub trait GGSWToRef { + fn to_ref(&self) -> GGSW<&[u8]>; +} + +impl<D: DataRef> GGSWToRef for GGSW<D> { + fn to_ref(&self) -> GGSW<&[u8]> { + GGSW { + dsize: self.dsize, + k: self.k, + base2k: self.base2k, + data: self.data.to_ref(), + } + } +}
M poulpy-core/src/layouts/glwe_ct.rs → poulpy-core/src/layouts/glwe_ct.rs

@@ -1,11 +1,12 @@

use poulpy_hal::{ layouts::{ - Data, DataMut, DataRef, FillUniform, ReaderFrom, ToOwnedDeep, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo, ZnxInfos, + Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, ToOwnedDeep, VecZnx, VecZnxToMut, VecZnxToRef, + WriterTo, ZnxInfos, }, source::Source, }; -use crate::layouts::{Base2K, BuildError, Degree, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{Base2K, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use std::fmt;

@@ -14,8 +15,8 @@ where

Self: LWEInfos, { fn rank(&self) -> Rank; - fn glwe_layout(&self) -> GLWECiphertextLayout { - GLWECiphertextLayout { + fn glwe_layout(&self) -> GLWELayout { + GLWELayout { n: self.n(), base2k: self.base2k(), k: self.k(),

@@ -24,21 +25,21 @@ }

} } -pub trait GLWELayoutSet { +pub trait SetGLWEInfos { fn set_k(&mut self, k: TorusPrecision); - fn set_basek(&mut self, base2k: Base2K); + fn set_base2k(&mut self, base2k: Base2K); } #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct GLWECiphertextLayout { - pub n: Degree, +pub struct GLWELayout { + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank: Rank, } -impl LWEInfos for GLWECiphertextLayout { - fn n(&self) -> Degree { +impl LWEInfos for GLWELayout { + fn n(&self) -> RingDegree { self.n }

@@ -51,21 +52,21 @@ self.k

} } -impl GLWEInfos for GLWECiphertextLayout { +impl GLWEInfos for GLWELayout { fn rank(&self) -> Rank { self.rank } } #[derive(PartialEq, Eq, Clone)] -pub struct GLWECiphertext<D: Data> { +pub struct GLWE<D: Data> { pub(crate) data: VecZnx<D>, pub(crate) base2k: Base2K, pub(crate) k: TorusPrecision, } -impl<D: DataMut> GLWELayoutSet for GLWECiphertext<D> { - fn set_basek(&mut self, base2k: Base2K) { +impl<D: DataMut> SetGLWEInfos for GLWE<D> { + fn set_base2k(&mut self, base2k: Base2K) { self.base2k = base2k }

@@ -74,99 +75,19 @@ self.k = k

} } -impl<D: DataRef> GLWECiphertext<D> { +impl<D: DataRef> GLWE<D> { pub fn data(&self) -> &VecZnx<D> { &self.data } } -impl<D: DataMut> GLWECiphertext<D> { +impl<D: DataMut> GLWE<D> { pub fn data_mut(&mut self) -> &mut VecZnx<D> { &mut self.data } } -pub struct GLWECiphertextBuilder<D: Data> { - data: Option<VecZnx<D>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, -} - -impl<D: Data> GLWECiphertext<D> { - #[inline] - pub fn builder() -> GLWECiphertextBuilder<D> { - GLWECiphertextBuilder { - data: None, - base2k: None, - k: None, - } - } -} - -impl GLWECiphertextBuilder<Vec<u8>> { - #[inline] - pub fn layout<A>(mut self, layout: &A) -> Self - where - A: GLWEInfos, - { - self.data = Some(VecZnx::alloc( - layout.n().into(), - (layout.rank() + 1).into(), - layout.size(), - )); - self.base2k = Some(layout.base2k()); - self.k = Some(layout.k()); - self - } -} - -impl<D: Data> GLWECiphertextBuilder<D> { - #[inline] - pub fn data(mut self, data: VecZnx<D>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self - } - - pub fn build(self) -> Result<GLWECiphertext<D>, BuildError> { - let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GLWECiphertext { data, base2k, k }) - } -} - -impl<D: Data> LWEInfos for GLWECiphertext<D> { +impl<D: Data> LWEInfos for GLWE<D> { fn base2k(&self) -> Base2K { self.base2k }

@@ -175,8 +96,8 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -184,16 +105,16 @@ self.data.size()

} } -impl<D: Data> GLWEInfos for GLWECiphertext<D> { +impl<D: Data> GLWEInfos for GLWE<D> { fn rank(&self) -> Rank { Rank(self.data.cols() as u32 - 1) } } -impl<D: DataRef> ToOwnedDeep for GLWECiphertext<D> { - type Owned = GLWECiphertext<Vec<u8>>; +impl<D: DataRef> ToOwnedDeep for GLWE<D> { + type Owned = GLWE<Vec<u8>>; fn to_owned_deep(&self) -> Self::Owned { - GLWECiphertext { + GLWE { data: self.data.to_owned_deep(), k: self.k, base2k: self.base2k,

@@ -201,17 +122,17 @@ }

} } -impl<D: DataRef> fmt::Debug for GLWECiphertext<D> { +impl<D: DataRef> fmt::Debug for GLWE<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataRef> fmt::Display for GLWECiphertext<D> { +impl<D: DataRef> fmt::Display for GLWE<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "GLWECiphertext: base2k={} k={}: {}", + "GLWE: base2k={} k={}: {}", self.base2k().0, self.k().0, self.data

@@ -219,71 +140,86 @@ )

} } -impl<D: DataMut> FillUniform for GLWECiphertext<D> { +impl<D: DataMut> FillUniform for GLWE<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.data.fill_uniform(log_bound, source); } } -impl GLWECiphertext<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait GLWEAlloc +where + Self: GetRingDegree, +{ + fn alloc_glwe(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWE<Vec<u8>> { + GLWE { + data: VecZnx::alloc( + self.ring_degree().into(), + (rank + 1).into(), + k.0.div_ceil(base2k.0) as usize, + ), + base2k, + k, + } + } + + fn alloc_glwe_from_infos<A>(&self, infos: &A) -> GLWE<Vec<u8>> where A: GLWEInfos, { - Self::alloc_with(infos.n(), infos.base2k(), infos.k(), infos.rank()) + self.alloc_glwe(infos.base2k(), infos.k(), infos.rank()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self { - Self { - data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize), - base2k, - k, - } + fn bytes_of_glwe(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { + VecZnx::bytes_of( + self.ring_degree().into(), + (rank + 1).into(), + k.0.div_ceil(base2k.0) as usize, + ) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_glwe_from_infos<A>(&self, infos: &A) -> usize where A: GLWEInfos, { - Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), infos.rank()) + self.bytes_of_glwe(infos.base2k(), infos.k(), infos.rank()) } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { - VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize) +impl<B: Backend> GLWEAlloc for Module<B> where Self: GetRingDegree {} + +impl GLWE<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GLWEInfos, + M: GLWEAlloc, + { + module.alloc_glwe_from_infos(infos) } -} -pub trait GLWECiphertextToRef { - fn to_ref(&self) -> GLWECiphertext<&[u8]>; -} + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self + where + M: GLWEAlloc, + { + module.alloc_glwe(base2k, k, rank) + } -impl<D: DataRef> GLWECiphertextToRef for GLWECiphertext<D> { - fn to_ref(&self) -> GLWECiphertext<&[u8]> { - GLWECiphertext::builder() - .k(self.k()) - .base2k(self.base2k()) - .data(self.data.to_ref()) - .build() - .unwrap() + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GLWEInfos, + M: GLWEAlloc, + { + module.bytes_of_glwe_from_infos(infos) } -} -pub trait GLWECiphertextToMut { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]>; -} - -impl<D: DataMut> GLWECiphertextToMut for GLWECiphertext<D> { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext::builder() - .k(self.k()) - .base2k(self.base2k()) - .data(self.data.to_mut()) - .build() - .unwrap() + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize + where + M: GLWEAlloc, + { + module.bytes_of_glwe(base2k, k, rank) } } -impl<D: DataMut> ReaderFrom for GLWECiphertext<D> { +impl<D: DataMut> ReaderFrom for GLWE<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -291,10 +227,38 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for GLWECiphertext<D> { +impl<D: DataRef> WriterTo for GLWE<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.0)?; writer.write_u32::<LittleEndian>(self.base2k.0)?; self.data.write_to(writer) } } + +pub trait GLWEToRef { + fn to_ref(&self) -> GLWE<&[u8]>; +} + +impl<D: DataRef> GLWEToRef for GLWE<D> { + fn to_ref(&self) -> GLWE<&[u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.to_ref(), + } + } +} + +pub trait GLWEToMut { + fn to_mut(&mut self) -> GLWE<&mut [u8]>; +} + +impl<D: DataMut> GLWEToMut for GLWE<D> { + fn to_mut(&mut self) -> GLWE<&mut [u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.to_mut(), + } + } +}
M poulpy-core/src/layouts/glwe_pk.rs → poulpy-core/src/layouts/glwe_pk.rs

@@ -1,8 +1,10 @@

-use poulpy_hal::layouts::{Data, DataMut, DataRef, ReaderFrom, VecZnx, WriterTo, ZnxInfos}; +use poulpy_hal::layouts::{ + Backend, Data, DataMut, DataRef, Module, ReaderFrom, VecZnx, VecZnxToMut, VecZnxToRef, WriterTo, ZnxInfos, +}; use crate::{ dist::Distribution, - layouts::{Base2K, BuildError, Degree, GLWEInfos, LWEInfos, Rank, TorusPrecision}, + layouts::{Base2K, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision}, }; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

@@ -16,12 +18,22 @@ }

#[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct GLWEPublicKeyLayout { - pub n: Degree, + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank: Rank, } +pub trait GetDist { + fn get_dist(&self) -> Distribution; +} + +impl<D: DataRef> GetDist for GLWEPublicKey<D> { + fn get_dist(&self) -> Distribution { + self.dist + } +} + impl<D: Data> LWEInfos for GLWEPublicKey<D> { fn base2k(&self) -> Base2K { self.base2k

@@ -31,8 +43,8 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -55,7 +67,7 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n }

@@ -70,117 +82,77 @@ self.rank

} } -pub struct GLWEPublicKeyBuilder<D: Data> { - data: Option<VecZnx<D>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, -} - -impl<D: Data> GLWEPublicKey<D> { - #[inline] - pub fn builder() -> GLWEPublicKeyBuilder<D> { - GLWEPublicKeyBuilder { - data: None, - base2k: None, - k: None, +pub trait GLWEPublicKeyAlloc +where + Self: GetRingDegree, +{ + fn alloc_glwe_public_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKey<Vec<u8>> { + GLWEPublicKey { + data: VecZnx::alloc( + self.ring_degree().into(), + (rank + 1).into(), + k.0.div_ceil(base2k.0) as usize, + ), + base2k, + k, + dist: Distribution::NONE, } } -} -impl GLWEPublicKeyBuilder<Vec<u8>> { - #[inline] - pub fn layout<A>(mut self, layout: &A) -> Self + fn alloc_glwe_public_key_from_infos<A>(&self, infos: &A) -> GLWEPublicKey<Vec<u8>> where A: GLWEInfos, { - self.data = Some(VecZnx::alloc( - layout.n().into(), - (layout.rank() + 1).into(), - layout.size(), - )); - self.base2k = Some(layout.base2k()); - self.k = Some(layout.k()); - self + self.alloc_glwe_public_key(infos.base2k(), infos.k(), infos.rank()) } -} -impl<D: Data> GLWEPublicKeyBuilder<D> { - #[inline] - pub fn data(mut self, data: VecZnx<D>) -> Self { - self.data = Some(data); - self + fn bytes_of_glwe_public_key(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { + VecZnx::bytes_of( + self.ring_degree().into(), + (rank + 1).into(), + k.0.div_ceil(base2k.0) as usize, + ) } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self - } - - pub fn build(self) -> Result<GLWEPublicKey<D>, BuildError> { - let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GLWEPublicKey { - data, - base2k, - k, - dist: Distribution::NONE, - }) + fn bytes_of_glwe_public_key_from_infos<A>(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + self.bytes_of_glwe_public_key(infos.base2k(), infos.k(), infos.rank()) } } +impl<B: Backend> GLWEPublicKeyAlloc for Module<B> where Self: GetRingDegree {} + impl GLWEPublicKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GLWEInfos, + M: GLWEPublicKeyAlloc, { - Self::alloc_with(infos.n(), infos.base2k(), infos.k(), infos.rank()) + module.alloc_glwe_public_key_from_infos(infos) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self { - Self { - data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize), - base2k, - k, - dist: Distribution::NONE, - } + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self + where + M: GLWEPublicKeyAlloc, + { + module.alloc_glwe_public_key(base2k, k, rank) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GLWEInfos, + M: GLWEPublicKeyAlloc, { - Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), infos.rank()) + module.bytes_of_glwe_public_key_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { - VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize + where + M: GLWEPublicKeyAlloc, + { + module.bytes_of_glwe_public_key(base2k, k, rank) } }

@@ -207,3 +179,33 @@ }

self.data.write_to(writer) } } + +pub trait GLWEPublicKeyToRef { + fn to_ref(&self) -> GLWEPublicKey<&[u8]>; +} + +impl<D: DataRef> GLWEPublicKeyToRef for GLWEPublicKey<D> { + fn to_ref(&self) -> GLWEPublicKey<&[u8]> { + GLWEPublicKey { + data: self.data.to_ref(), + base2k: self.base2k, + k: self.k, + dist: self.dist, + } + } +} + +pub trait GLWEPublicKeyToMut { + fn to_mut(&mut self) -> GLWEPublicKey<&mut [u8]>; +} + +impl<D: DataMut> GLWEPublicKeyToMut for GLWEPublicKey<D> { + fn to_mut(&mut self) -> GLWEPublicKey<&mut [u8]> { + GLWEPublicKey { + base2k: self.base2k, + k: self.k, + dist: self.dist, + data: self.data.to_mut(), + } + } +}
M poulpy-core/src/layouts/glwe_pt.rs → poulpy-core/src/layouts/glwe_pt.rs

@@ -1,15 +1,14 @@

use std::fmt; -use poulpy_hal::layouts::{Data, DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos}; use crate::layouts::{ - Base2K, BuildError, Degree, GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEInfos, GLWELayoutSet, LWEInfos, - Rank, TorusPrecision, + Base2K, GLWE, GLWEInfos, GLWEToMut, GLWEToRef, GetRingDegree, LWEInfos, Rank, RingDegree, SetGLWEInfos, TorusPrecision, }; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct GLWEPlaintextLayout { - pub n: Degree, + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, }

@@ -23,7 +22,7 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n } }

@@ -40,8 +39,8 @@ pub base2k: Base2K,

pub k: TorusPrecision, } -impl<D: DataMut> GLWELayoutSet for GLWEPlaintext<D> { - fn set_basek(&mut self, base2k: Base2K) { +impl<D: DataMut> SetGLWEInfos for GLWEPlaintext<D> { + fn set_base2k(&mut self, base2k: Base2K) { self.base2k = base2k }

@@ -63,8 +62,8 @@ fn size(&self) -> usize {

self.data.size() } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } }

@@ -74,129 +73,135 @@ Rank(self.data.cols() as u32 - 1)

} } -pub struct GLWEPlaintextBuilder<D: Data> { - data: Option<VecZnx<D>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, +impl<D: DataRef> fmt::Display for GLWEPlaintext<D> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "GLWEPlaintext: base2k={} k={}: {}", + self.base2k().0, + self.k().0, + self.data + ) + } } -impl<D: Data> GLWEPlaintext<D> { - #[inline] - pub fn builder() -> GLWEPlaintextBuilder<D> { - GLWEPlaintextBuilder { - data: None, - base2k: None, - k: None, +pub trait GLWEPlaintextAlloc +where + Self: GetRingDegree, +{ + fn alloc_glwe_plaintext(&self, base2k: Base2K, k: TorusPrecision) -> GLWEPlaintext<Vec<u8>> { + GLWEPlaintext { + data: VecZnx::alloc( + self.ring_degree().into(), + 1, + k.0.div_ceil(base2k.0) as usize, + ), + base2k, + k, } } -} -impl<D: Data> GLWEPlaintextBuilder<D> { - #[inline] - pub fn data(mut self, data: VecZnx<D>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self + fn alloc_glwe_plaintext_from_infos<A>(&self, infos: &A) -> GLWEPlaintext<Vec<u8>> + where + A: GLWEInfos, + { + self.alloc_glwe_plaintext(infos.base2k(), infos.k()) } - pub fn build(self) -> Result<GLWEPlaintext<D>, BuildError> { - let data: VecZnx<D> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - - if base2k.0 == 0 { - return Err(BuildError::ZeroBase2K); - } - - if k.0 == 0 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() != 1 { - return Err(BuildError::ZeroCols); - } + fn bytes_of_glwe_plaintext(&self, base2k: Base2K, k: TorusPrecision) -> usize { + VecZnx::bytes_of( + self.ring_degree().into(), + 1, + k.0.div_ceil(base2k.0) as usize, + ) + } - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GLWEPlaintext { data, base2k, k }) + fn bytes_of_glwe_plaintext_from_infos<A>(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + self.bytes_of_glwe_plaintext(infos.base2k(), infos.k()) } } -impl<D: DataRef> fmt::Display for GLWEPlaintext<D> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "GLWEPlaintext: base2k={} k={}: {}", - self.base2k().0, - self.k().0, - self.data - ) - } -} +impl<B: Backend> GLWEPlaintextAlloc for Module<B> where Self: GetRingDegree {} impl GLWEPlaintext<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GLWEInfos, + M: GLWEPlaintextAlloc, { - Self::alloc_with(infos.n(), infos.base2k(), infos.k(), Rank(0)) + module.alloc_glwe_plaintext_from_infos(infos) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self { - debug_assert!(rank.0 == 0); - Self { - data: VecZnx::alloc(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize), - base2k, - k, - } + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> Self + where + M: GLWEPlaintextAlloc, + { + module.alloc_glwe_plaintext(base2k, k) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GLWEInfos, + M: GLWEPlaintextAlloc, { - Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k(), Rank(0)) + module.bytes_of_glwe_plaintext_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { - debug_assert!(rank.0 == 0); - VecZnx::alloc_bytes(n.into(), (rank + 1).into(), k.0.div_ceil(base2k.0) as usize) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> usize + where + M: GLWEPlaintextAlloc, + { + module.bytes_of_glwe_plaintext(base2k, k) } } -impl<D: DataRef> GLWECiphertextToRef for GLWEPlaintext<D> { - fn to_ref(&self) -> GLWECiphertext<&[u8]> { - GLWECiphertext::builder() - .data(self.data.to_ref()) - .k(self.k()) - .base2k(self.base2k()) - .build() - .unwrap() +impl<D: DataRef> GLWEToRef for GLWEPlaintext<D> { + fn to_ref(&self) -> GLWE<&[u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.to_ref(), + } } } -impl<D: DataMut> GLWECiphertextToMut for GLWEPlaintext<D> { - fn to_mut(&mut self) -> GLWECiphertext<&mut [u8]> { - GLWECiphertext::builder() - .k(self.k()) - .base2k(self.base2k()) - .data(self.data.to_mut()) - .build() - .unwrap() +impl<D: DataMut> GLWEToMut for GLWEPlaintext<D> { + fn to_mut(&mut self) -> GLWE<&mut [u8]> { + GLWE { + k: self.k, + base2k: self.base2k, + data: self.data.to_mut(), + } + } +} + +pub trait GLWEPlaintextToRef { + fn to_ref(&self) -> GLWEPlaintext<&[u8]>; +} + +impl<D: DataRef> GLWEPlaintextToRef for GLWEPlaintext<D> { + fn to_ref(&self) -> GLWEPlaintext<&[u8]> { + GLWEPlaintext { + data: self.data.to_ref(), + base2k: self.base2k, + k: self.k, + } + } +} + +pub trait GLWEPlaintextToMut { + fn to_ref(&mut self) -> GLWEPlaintext<&mut [u8]>; +} + +impl<D: DataMut> GLWEPlaintextToMut for GLWEPlaintext<D> { + fn to_ref(&mut self) -> GLWEPlaintext<&mut [u8]> { + GLWEPlaintext { + base2k: self.base2k, + k: self.k, + data: self.data.to_mut(), + } } }
M poulpy-core/src/layouts/glwe_sk.rs → poulpy-core/src/layouts/glwe_sk.rs

@@ -1,16 +1,19 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, ReaderFrom, ScalarZnx, WriterTo, ZnxInfos, ZnxZero}, + layouts::{ + Backend, Data, DataMut, DataRef, Module, ReaderFrom, ScalarZnx, ScalarZnxToMut, ScalarZnxToRef, WriterTo, ZnxInfos, + ZnxZero, + }, source::Source, }; use crate::{ dist::Distribution, - layouts::{Base2K, Degree, GLWEInfos, LWEInfos, Rank, TorusPrecision}, + layouts::{Base2K, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision}, }; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct GLWESecretLayout { - pub n: Degree, + pub n: RingDegree, pub rank: Rank, }

@@ -23,7 +26,7 @@ fn k(&self) -> TorusPrecision {

TorusPrecision(0) } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n }

@@ -52,8 +55,8 @@ fn k(&self) -> TorusPrecision {

TorusPrecision(0) } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -67,30 +70,67 @@ Rank(self.data.cols() as u32)

} } +pub trait GLWESecretAlloc +where + Self: GetRingDegree, +{ + fn alloc_glwe_secret(&self, rank: Rank) -> GLWESecret<Vec<u8>> { + GLWESecret { + data: ScalarZnx::alloc(self.ring_degree().into(), rank.into()), + dist: Distribution::NONE, + } + } + + fn alloc_glwe_secret_from_infos<A>(&self, infos: &A) -> GLWESecret<Vec<u8>> + where + A: GLWEInfos, + { + self.alloc_glwe_secret(infos.rank()) + } + + fn bytes_of_glwe_secret(&self, rank: Rank) -> usize { + ScalarZnx::bytes_of(self.ring_degree().into(), rank.into()) + } + + fn bytes_of_glwe_secret_from_infos<A>(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + self.bytes_of_glwe_secret(infos.rank()) + } +} + +impl<B: Backend> GLWESecretAlloc for Module<B> where Self: GetRingDegree {} + impl GLWESecret<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GLWEInfos, + M: GLWESecretAlloc, { - Self::alloc_with(infos.n(), infos.rank()) + module.alloc_glwe_secret_from_infos(infos) } - pub fn alloc_with(n: Degree, rank: Rank) -> Self { - Self { - data: ScalarZnx::alloc(n.into(), rank.into()), - dist: Distribution::NONE, - } + pub fn alloc<M>(module: &M, rank: Rank) -> Self + where + M: GLWESecretAlloc, + { + module.alloc_glwe_secret(rank) } - pub fn alloc_bytes<A>(infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GLWEInfos, + M: GLWESecretAlloc, { - Self::alloc_bytes_with(infos.n(), infos.rank()) + module.bytes_of_glwe_secret_from_infos(infos) } - pub fn alloc_bytes_with(n: Degree, rank: Rank) -> usize { - ScalarZnx::alloc_bytes(n.into(), rank.into()) + pub fn bytes_of<M>(module: &M, rank: Rank) -> usize + where + M: GLWESecretAlloc, + { + module.bytes_of_glwe_secret(rank) } }

@@ -133,6 +173,32 @@

pub fn fill_zero(&mut self) { self.data.zero(); self.dist = Distribution::ZERO; + } +} + +pub trait GLWESecretToMut { + fn to_mut(&mut self) -> GLWESecret<&mut [u8]>; +} + +impl<D: DataMut> GLWESecretToMut for GLWESecret<D> { + fn to_mut(&mut self) -> GLWESecret<&mut [u8]> { + GLWESecret { + dist: self.dist, + data: self.data.to_mut(), + } + } +} + +pub trait GLWESecretToRef { + fn to_ref(&self) -> GLWESecret<&[u8]>; +} + +impl<D: DataRef> GLWESecretToRef for GLWESecret<D> { + fn to_ref(&self) -> GLWESecret<&[u8]> { + GLWESecret { + data: self.data.to_ref(), + dist: self.dist, + } } }
M poulpy-core/src/layouts/glwe_to_lwe_ksk.rs → poulpy-core/src/layouts/glwe_to_lwe_ksk.rs

@@ -1,15 +1,18 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; -use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{ + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut, + GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision, +}; use std::fmt; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct GLWEToLWEKeyLayout { - pub n: Degree, + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank_in: Rank,

@@ -17,7 +20,7 @@ pub dnum: Dnum,

} impl LWEInfos for GLWEToLWEKeyLayout { - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n }

@@ -54,11 +57,11 @@ self.dnum

} } -/// A special [GLWESwitchingKey] required to for the conversion from [GLWECiphertext] to [LWECiphertext]. +/// A special [GLWESwitchingKey] required to for the conversion from [GLWE] to [LWE]. #[derive(PartialEq, Eq, Clone)] -pub struct GLWEToLWEKey<D: Data>(pub(crate) GGLWESwitchingKey<D>); +pub struct GLWEToLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); -impl<D: Data> LWEInfos for GLWEToLWEKey<D> { +impl<D: Data> LWEInfos for GLWEToLWESwitchingKey<D> { fn base2k(&self) -> Base2K { self.0.base2k() }

@@ -67,7 +70,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -76,12 +79,12 @@ self.0.size()

} } -impl<D: Data> GLWEInfos for GLWEToLWEKey<D> { +impl<D: Data> GLWEInfos for GLWEToLWESwitchingKey<D> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data> GGLWEInfos for GLWEToLWEKey<D> { +impl<D: Data> GGLWEInfos for GLWEToLWESwitchingKey<D> { fn rank_in(&self) -> Rank { self.0.rank_in() }

@@ -99,84 +102,145 @@ self.0.dnum()

} } -impl<D: DataRef> fmt::Debug for GLWEToLWEKey<D> { +impl<D: DataRef> fmt::Debug for GLWEToLWESwitchingKey<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataMut> FillUniform for GLWEToLWEKey<D> { +impl<D: DataMut> FillUniform for GLWEToLWESwitchingKey<D> { fn fill_uniform(&mut self, log_bound: usize, source: &mut Source) { self.0.fill_uniform(log_bound, source); } } -impl<D: DataRef> fmt::Display for GLWEToLWEKey<D> { +impl<D: DataRef> fmt::Display for GLWEToLWESwitchingKey<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "(GLWEToLWESwitchingKey) {}", self.0) } } -impl<D: DataMut> ReaderFrom for GLWEToLWEKey<D> { +impl<D: DataMut> ReaderFrom for GLWEToLWESwitchingKey<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.0.read_from(reader) } } -impl<D: DataRef> WriterTo for GLWEToLWEKey<D> { +impl<D: DataRef> WriterTo for GLWEToLWESwitchingKey<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { self.0.write_to(writer) } } -impl GLWEToLWEKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait GLWEToLWESwitchingKeyAlloc +where + Self: GLWESwitchingKeyAlloc, +{ + fn alloc_glwe_to_lwe_switching_key( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + dnum: Dnum, + ) -> GLWEToLWESwitchingKey<Vec<u8>> { + GLWEToLWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, rank_in, Rank(1), dnum, Dsize(1))) + } + + fn alloc_glwe_to_lwe_switching_key_from_infos<A>(&self, infos: &A) -> GLWEToLWESwitchingKey<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is not supported for GLWEToLWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for GLWEToLWESwitchingKey" ); - Self(GGLWESwitchingKey::alloc(infos)) + self.alloc_glwe_to_lwe_switching_key(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self { - Self(GGLWESwitchingKey::alloc_with( - n, - base2k, - k, - rank_in, - Rank(1), - dnum, - Dsize(1), - )) + fn bytes_of_glwe_to_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key(base2k, k, rank_in, Rank(1), dnum, Dsize(1)) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_glwe_to_lwe_switching_key_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is not supported for GLWEToLWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for GLWEToLWESwitchingKey" ); - GGLWESwitchingKey::alloc_bytes(infos) + self.bytes_of_glwe_to_lwe_switching_key(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum()) } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize { - GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, rank_in, Rank(1), dnum, Dsize(1)) +impl<B: Backend> GLWEToLWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {} + +impl GLWEToLWESwitchingKey<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyAlloc, + { + module.alloc_glwe_to_lwe_switching_key_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self + where + M: GLWEToLWESwitchingKeyAlloc, + { + module.alloc_glwe_to_lwe_switching_key(base2k, k, rank_in, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyAlloc, + { + module.bytes_of_glwe_to_lwe_switching_key_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize + where + M: GLWEToLWESwitchingKeyAlloc, + { + module.bytes_of_glwe_to_lwe_switching_key(base2k, k, rank_in, dnum) + } +} + +pub trait GLWEToLWESwitchingKeyToRef { + fn to_ref(&self) -> GLWEToLWESwitchingKey<&[u8]>; +} + +impl<D: DataRef> GLWEToLWESwitchingKeyToRef for GLWEToLWESwitchingKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToRef, +{ + fn to_ref(&self) -> GLWEToLWESwitchingKey<&[u8]> { + GLWEToLWESwitchingKey(self.0.to_ref()) + } +} + +pub trait GLWEToLWESwitchingKeyToMut { + fn to_mut(&mut self) -> GLWEToLWESwitchingKey<&mut [u8]>; +} + +impl<D: DataMut> GLWEToLWESwitchingKeyToMut for GLWEToLWESwitchingKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToMut, +{ + fn to_mut(&mut self) -> GLWEToLWESwitchingKey<&mut [u8]> { + GLWEToLWESwitchingKey(self.0.to_mut()) } }
M poulpy-core/src/layouts/lwe_ct.rs → poulpy-core/src/layouts/lwe_ct.rs

@@ -1,15 +1,15 @@

use std::fmt; use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo, Zn, ZnToMut, ZnToRef, ZnxInfos}, source::Source, }; -use crate::layouts::{Base2K, BuildError, Degree, TorusPrecision}; +use crate::layouts::{Base2K, RingDegree, TorusPrecision}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; pub trait LWEInfos { - fn n(&self) -> Degree; + fn n(&self) -> RingDegree; fn k(&self) -> TorusPrecision; fn max_k(&self) -> TorusPrecision { TorusPrecision(self.k().0 * self.size() as u32)

@@ -18,8 +18,8 @@ fn base2k(&self) -> Base2K;

fn size(&self) -> usize { self.k().0.div_ceil(self.base2k().0) as usize } - fn lwe_layout(&self) -> LWECiphertextLayout { - LWECiphertextLayout { + fn lwe_layout(&self) -> LWELayout { + LWELayout { n: self.n(), k: self.k(), base2k: self.base2k(),

@@ -27,14 +27,19 @@ }

} } +pub trait SetLWEInfos { + fn set_k(&mut self, k: TorusPrecision); + fn set_base2k(&mut self, base2k: Base2K); +} + #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub struct LWECiphertextLayout { - pub n: Degree, +pub struct LWELayout { + pub n: RingDegree, pub k: TorusPrecision, pub base2k: Base2K, } -impl LWEInfos for LWECiphertextLayout { +impl LWEInfos for LWELayout { fn base2k(&self) -> Base2K { self.base2k }

@@ -43,19 +48,18 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n } } - #[derive(PartialEq, Eq, Clone)] -pub struct LWECiphertext<D: Data> { +pub struct LWE<D: Data> { pub(crate) data: Zn<D>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K, } -impl<D: Data> LWEInfos for LWECiphertext<D> { +impl<D: Data> LWEInfos for LWE<D> { fn base2k(&self) -> Base2K { self.base2k }

@@ -63,8 +67,8 @@

fn k(&self) -> TorusPrecision { self.k } - fn n(&self) -> Degree { - Degree(self.data.n() as u32 - 1) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32 - 1) } fn size(&self) -> usize {

@@ -72,29 +76,39 @@ self.data.size()

} } -impl<D: DataRef> LWECiphertext<D> { +impl<D: Data> SetLWEInfos for LWE<D> { + fn set_base2k(&mut self, base2k: Base2K) { + self.base2k = base2k + } + + fn set_k(&mut self, k: TorusPrecision) { + self.k = k + } +} + +impl<D: DataRef> LWE<D> { pub fn data(&self) -> &Zn<D> { &self.data } } -impl<D: DataMut> LWECiphertext<D> { +impl<D: DataMut> LWE<D> { pub fn data_mut(&mut self) -> &Zn<D> { &mut self.data } } -impl<D: DataRef> fmt::Debug for LWECiphertext<D> { +impl<D: DataRef> fmt::Debug for LWE<D> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{self}") } } -impl<D: DataRef> fmt::Display for LWECiphertext<D> { +impl<D: DataRef> fmt::Display for LWE<D> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "LWECiphertext: base2k={} k={}: {}", + "LWE: base2k={} k={}: {}", self.base2k().0, self.k().0, self.data

@@ -102,7 +116,7 @@ )

} } -impl<D: DataMut> FillUniform for LWECiphertext<D> +impl<D: DataMut> FillUniform for LWE<D> where Zn<D>: FillUniform, {

@@ -111,142 +125,98 @@ self.data.fill_uniform(log_bound, source);

} } -impl LWECiphertext<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self - where - A: LWEInfos, - { - Self::alloc_with(infos.n(), infos.base2k(), infos.k()) - } - - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision) -> Self { - Self { +pub trait LWEAlloc { + fn alloc_lwe(&self, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> LWE<Vec<u8>> { + LWE { data: Zn::alloc((n + 1).into(), 1, k.0.div_ceil(base2k.0) as usize), k, base2k, } } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn alloc_lwe_from_infos<A>(&self, infos: &A) -> LWE<Vec<u8>> where A: LWEInfos, { - Self::alloc_bytes_with(infos.n(), infos.base2k(), infos.k()) + self.alloc_lwe(infos.n(), infos.base2k(), infos.k()) } - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision) -> usize { - Zn::alloc_bytes((n + 1).into(), 1, k.0.div_ceil(base2k.0) as usize) + fn bytes_of_lwe(&self, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> usize { + Zn::bytes_of((n + 1).into(), 1, k.0.div_ceil(base2k.0) as usize) } -} -impl LWECiphertextBuilder<Vec<u8>> { - #[inline] - pub fn layout<A>(mut self, layout: A) -> Self + fn bytes_of_lwe_from_infos<A>(&self, infos: &A) -> usize where A: LWEInfos, { - self.data = Some(Zn::alloc((layout.n() + 1).into(), 1, layout.size())); - self.base2k = Some(layout.base2k()); - self.k = Some(layout.k()); - self + self.bytes_of_lwe(infos.n(), infos.base2k(), infos.k()) } } -pub struct LWECiphertextBuilder<D: Data> { - data: Option<Zn<D>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, -} +impl<B: Backend> LWEAlloc for Module<B> {} -impl<D: Data> LWECiphertext<D> { - #[inline] - pub fn builder() -> LWECiphertextBuilder<D> { - LWECiphertextBuilder { - data: None, - base2k: None, - k: None, - } +impl LWE<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: LWEInfos, + M: LWEAlloc, + { + module.alloc_lwe_from_infos(infos) } -} -impl<D: Data> LWECiphertextBuilder<D> { - #[inline] - pub fn data(mut self, data: Zn<D>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self + pub fn alloc<M>(module: &M, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> Self + where + M: LWEAlloc, + { + module.alloc_lwe(n, base2k, k) } - pub fn build(self) -> Result<LWECiphertext<D>, BuildError> { - let data: Zn<D> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - - if base2k.0 == 0 { - return Err(BuildError::ZeroBase2K); - } - - if k.0 == 0 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: LWEInfos, + M: LWEAlloc, + { + module.bytes_of_lwe_from_infos(infos) + } - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(LWECiphertext { data, base2k, k }) + pub fn bytes_of<M>(module: &M, n: RingDegree, base2k: Base2K, k: TorusPrecision) -> usize + where + M: LWEAlloc, + { + module.bytes_of_lwe(n, base2k, k) } } -pub trait LWECiphertextToRef { - fn to_ref(&self) -> LWECiphertext<&[u8]>; +pub trait LWEToRef { + fn to_ref(&self) -> LWE<&[u8]>; } -impl<D: DataRef> LWECiphertextToRef for LWECiphertext<D> { - fn to_ref(&self) -> LWECiphertext<&[u8]> { - LWECiphertext::builder() - .base2k(self.base2k()) - .k(self.k()) - .data(self.data.to_ref()) - .build() - .unwrap() +impl<D: DataRef> LWEToRef for LWE<D> { + fn to_ref(&self) -> LWE<&[u8]> { + LWE { + k: self.k, + base2k: self.base2k, + data: self.data.to_ref(), + } } } -pub trait LWECiphertextToMut { +pub trait LWEToMut { #[allow(dead_code)] - fn to_mut(&mut self) -> LWECiphertext<&mut [u8]>; + fn to_mut(&mut self) -> LWE<&mut [u8]>; } -impl<D: DataMut> LWECiphertextToMut for LWECiphertext<D> { - fn to_mut(&mut self) -> LWECiphertext<&mut [u8]> { - LWECiphertext::builder() - .base2k(self.base2k()) - .k(self.k()) - .data(self.data.to_mut()) - .build() - .unwrap() +impl<D: DataMut> LWEToMut for LWE<D> { + fn to_mut(&mut self) -> LWE<&mut [u8]> { + LWE { + k: self.k, + base2k: self.base2k, + data: self.data.to_mut(), + } } } -impl<D: DataMut> ReaderFrom for LWECiphertext<D> { +impl<D: DataMut> ReaderFrom for LWE<D> { fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> { self.k = TorusPrecision(reader.read_u32::<LittleEndian>()?); self.base2k = Base2K(reader.read_u32::<LittleEndian>()?);

@@ -254,7 +224,7 @@ self.data.read_from(reader)

} } -impl<D: DataRef> WriterTo for LWECiphertext<D> { +impl<D: DataRef> WriterTo for LWE<D> { fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> { writer.write_u32::<LittleEndian>(self.k.into())?; writer.write_u32::<LittleEndian>(self.base2k.into())?;
M poulpy-core/src/layouts/lwe_ksk.rs → poulpy-core/src/layouts/lwe_ksk.rs

@@ -1,22 +1,25 @@

use std::fmt; use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; -use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{ + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut, + GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision, +}; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct LWESwitchingKeyLayout { - pub n: Degree, + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub dnum: Dnum, } impl LWEInfos for LWESwitchingKeyLayout { - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n }

@@ -54,7 +57,7 @@ }

} #[derive(PartialEq, Eq, Clone)] -pub struct LWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>); +pub struct LWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); impl<D: Data> LWEInfos for LWESwitchingKey<D> { fn base2k(&self) -> Base2K {

@@ -65,7 +68,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -98,65 +101,94 @@ self.0.dnum()

} } -impl LWESwitchingKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait LWESwitchingKeyAlloc +where + Self: GLWESwitchingKeyAlloc, +{ + fn alloc_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> LWESwitchingKey<Vec<u8>> { + LWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, Rank(1), Rank(1), dnum, Dsize(1))) + } + + fn alloc_lwe_switching_key_from_infos<A>(&self, infos: &A) -> LWESwitchingKey<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for LWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, "rank_in > 1 is not supported for LWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is not supported for LWESwitchingKey" ); - Self(GGLWESwitchingKey::alloc(infos)) + self.alloc_lwe_switching_key(infos.base2k(), infos.k(), infos.dnum()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self { - Self(GGLWESwitchingKey::alloc_with( - n, - base2k, - k, - Rank(1), - Rank(1), - dnum, - Dsize(1), - )) + fn bytes_of_lwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key(base2k, k, Rank(1), Rank(1), dnum, Dsize(1)) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_lwe_switching_key_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for LWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, "rank_in > 1 is not supported for LWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.rank_out().0, 1, "rank_out > 1 is not supported for LWESwitchingKey" ); - GGLWESwitchingKey::alloc_bytes(infos) + self.bytes_of_lwe_switching_key(infos.base2k(), infos.k(), infos.dnum()) } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { - GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), Rank(1), dnum, Dsize(1)) +impl<B: Backend> LWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {} + +impl LWESwitchingKey<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: LWESwitchingKeyAlloc, + { + module.alloc_lwe_switching_key_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self + where + M: LWESwitchingKeyAlloc, + { + module.alloc_lwe_switching_key(base2k, k, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: LWESwitchingKeyAlloc, + { + module.bytes_of_glwe_switching_key_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize + where + M: LWESwitchingKeyAlloc, + { + module.bytes_of_lwe_switching_key(base2k, k, dnum) } }

@@ -189,3 +221,29 @@ fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {

self.0.write_to(writer) } } + +pub trait LWESwitchingKeyToRef { + fn to_ref(&self) -> LWESwitchingKey<&[u8]>; +} + +impl<D: DataRef> LWESwitchingKeyToRef for LWESwitchingKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToRef, +{ + fn to_ref(&self) -> LWESwitchingKey<&[u8]> { + LWESwitchingKey(self.0.to_ref()) + } +} + +pub trait LWESwitchingKeyToMut { + fn to_mut(&mut self) -> LWESwitchingKey<&mut [u8]>; +} + +impl<D: DataMut> LWESwitchingKeyToMut for LWESwitchingKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToMut, +{ + fn to_mut(&mut self) -> LWESwitchingKey<&mut [u8]> { + LWESwitchingKey(self.0.to_mut()) + } +}
M poulpy-core/src/layouts/lwe_pt.rs → poulpy-core/src/layouts/lwe_pt.rs

@@ -1,8 +1,8 @@

use std::fmt; -use poulpy_hal::layouts::{Data, DataMut, DataRef, Zn, ZnToMut, ZnToRef, ZnxInfos}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Zn, ZnToMut, ZnToRef, ZnxInfos}; -use crate::layouts::{Base2K, Degree, LWEInfos, TorusPrecision}; +use crate::layouts::{Base2K, LWEInfos, RingDegree, TorusPrecision}; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct LWEPlaintextLayout {

@@ -19,8 +19,8 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { - Degree(0) + fn n(&self) -> RingDegree { + RingDegree(0) } fn size(&self) -> usize {

@@ -43,8 +43,8 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { - Degree(self.data.n() as u32 - 1) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32 - 1) } fn size(&self) -> usize {

@@ -52,20 +52,39 @@ self.data.size()

} } +pub trait LWEPlaintextAlloc { + fn alloc_lwe_plaintext(&self, base2k: Base2K, k: TorusPrecision) -> LWEPlaintext<Vec<u8>> { + LWEPlaintext { + data: Zn::alloc(1, 1, k.0.div_ceil(base2k.0) as usize), + k, + base2k, + } + } + + fn alloc_lwe_plaintext_from_infos<A>(&self, infos: &A) -> LWEPlaintext<Vec<u8>> + where + A: LWEInfos, + { + self.alloc_lwe_plaintext(infos.base2k(), infos.k()) + } +} + +impl<B: Backend> LWEPlaintextAlloc for Module<B> {} + impl LWEPlaintext<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: LWEInfos, + M: LWEPlaintextAlloc, { - Self::alloc_with(infos.base2k(), infos.k()) + module.alloc_lwe_plaintext_from_infos(infos) } - pub fn alloc_with(base2k: Base2K, k: TorusPrecision) -> Self { - Self { - data: Zn::alloc(1, 1, k.0.div_ceil(base2k.0) as usize), - k, - base2k, - } + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision) -> Self + where + M: LWEPlaintextAlloc, + { + module.alloc_lwe_plaintext(base2k, k) } }
M poulpy-core/src/layouts/lwe_sk.rs → poulpy-core/src/layouts/lwe_sk.rs

@@ -1,11 +1,11 @@

use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, ScalarZnx, ZnxInfos, ZnxView, ZnxZero}, + layouts::{Backend, Data, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToMut, ScalarZnxToRef, ZnxInfos, ZnxView, ZnxZero}, source::Source, }; use crate::{ dist::Distribution, - layouts::{Base2K, Degree, LWEInfos, TorusPrecision}, + layouts::{Base2K, LWEInfos, RingDegree, TorusPrecision}, }; pub struct LWESecret<D: Data> {

@@ -13,15 +13,26 @@ pub(crate) data: ScalarZnx<D>,

pub(crate) dist: Distribution, } -impl LWESecret<Vec<u8>> { - pub fn alloc(n: Degree) -> Self { - Self { +pub trait LWESecretAlloc { + fn alloc_lwe_secret(&self, n: RingDegree) -> LWESecret<Vec<u8>> { + LWESecret { data: ScalarZnx::alloc(n.into(), 1), dist: Distribution::NONE, } } } +impl<B: Backend> LWESecretAlloc for Module<B> {} + +impl LWESecret<Vec<u8>> { + pub fn alloc<M>(module: &M, n: RingDegree) -> Self + where + M: LWESecretAlloc, + { + module.alloc_lwe_secret(n) + } +} + impl<D: DataRef> LWESecret<D> { pub fn raw(&self) -> &[i64] { self.data.at(0, 0)

@@ -44,8 +55,8 @@ fn k(&self) -> TorusPrecision {

TorusPrecision(0) } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -84,3 +95,29 @@ self.data.zero();

self.dist = Distribution::ZERO; } } + +pub trait LWESecretToRef { + fn to_ref(&self) -> LWESecret<&[u8]>; +} + +impl<D: DataRef> LWESecretToRef for LWESecret<D> { + fn to_ref(&self) -> LWESecret<&[u8]> { + LWESecret { + dist: self.dist, + data: self.data.to_ref(), + } + } +} + +pub trait LWESecretToMut { + fn to_mut(&mut self) -> LWESecret<&mut [u8]>; +} + +impl<D: DataMut> LWESecretToMut for LWESecret<D> { + fn to_mut(&mut self) -> LWESecret<&mut [u8]> { + LWESecret { + dist: self.dist, + data: self.data.to_mut(), + } + } +}
M poulpy-core/src/layouts/lwe_to_glwe_ksk.rs → poulpy-core/src/layouts/lwe_to_glwe_ksk.rs

@@ -1,15 +1,18 @@

use std::fmt; use poulpy_hal::{ - layouts::{Data, DataMut, DataRef, FillUniform, ReaderFrom, WriterTo}, + layouts::{Backend, Data, DataMut, DataRef, FillUniform, Module, ReaderFrom, WriterTo}, source::Source, }; -use crate::layouts::{Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision}; +use crate::layouts::{ + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyAlloc, GLWESwitchingKeyToMut, + GLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision, +}; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct LWEToGLWESwitchingKeyLayout { - pub n: Degree, + pub n: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub rank_out: Rank,

@@ -25,7 +28,7 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n } }

@@ -55,7 +58,7 @@ }

} #[derive(PartialEq, Eq, Clone)] -pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GGLWESwitchingKey<D>); +pub struct LWEToGLWESwitchingKey<D: Data>(pub(crate) GLWESwitchingKey<D>); impl<D: Data> LWEInfos for LWEToGLWESwitchingKey<D> { fn base2k(&self) -> Base2K {

@@ -66,7 +69,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -128,54 +131,116 @@ self.0.write_to(writer)

} } -impl LWEToGLWESwitchingKey<Vec<u8>> { - pub fn alloc<A>(infos: &A) -> Self +pub trait LWEToGLWESwitchingKeyAlloc +where + Self: GLWESwitchingKeyAlloc, +{ + fn alloc_lwe_to_glwe_switching_key( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_out: Rank, + dnum: Dnum, + ) -> LWEToGLWESwitchingKey<Vec<u8>> { + LWEToGLWESwitchingKey(self.alloc_glwe_switching_key(base2k, k, Rank(1), rank_out, dnum, Dsize(1))) + } + + fn alloc_lwe_to_glwe_switching_key_from_infos<A>(&self, infos: &A) -> LWEToGLWESwitchingKey<Vec<u8>> where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, "rank_in > 1 is not supported for LWEToGLWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for LWEToGLWESwitchingKey" ); - Self(GGLWESwitchingKey::alloc(infos)) + + self.alloc_lwe_to_glwe_switching_key(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum()) } - pub fn alloc_with(n: Degree, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self { - Self(GGLWESwitchingKey::alloc_with( - n, - base2k, - k, - Rank(1), - rank_out, - dnum, - Dsize(1), - )) + fn bytes_of_lwe_to_glwe_switching_key(&self, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key(base2k, k, Rank(1), rank_out, dnum, Dsize(1)) } - pub fn alloc_bytes<A>(infos: &A) -> usize + fn bytes_of_lwe_to_glwe_switching_key_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, { - debug_assert_eq!( + assert_eq!( infos.rank_in().0, 1, "rank_in > 1 is not supported for LWEToGLWESwitchingKey" ); - debug_assert_eq!( + assert_eq!( infos.dsize().0, 1, "dsize > 1 is not supported for LWEToGLWESwitchingKey" ); - GGLWESwitchingKey::alloc_bytes(infos) + self.bytes_of_lwe_to_glwe_switching_key(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum()) + } +} + +impl<B: Backend> LWEToGLWESwitchingKeyAlloc for Module<B> where Self: GLWESwitchingKeyAlloc {} + +impl LWEToGLWESwitchingKey<Vec<u8>> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyAlloc, + { + module.alloc_lwe_to_glwe_switching_key_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self + where + M: LWEToGLWESwitchingKeyAlloc, + { + module.alloc_lwe_to_glwe_switching_key(base2k, k, rank_out, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyAlloc, + { + module.bytes_of_lwe_to_glwe_switching_key_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize + where + M: LWEToGLWESwitchingKeyAlloc, + { + module.bytes_of_lwe_to_glwe_switching_key(base2k, k, rank_out, dnum) + } +} + +pub trait LWEToGLWESwitchingKeyToRef { + fn to_ref(&self) -> LWEToGLWESwitchingKey<&[u8]>; +} + +impl<D: DataRef> LWEToGLWESwitchingKeyToRef for LWEToGLWESwitchingKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToRef, +{ + fn to_ref(&self) -> LWEToGLWESwitchingKey<&[u8]> { + LWEToGLWESwitchingKey(self.0.to_ref()) } +} - pub fn alloc_bytes_with(n: Degree, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize { - GGLWESwitchingKey::alloc_bytes_with(n, base2k, k, Rank(1), rank_out, dnum, Dsize(1)) +pub trait LWEToGLWESwitchingKeyToMut { + fn to_mut(&mut self) -> LWEToGLWESwitchingKey<&mut [u8]>; +} + +impl<D: DataMut> LWEToGLWESwitchingKeyToMut for LWEToGLWESwitchingKey<D> +where + GLWESwitchingKey<D>: GLWESwitchingKeyToMut, +{ + fn to_mut(&mut self) -> LWEToGLWESwitchingKey<&mut [u8]> { + LWEToGLWESwitchingKey(self.0.to_mut()) } }
M poulpy-core/src/layouts/mod.rs → poulpy-core/src/layouts/mod.rs

@@ -33,20 +33,16 @@ pub use lwe_pt::*;

pub use lwe_sk::*; pub use lwe_to_glwe_ksk::*; -#[derive(Debug)] -pub enum BuildError { - MissingData, - MissingBase2K, - MissingK, - MissingDigits, - ZeroDegree, - NonPowerOfTwoDegree, - ZeroBase2K, - ZeroTorusPrecision, - ZeroCols, - ZeroLimbs, - ZeroRank, - ZeroDigits, +use poulpy_hal::layouts::{Backend, Module}; + +pub trait GetRingDegree { + fn ring_degree(&self) -> RingDegree; +} + +impl<B: Backend> GetRingDegree for Module<B> { + fn ring_degree(&self) -> RingDegree { + Self::n(&self).into() + } } /// Newtype over `u32` with arithmetic and comparisons against same type and `u32`.

@@ -206,14 +202,14 @@ }

}; } -newtype_u32!(Degree); +newtype_u32!(RingDegree); newtype_u32!(TorusPrecision); newtype_u32!(Base2K); newtype_u32!(Dnum); newtype_u32!(Rank); newtype_u32!(Dsize); -impl Degree { +impl RingDegree { pub fn log2(&self) -> usize { let n: usize = self.0 as usize; (usize::BITS - (n - 1).leading_zeros()) as _
M poulpy-core/src/layouts/prepared/gglwe_atk.rs → poulpy-core/src/layouts/prepared/gglwe_atk.rs

@@ -1,27 +1,21 @@

-use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace}, + AutomorphismKeyToRef, Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TorusPrecision, + prepared::{ + GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut, + GLWESwitchingKeyPreparedToRef, + }, }; #[derive(PartialEq, Eq)] -pub struct GGLWEAutomorphismKeyPrepared<D: Data, B: Backend> { - pub(crate) key: GGLWESwitchingKeyPrepared<D, B>, +pub struct AutomorphismKeyPrepared<D: Data, B: Backend> { + pub(crate) key: GLWESwitchingKeyPrepared<D, B>, pub(crate) p: i64, } -impl<D: Data, B: Backend> GGLWEAutomorphismKeyPrepared<D, B> { - pub fn p(&self) -> i64 { - self.p - } -} - -impl<D: Data, B: Backend> LWEInfos for GGLWEAutomorphismKeyPrepared<D, B> { - fn n(&self) -> Degree { +impl<D: Data, B: Backend> LWEInfos for AutomorphismKeyPrepared<D, B> { + fn n(&self) -> RingDegree { self.key.n() }

@@ -38,13 +32,33 @@ self.key.size()

} } -impl<D: Data, B: Backend> GLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> { +pub trait GetAutomorphismGaloisElement { + fn p(&self) -> i64; +} + +impl<D: Data, B: Backend> GetAutomorphismGaloisElement for AutomorphismKeyPrepared<D, B> { + fn p(&self) -> i64 { + self.p + } +} + +pub trait SetAutomorphismGaloisElement { + fn set_p(&mut self, p: i64); +} + +impl<D: Data, B: Backend> SetAutomorphismGaloisElement for AutomorphismKeyPrepared<D, B> { + fn set_p(&mut self, p: i64) { + self.p = p + } +} + +impl<D: Data, B: Backend> GLWEInfos for AutomorphismKeyPrepared<D, B> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data, B: Backend> GGLWEInfos for GGLWEAutomorphismKeyPrepared<D, B> { +impl<D: Data, B: Backend> GGLWEInfos for AutomorphismKeyPrepared<D, B> { fn rank_in(&self) -> Rank { self.key.rank_in() }

@@ -62,80 +76,170 @@ self.key.dnum()

} } -impl<B: Backend> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self +pub trait AutomorphismKeyPreparedAlloc<B: Backend> +where + Self: GLWESwitchingKeyPreparedAlloc<B>, +{ + fn alloc_automorphism_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> AutomorphismKeyPrepared<Vec<u8>, B> { + AutomorphismKeyPrepared::<Vec<u8>, B> { + key: self.alloc_glwe_switching_key_prepared(base2k, k, rank, rank, dnum, dsize), + p: 0, + } + } + + fn alloc_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> AutomorphismKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { assert_eq!( infos.rank_in(), infos.rank_out(), - "rank_in != rank_out is not supported for GGLWEAutomorphismKeyPrepared" + "rank_in != rank_out is not supported for AutomorphismKeyPrepared" ); - GGLWEAutomorphismKeyPrepared::<Vec<u8>, B> { - key: GGLWESwitchingKeyPrepared::alloc(module, infos), - p: 0, - } + self.alloc_automorphism_key_prepared( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self - where - Module<B>: VmpPMatAlloc<B>, - { - GGLWEAutomorphismKeyPrepared { - key: GGLWESwitchingKeyPrepared::alloc_with(module, base2k, k, rank, rank, dnum, dsize), - p: 0, - } + fn bytes_of_automorphism_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize { + self.bytes_of_glwe_switching_key_prepared(base2k, k, rank, rank, dnum, dsize) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + fn bytes_of_automorphism_key_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, { assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWEAutomorphismKeyPrepared" ); - GGLWESwitchingKeyPrepared::alloc_bytes(module, infos) + self.bytes_of_automorphism_key_prepared( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) } +} - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize +impl<B: Backend> AutomorphismKeyPreparedAlloc<B> for Module<B> where Module<B>: GLWESwitchingKeyPreparedAlloc<B> {} + +impl<B: Backend> AutomorphismKeyPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where - Module<B>: VmpPMatAllocBytes, + A: GGLWEInfos, + M: AutomorphismKeyPreparedAlloc<B>, { - GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rank, rank, dnum, dsize) + module.alloc_automorphism_key_prepared_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> Self + where + M: AutomorphismKeyPreparedAlloc<B>, + { + module.alloc_automorphism_key_prepared(base2k, k, rank, dnum, dsize) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: AutomorphismKeyPreparedAlloc<B>, + { + module.bytes_of_automorphism_key_prepared_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: AutomorphismKeyPreparedAlloc<B>, + { + module.bytes_of_automorphism_key_prepared(base2k, k, rank, dnum, dsize) } } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWEAutomorphismKeyPrepared<Vec<u8>, B> +pub trait PrepareAutomorphismKey<B: Backend> where - GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>, + Self: GLWESwitchingKeyPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos) + fn prepare_automorphism_key_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.prepare_glwe_switching_key_tmp_bytes(infos) + } + + fn prepare_automorphism_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: AutomorphismKeyPreparedToMut<B> + SetAutomorphismGaloisElement, + O: AutomorphismKeyToRef + GetAutomorphismGaloisElement, + { + self.prepare_glwe_switching(&mut res.to_mut().key, &other.to_ref().key, scratch); + res.set_p(other.p()); + } +} + +impl<B: Backend> PrepareAutomorphismKey<B> for Module<B> where Module<B>: GLWESwitchingKeyPrepare<B> {} + +impl<B: Backend> AutomorphismKeyPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize + where + M: PrepareAutomorphismKey<B>, + { + module.prepare_automorphism_key_tmp_bytes(self) } } -impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWEAutomorphismKey<DR>> for GGLWEAutomorphismKeyPrepared<D, B> -where - Module<B>: VmpPrepare<B>, -{ - fn prepare(&mut self, module: &Module<B>, other: &GGLWEAutomorphismKey<DR>, scratch: &mut Scratch<B>) { - self.key.prepare(module, &other.key, scratch); - self.p = other.p; +impl<D: DataMut, B: Backend> AutomorphismKeyPrepared<D, B> { + pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: AutomorphismKeyToRef + GetAutomorphismGaloisElement, + M: PrepareAutomorphismKey<B>, + { + module.prepare_automorphism_key(self, other, scratch); + } +} + +pub trait AutomorphismKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> AutomorphismKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> AutomorphismKeyPreparedToMut<B> for AutomorphismKeyPrepared<D, B> { + fn to_mut(&mut self) -> AutomorphismKeyPrepared<&mut [u8], B> { + AutomorphismKeyPrepared { + p: self.p, + key: self.key.to_mut(), + } } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> for GGLWEAutomorphismKey<D> -where - Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>, -{ - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWEAutomorphismKeyPrepared<Vec<u8>, B> { - let mut atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = GGLWEAutomorphismKeyPrepared::alloc(module, self); - atk_prepared.prepare(module, self, scratch); - atk_prepared +pub trait AutomorphismKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> AutomorphismKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> AutomorphismKeyPreparedToRef<B> for AutomorphismKeyPrepared<D, B> { + fn to_ref(&self) -> AutomorphismKeyPrepared<&[u8], B> { + AutomorphismKeyPrepared { + p: self.p, + key: self.key.to_ref(), + } } }
M poulpy-core/src/layouts/prepared/gglwe_ct.rs → poulpy-core/src/layouts/prepared/gglwe_ct.rs

@@ -1,25 +1,23 @@

use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare, VmpPrepareTmpBytes}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, ZnxInfos}, - oep::VmpPMatAllocBytesImpl, + api::{VmpPMatAlloc, VmpPMatBytesOf, VmpPrepare, VmpPrepareTmpBytes}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToMut, VmpPMatToRef, ZnxInfos}, }; use crate::layouts::{ - Base2K, BuildError, Degree, Dnum, Dsize, GGLWECiphertext, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - prepared::{Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGLWE, GGLWEInfos, GGLWEToRef, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision, }; #[derive(PartialEq, Eq)] -pub struct GGLWECiphertextPrepared<D: Data, B: Backend> { +pub struct GGLWEPrepared<D: Data, B: Backend> { pub(crate) data: VmpPMat<D, B>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K, pub(crate) dsize: Dsize, } -impl<D: Data, B: Backend> LWEInfos for GGLWECiphertextPrepared<D, B> { - fn n(&self) -> Degree { - Degree(self.data.n() as u32) +impl<D: Data, B: Backend> LWEInfos for GGLWEPrepared<D, B> { + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn base2k(&self) -> Base2K {

@@ -35,13 +33,13 @@ self.data.size()

} } -impl<D: Data, B: Backend> GLWEInfos for GGLWECiphertextPrepared<D, B> { +impl<D: Data, B: Backend> GLWEInfos for GGLWEPrepared<D, B> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data, B: Backend> GGLWEInfos for GGLWECiphertextPrepared<D, B> { +impl<D: Data, B: Backend> GGLWEInfos for GGLWEPrepared<D, B> { fn rank_in(&self) -> Rank { Rank(self.data.cols_in() as u32) }

@@ -59,117 +57,47 @@ Dnum(self.data.rows() as u32)

} } -pub struct GGLWECiphertextPreparedBuilder<D: Data, B: Backend> { - data: Option<VmpPMat<D, B>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, - dsize: Option<Dsize>, -} - -impl<D: Data, B: Backend> GGLWECiphertextPrepared<D, B> { - #[inline] - pub fn builder() -> GGLWECiphertextPreparedBuilder<D, B> { - GGLWECiphertextPreparedBuilder { - data: None, - base2k: None, - k: None, - dsize: None, - } - } -} - -impl<B: Backend> GGLWECiphertextPreparedBuilder<Vec<u8>, B> { - #[inline] - pub fn layout<A>(mut self, infos: &A) -> Self - where - A: GGLWEInfos, - B: VmpPMatAllocBytesImpl<B>, - { - self.data = Some(VmpPMat::alloc( - infos.n().into(), - infos.dnum().into(), - infos.rank_in().into(), - (infos.rank_out() + 1).into(), - infos.size(), - )); - self.base2k = Some(infos.base2k()); - self.k = Some(infos.k()); - self.dsize = Some(infos.dsize()); - self - } -} - -impl<D: Data, B: Backend> GGLWECiphertextPreparedBuilder<D, B> { - #[inline] - pub fn data(mut self, data: VmpPMat<D, B>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self - } - - #[inline] - pub fn dsize(mut self, dsize: Dsize) -> Self { - self.dsize = Some(dsize); - self - } +pub trait GGLWEPreparedAlloc<B: Backend> +where + Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf, +{ + fn alloc_gglwe_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> GGLWEPrepared<Vec<u8>, B> { + let size: usize = k.0.div_ceil(base2k.0) as usize; + debug_assert!( + size as u32 > dsize.0, + "invalid gglwe: ceil(k/base2k): {size} <= dsize: {}", + dsize.0 + ); - pub fn build(self) -> Result<GGLWECiphertextPrepared<D, B>, BuildError> { - let data: VmpPMat<D, B> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?; - - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } + assert!( + dnum.0 * dsize.0 <= size as u32, + "invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}", + dnum.0, + dsize.0, + ); - if dsize == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GGLWECiphertextPrepared { - data, + GGLWEPrepared { + data: self.vmp_pmat_alloc(dnum.into(), rank_in.into(), (rank_out + 1).into(), size), + k, base2k, - k, dsize, - }) + } } -} -impl<B: Backend> GGLWECiphertextPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self + fn alloc_gglwe_prepared_from_infos<A>(&self, infos: &A) -> GGLWEPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { - debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()"); - Self::alloc_with( - module, + assert_eq!(self.ring_degree(), infos.n()); + self.alloc_gglwe_prepared( infos.base2k(), infos.k(), infos.rank_in(),

@@ -179,18 +107,15 @@ infos.dsize(),

) } - pub fn alloc_with( - module: &Module<B>, + fn bytes_of_gglwe_prepared( + &self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> Self - where - Module<B>: VmpPMatAlloc<B>, - { + ) -> usize { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -205,22 +130,15 @@ dnum.0,

dsize.0, ); - Self { - data: module.vmp_pmat_alloc(dnum.into(), rank_in.into(), (rank_out + 1).into(), size), - k, - base2k, - dsize, - } + self.bytes_of_vmp_pmat(dnum.into(), rank_in.into(), (rank_out + 1).into(), size) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + fn bytes_of_gglwe_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, { - debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()"); - Self::alloc_bytes_with( - module, + assert_eq!(self.ring_degree(), infos.n()); + self.bytes_of_gglwe_prepared( infos.base2k(), infos.k(), infos.rank_in(),

@@ -229,70 +147,139 @@ infos.dnum(),

infos.dsize(), ) } +} - pub fn alloc_bytes_with( - module: &Module<B>, +impl<B: Backend> GGLWEPreparedAlloc<B> for Module<B> where Module<B>: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf {} + +impl<B: Backend> GGLWEPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GGLWEPreparedAlloc<B>, + { + module.alloc_gglwe_prepared_from_infos(infos) + } + + pub fn alloc<M>( + module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, - ) -> usize + ) -> Self where - Module<B>: VmpPMatAllocBytes, + M: GGLWEPreparedAlloc<B>, { - let size: usize = k.0.div_ceil(base2k.0) as usize; - debug_assert!( - size as u32 > dsize.0, - "invalid gglwe: ceil(k/base2k): {size} <= dsize: {}", - dsize.0 - ); + module.alloc_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize) + } - assert!( - dnum.0 * dsize.0 <= size as u32, - "invalid gglwe: dnum: {} * dsize:{} > ceil(k/base2k): {size}", - dnum.0, - dsize.0, - ); + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GGLWEPreparedAlloc<B>, + { + module.bytes_of_gglwe_prepared_from_infos(infos) + } - module.vmp_pmat_alloc_bytes(dnum.into(), rank_in.into(), (rank_out + 1).into(), size) + pub fn bytes_of<M>( + module: &M, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize + where + M: GGLWEPreparedAlloc<B>, + { + module.bytes_of_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize) } } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWECiphertextPrepared<Vec<u8>, B> +pub trait GGLWEPrepare<B: Backend> where - Module<B>: VmpPrepareTmpBytes, + Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - module.vmp_prepare_tmp_bytes( + fn prepare_gglwe_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.vmp_prepare_tmp_bytes( infos.dnum().into(), infos.rank_in().into(), (infos.rank() + 1).into(), infos.size(), ) } + + fn prepare_gglwe<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: GGLWEPreparedToMut<B>, + O: GGLWEToRef, + { + let mut res: GGLWEPrepared<&mut [u8], B> = res.to_mut(); + let other: GGLWE<&[u8]> = other.to_ref(); + + assert_eq!(res.n(), self.ring_degree()); + assert_eq!(other.n(), self.ring_degree()); + assert_eq!(res.base2k, other.base2k); + assert_eq!(res.k, other.k); + assert_eq!(res.dsize, other.dsize); + + self.vmp_prepare(&mut res.data, &other.data, scratch); + } } -impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWECiphertext<DR>> for GGLWECiphertextPrepared<D, B> -where - Module<B>: VmpPrepare<B>, -{ - fn prepare(&mut self, module: &Module<B>, other: &GGLWECiphertext<DR>, scratch: &mut Scratch<B>) { - module.vmp_prepare(&mut self.data, &other.data, scratch); - self.k = other.k; - self.base2k = other.base2k; - self.dsize = other.dsize; +impl<B: Backend> GGLWEPrepare<B> for Module<B> where Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B> {} + +impl<D: DataMut, B: Backend> GGLWEPrepared<D, B> { + pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: GGLWEToRef, + M: GGLWEPrepare<B>, + { + module.prepare_gglwe(self, other, scratch); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWECiphertextPrepared<Vec<u8>, B>> for GGLWECiphertext<D> -where - Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>, -{ - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWECiphertextPrepared<Vec<u8>, B> { - let mut atk_prepared: GGLWECiphertextPrepared<Vec<u8>, B> = GGLWECiphertextPrepared::alloc(module, self); - atk_prepared.prepare(module, self, scratch); - atk_prepared +impl<B: Backend> GGLWEPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize + where + M: GGLWEPrepare<B>, + { + module.prepare_gglwe_tmp_bytes(self) + } +} + +pub trait GGLWEPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> GGLWEPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> GGLWEPreparedToMut<B> for GGLWEPrepared<D, B> { + fn to_mut(&mut self) -> GGLWEPrepared<&mut [u8], B> { + GGLWEPrepared { + k: self.k, + base2k: self.base2k, + dsize: self.dsize, + data: self.data.to_mut(), + } + } +} + +pub trait GGLWEPreparedToRef<B: Backend> { + fn to_ref(&self) -> GGLWEPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> GGLWEPreparedToRef<B> for GGLWEPrepared<D, B> { + fn to_ref(&self) -> GGLWEPrepared<&[u8], B> { + GGLWEPrepared { + k: self.k, + base2k: self.base2k, + dsize: self.dsize, + data: self.data.to_ref(), + } } }
M poulpy-core/src/layouts/prepared/gglwe_ksk.rs → poulpy-core/src/layouts/prepared/gglwe_ksk.rs

@@ -1,22 +1,40 @@

-use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, LWEInfos, Rank, TorusPrecision, - prepared::{GGLWECiphertextPrepared, Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKeySetMetaData, GLWESwitchingKeyToRef, GLWESwtichingKeyGetMetaData, + LWEInfos, Rank, RingDegree, TorusPrecision, + prepared::{GGLWEPrepare, GGLWEPrepared, GGLWEPreparedAlloc, GGLWEPreparedToMut, GGLWEPreparedToRef}, }; #[derive(PartialEq, Eq)] -pub struct GGLWESwitchingKeyPrepared<D: Data, B: Backend> { - pub(crate) key: GGLWECiphertextPrepared<D, B>, +pub struct GLWESwitchingKeyPrepared<D: Data, B: Backend> { + pub(crate) key: GGLWEPrepared<D, B>, pub(crate) sk_in_n: usize, // Degree of sk_in pub(crate) sk_out_n: usize, // Degree of sk_out } -impl<D: Data, B: Backend> LWEInfos for GGLWESwitchingKeyPrepared<D, B> { - fn n(&self) -> Degree { +impl<D: DataMut, B: Backend> GLWESwitchingKeySetMetaData for GLWESwitchingKeyPrepared<D, B> { + fn set_sk_in_n(&mut self, sk_in_n: usize) { + self.sk_in_n = sk_in_n + } + + fn set_sk_out_n(&mut self, sk_out_n: usize) { + self.sk_out_n = sk_out_n + } +} + +impl<D: DataRef, B: Backend> GLWESwtichingKeyGetMetaData for GLWESwitchingKeyPrepared<D, B> { + fn sk_in_n(&self) -> usize { + self.sk_in_n + } + + fn sk_out_n(&self) -> usize { + self.sk_out_n + } +} + +impl<D: Data, B: Backend> LWEInfos for GLWESwitchingKeyPrepared<D, B> { + fn n(&self) -> RingDegree { self.key.n() }

@@ -33,13 +51,13 @@ self.key.size()

} } -impl<D: Data, B: Backend> GLWEInfos for GGLWESwitchingKeyPrepared<D, B> { +impl<D: Data, B: Backend> GLWEInfos for GLWESwitchingKeyPrepared<D, B> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data, B: Backend> GGLWEInfos for GGLWESwitchingKeyPrepared<D, B> { +impl<D: Data, B: Backend> GGLWEInfos for GLWESwitchingKeyPrepared<D, B> { fn rank_in(&self) -> Rank { self.key.rank_in() }

@@ -57,22 +75,80 @@ self.key.dnum()

} } -impl<B: Backend> GGLWESwitchingKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self +pub trait GLWESwitchingKeyPreparedAlloc<B: Backend> +where + Self: GGLWEPreparedAlloc<B>, +{ + fn alloc_glwe_switching_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> GLWESwitchingKeyPrepared<Vec<u8>, B> { + GLWESwitchingKeyPrepared::<Vec<u8>, B> { + key: self.alloc_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize), + sk_in_n: 0, + sk_out_n: 0, + } + } + + fn alloc_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> GLWESwitchingKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { - debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()"); - GGLWESwitchingKeyPrepared::<Vec<u8>, B> { - key: GGLWECiphertextPrepared::alloc(module, infos), - sk_in_n: 0, - sk_out_n: 0, - } + self.alloc_glwe_switching_key_prepared( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.rank_out(), + infos.dnum(), + infos.dsize(), + ) + } + + fn bytes_of_glwe_switching_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + rank_out: Rank, + dnum: Dnum, + dsize: Dsize, + ) -> usize { + self.bytes_of_gglwe_prepared(base2k, k, rank_in, rank_out, dnum, dsize) + } + + fn bytes_of_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.bytes_of_glwe_switching_key_prepared( + infos.base2k(), + infos.k(), + infos.rank_in(), + infos.rank_out(), + infos.dnum(), + infos.dsize(), + ) + } +} + +impl<B: Backend> GLWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GGLWEPreparedAlloc<B> {} + +impl<B: Backend> GLWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GLWESwitchingKeyPreparedAlloc<B>, + { + module.alloc_glwe_switching_key_prepared_from_infos(infos) } - pub fn alloc_with( - module: &Module<B>, + pub fn alloc<M>( + module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank,

@@ -81,26 +157,21 @@ dnum: Dnum,

dsize: Dsize, ) -> Self where - Module<B>: VmpPMatAlloc<B>, + M: GLWESwitchingKeyPreparedAlloc<B>, { - GGLWESwitchingKeyPrepared::<Vec<u8>, B> { - key: GGLWECiphertextPrepared::alloc_with(module, base2k, k, rank_in, rank_out, dnum, dsize), - sk_in_n: 0, - sk_out_n: 0, - } + module.alloc_glwe_switching_key_prepared(base2k, k, rank_in, rank_out, dnum, dsize) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, + M: GLWESwitchingKeyPreparedAlloc<B>, { - debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()"); - GGLWECiphertextPrepared::alloc_bytes(module, infos) + module.bytes_of_glwe_switching_key_prepared_from_infos(infos) } - pub fn alloc_bytes_with( - module: &Module<B>, + pub fn bytes_of<M>( + module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank,

@@ -109,39 +180,79 @@ dnum: Dnum,

dsize: Dsize, ) -> usize where - Module<B>: VmpPMatAllocBytes, + M: GLWESwitchingKeyPreparedAlloc<B>, { - GGLWECiphertextPrepared::alloc_bytes_with(module, base2k, k, rank_in, rank_out, dnum, dsize) + module.bytes_of_glwe_switching_key_prepared(base2k, k, rank_in, rank_out, dnum, dsize) } } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWESwitchingKeyPrepared<Vec<u8>, B> +pub trait GLWESwitchingKeyPrepare<B: Backend> where - GGLWECiphertextPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>, + Self: GGLWEPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - GGLWECiphertextPrepared::prepare_scratch_space(module, infos) + fn prepare_glwe_switching_key_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.prepare_gglwe_tmp_bytes(infos) + } + + fn prepare_glwe_switching<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: GLWESwitchingKeyPreparedToMut<B> + GLWESwitchingKeySetMetaData, + O: GLWESwitchingKeyToRef + GLWESwtichingKeyGetMetaData, + { + self.prepare_gglwe(&mut res.to_mut().key, &other.to_ref().key, scratch); + res.set_sk_in_n(other.sk_in_n()); + res.set_sk_out_n(other.sk_out_n()); } } -impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWESwitchingKey<DR>> for GGLWESwitchingKeyPrepared<D, B> -where - Module<B>: VmpPrepare<B>, -{ - fn prepare(&mut self, module: &Module<B>, other: &GGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) { - self.key.prepare(module, &other.key, scratch); - self.sk_in_n = other.sk_in_n; - self.sk_out_n = other.sk_out_n; +impl<B: Backend> GLWESwitchingKeyPrepare<B> for Module<B> where Self: GGLWEPrepare<B> {} + +impl<D: DataMut, B: Backend> GLWESwitchingKeyPrepared<D, B> { + pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: GLWESwitchingKeyToRef + GLWESwtichingKeyGetMetaData, + M: GLWESwitchingKeyPrepare<B>, + { + module.prepare_glwe_switching(self, other, scratch); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWESwitchingKeyPrepared<Vec<u8>, B>> for GGLWESwitchingKey<D> -where - Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>, -{ - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWESwitchingKeyPrepared<Vec<u8>, B> { - let mut atk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = GGLWESwitchingKeyPrepared::alloc(module, self); - atk_prepared.prepare(module, self, scratch); - atk_prepared +impl<B: Backend> GLWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<M>(&self, module: &M) -> usize + where + M: GLWESwitchingKeyPrepare<B>, + { + module.prepare_glwe_switching_key_tmp_bytes(self) + } +} + +pub trait GLWESwitchingKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> GLWESwitchingKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> GLWESwitchingKeyPreparedToMut<B> for GLWESwitchingKeyPrepared<D, B> { + fn to_mut(&mut self) -> GLWESwitchingKeyPrepared<&mut [u8], B> { + GLWESwitchingKeyPrepared { + sk_in_n: self.sk_in_n, + sk_out_n: self.sk_out_n, + key: self.key.to_mut(), + } + } +} + +pub trait GLWESwitchingKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> GLWESwitchingKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> GLWESwitchingKeyPreparedToRef<B> for GLWESwitchingKeyPrepared<D, B> { + fn to_ref(&self) -> GLWESwitchingKeyPrepared<&[u8], B> { + GLWESwitchingKeyPrepared { + sk_in_n: self.sk_in_n, + sk_out_n: self.sk_out_n, + key: self.key.to_ref(), + } } }
M poulpy-core/src/layouts/prepared/gglwe_tsk.rs → poulpy-core/src/layouts/prepared/gglwe_tsk.rs

@@ -1,20 +1,20 @@

-use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision, - prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TensorKey, TensorKeyToRef, TorusPrecision, + prepared::{ + GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut, + GLWESwitchingKeyPreparedToRef, + }, }; #[derive(PartialEq, Eq)] -pub struct GGLWETensorKeyPrepared<D: Data, B: Backend> { - pub(crate) keys: Vec<GGLWESwitchingKeyPrepared<D, B>>, +pub struct TensorKeyPrepared<D: Data, B: Backend> { + pub(crate) keys: Vec<GLWESwitchingKeyPrepared<D, B>>, } -impl<D: Data, B: Backend> LWEInfos for GGLWETensorKeyPrepared<D, B> { - fn n(&self) -> Degree { +impl<D: Data, B: Backend> LWEInfos for TensorKeyPrepared<D, B> { + fn n(&self) -> RingDegree { self.keys[0].n() }

@@ -31,13 +31,13 @@ self.keys[0].size()

} } -impl<D: Data, B: Backend> GLWEInfos for GGLWETensorKeyPrepared<D, B> { +impl<D: Data, B: Backend> GLWEInfos for TensorKeyPrepared<D, B> { fn rank(&self) -> Rank { self.rank_out() } } -impl<D: Data, B: Backend> GGLWEInfos for GGLWETensorKeyPrepared<D, B> { +impl<D: Data, B: Backend> GGLWEInfos for TensorKeyPrepared<D, B> { fn rank_in(&self) -> Rank { self.rank_out() }

@@ -55,19 +55,36 @@ self.keys[0].dnum()

} } -impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self +pub trait TensorKeyPreparedAlloc<B: Backend> +where + Self: GLWESwitchingKeyPreparedAlloc<B>, +{ + fn alloc_tensor_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + dnum: Dnum, + dsize: Dsize, + rank: Rank, + ) -> TensorKeyPrepared<Vec<u8>, B> { + let pairs: u32 = (((rank.as_u32() + 1) * rank.as_u32()) >> 1).max(1); + TensorKeyPrepared { + keys: (0..pairs) + .map(|_| self.alloc_glwe_switching_key_prepared(base2k, k, Rank(1), rank, dnum, dsize)) + .collect(), + } + } + + fn alloc_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> TensorKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKeyPrepared" ); - Self::alloc_with( - module, + self.alloc_tensor_key_prepared( infos.base2k(), infos.k(), infos.dnum(),

@@ -76,62 +93,62 @@ infos.rank_out(),

) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self + fn bytes_of_tensor_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize { + let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize; + pairs * self.bytes_of_glwe_switching_key_prepared(base2k, k, Rank(1), rank, dnum, dsize) + } + + fn bytes_of_tensor_key_prepared_from_infos<A>(&self, infos: &A) -> usize where - Module<B>: VmpPMatAlloc<B>, + A: GGLWEInfos, { - let mut keys: Vec<GGLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new(); - let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1); - (0..pairs).for_each(|_| { - keys.push(GGLWESwitchingKeyPrepared::alloc_with( - module, - base2k, - k, - Rank(1), - rank, - dnum, - dsize, - )); - }); - Self { keys } + self.bytes_of_tensor_key_prepared( + infos.base2k(), + infos.k(), + infos.rank(), + infos.dnum(), + infos.dsize(), + ) } +} + +impl<B: Backend> TensorKeyPreparedAlloc<B> for Module<B> where Module<B>: GLWESwitchingKeyPreparedAlloc<B> {} - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize +impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, + M: TensorKeyPreparedAlloc<B>, { - assert_eq!( - infos.rank_in(), - infos.rank_out(), - "rank_in != rank_out is not supported for GGLWETensorKey" - ); - let rank_out: usize = infos.rank_out().into(); - let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1); - pairs - * GGLWESwitchingKeyPrepared::alloc_bytes_with( - module, - infos.base2k(), - infos.k(), - Rank(1), - infos.rank_out(), - infos.dnum(), - infos.dsize(), - ) + module.alloc_tensor_key_prepared_from_infos(infos) } - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + pub fn alloc_with<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self where - Module<B>: VmpPMatAllocBytes, + M: TensorKeyPreparedAlloc<B>, { - let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize; - pairs * GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank, dnum, dsize) + module.alloc_tensor_key_prepared(base2k, k, dnum, dsize, rank) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: TensorKeyPreparedAlloc<B>, + { + module.bytes_of_tensor_key_prepared_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize + where + M: TensorKeyPreparedAlloc<B>, + { + module.bytes_of_tensor_key_prepared(base2k, k, rank, dnum, dsize) } } -impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> { +impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> { // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyPrepared<D, B> { + pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyPrepared<D, B> { if i > j { std::mem::swap(&mut i, &mut j); };

@@ -140,9 +157,9 @@ &mut self.keys[i * rank + j - (i * (i + 1) / 2)]

} } -impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> { +impl<D: DataRef, B: Backend> TensorKeyPrepared<D, B> { // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) - pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyPrepared<D, B> { + pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyPrepared<D, B> { if i > j { std::mem::swap(&mut i, &mut j); };

@@ -151,40 +168,81 @@ &self.keys[i * rank + j - (i * (i + 1) / 2)]

} } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWETensorKeyPrepared<Vec<u8>, B> +pub trait TensorKeyPrepare<B: Backend> where - GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>, + Self: GLWESwitchingKeyPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos) + fn prepare_tensor_key_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: GGLWEInfos, + { + self.prepare_glwe_switching_key_tmp_bytes(infos) + } + + fn prepare_tensor_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: TensorKeyPreparedToMut<B>, + O: TensorKeyToRef, + { + let mut res: TensorKeyPrepared<&mut [u8], B> = res.to_mut(); + let other: TensorKey<&[u8]> = other.to_ref(); + + assert_eq!(res.keys.len(), other.keys.len()); + + for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) { + self.prepare_glwe_switching(a, b, scratch); + } + } +} + +impl<B: Backend> TensorKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {} + +impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> { + fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: TensorKeyPrepare<B>, + { + module.prepare_tensor_key_tmp_bytes(infos) } } -impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWETensorKey<DR>> for GGLWETensorKeyPrepared<D, B> +impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> { + fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: TensorKeyToRef, + M: TensorKeyPrepare<B>, + { + module.prepare_tensor_key(self, other, scratch); + } +} + +pub trait TensorKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> TensorKeyPreparedToMut<B> for TensorKeyPrepared<D, B> where - Module<B>: VmpPrepare<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>, { - fn prepare(&mut self, module: &Module<B>, other: &GGLWETensorKey<DR>, scratch: &mut Scratch<B>) { - #[cfg(debug_assertions)] - { - assert_eq!(self.keys.len(), other.keys.len()); + fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B> { + TensorKeyPrepared { + keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(), } - self.keys - .iter_mut() - .zip(other.keys.iter()) - .for_each(|(a, b)| { - a.prepare(module, b, scratch); - }); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>> for GGLWETensorKey<D> +pub trait TensorKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> TensorKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> TensorKeyPreparedToRef<B> for TensorKeyPrepared<D, B> where - Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>, { - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWETensorKeyPrepared<Vec<u8>, B> { - let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc(module, self); - tsk_prepared.prepare(module, self, scratch); - tsk_prepared + fn to_ref(&self) -> TensorKeyPrepared<&[u8], B> { + TensorKeyPrepared { + keys: self.keys.iter().map(|c| c.to_ref()).collect(), + } } }
M poulpy-core/src/layouts/prepared/ggsw_ct.rs → poulpy-core/src/layouts/prepared/ggsw_ct.rs

@@ -1,25 +1,23 @@

use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare, VmpPrepareTmpBytes}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToRef, ZnxInfos}, - oep::VmpPMatAllocBytesImpl, + api::{VmpPMatAlloc, VmpPMatBytesOf, VmpPrepare, VmpPrepareTmpBytes}, + layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat, VmpPMatToMut, VmpPMatToRef, ZnxInfos}, }; use crate::layouts::{ - Base2K, BuildError, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - prepared::{Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGSW, GGSWInfos, GGSWToRef, GLWEInfos, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision, }; #[derive(PartialEq, Eq)] -pub struct GGSWCiphertextPrepared<D: Data, B: Backend> { +pub struct GGSWPrepared<D: Data, B: Backend> { pub(crate) data: VmpPMat<D, B>, pub(crate) k: TorusPrecision, pub(crate) base2k: Base2K, pub(crate) dsize: Dsize, } -impl<D: Data, B: Backend> LWEInfos for GGSWCiphertextPrepared<D, B> { - fn n(&self) -> Degree { - Degree(self.data.n() as u32) +impl<D: Data, B: Backend> LWEInfos for GGSWPrepared<D, B> { + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn base2k(&self) -> Base2K {

@@ -35,13 +33,13 @@ self.data.size()

} } -impl<D: Data, B: Backend> GLWEInfos for GGSWCiphertextPrepared<D, B> { +impl<D: Data, B: Backend> GLWEInfos for GGSWPrepared<D, B> { fn rank(&self) -> Rank { Rank(self.data.cols_out() as u32 - 1) } } -impl<D: Data, B: Backend> GGSWInfos for GGSWCiphertextPrepared<D, B> { +impl<D: Data, B: Backend> GGSWInfos for GGSWPrepared<D, B> { fn dsize(&self) -> Dsize { self.dsize }

@@ -51,131 +49,51 @@ Dnum(self.data.rows() as u32)

} } -pub struct GGSWCiphertextPreparedBuilder<D: Data, B: Backend> { - data: Option<VmpPMat<D, B>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, - dsize: Option<Dsize>, -} - -impl<D: Data, B: Backend> GGSWCiphertextPrepared<D, B> { - #[inline] - pub fn builder() -> GGSWCiphertextPreparedBuilder<D, B> { - GGSWCiphertextPreparedBuilder { - data: None, - base2k: None, - k: None, - dsize: None, - } - } -} - -impl<B: Backend> GGSWCiphertextPreparedBuilder<Vec<u8>, B> { - #[inline] - pub fn layout<A>(mut self, infos: &A) -> Self - where - A: GGSWInfos, - B: VmpPMatAllocBytesImpl<B>, - { +pub trait GGSWPreparedAlloc<B: Backend> +where + Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf, +{ + fn alloc_ggsw_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + dnum: Dnum, + dsize: Dsize, + rank: Rank, + ) -> GGSWPrepared<Vec<u8>, B> { + let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( - infos.size() as u32 > infos.dsize().0, - "invalid ggsw: ceil(k/base2k): {} <= dsize: {}", - infos.size(), - infos.dsize() + size as u32 > dsize.0, + "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}", + dsize.0 ); assert!( - infos.dnum().0 * infos.dsize().0 <= infos.size() as u32, - "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {}", - infos.dnum(), - infos.dsize(), - infos.size(), + dnum.0 * dsize.0 <= size as u32, + "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}", + dnum.0, + dsize.0, ); - self.data = Some(VmpPMat::alloc( - infos.n().into(), - infos.dnum().into(), - (infos.rank() + 1).into(), - (infos.rank() + 1).into(), - infos.size(), - )); - self.base2k = Some(infos.base2k()); - self.k = Some(infos.k()); - self.dsize = Some(infos.dsize()); - self - } -} - -impl<D: Data, B: Backend> GGSWCiphertextPreparedBuilder<D, B> { - #[inline] - pub fn data(mut self, data: VmpPMat<D, B>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self - } - - #[inline] - pub fn dsize(mut self, dsize: Dsize) -> Self { - self.dsize = Some(dsize); - self - } - - pub fn build(self) -> Result<GGSWCiphertextPrepared<D, B>, BuildError> { - let data: VmpPMat<D, B> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - let dsize: Dsize = self.dsize.ok_or(BuildError::MissingDigits)?; - - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if dsize == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GGSWCiphertextPrepared { - data, + GGSWPrepared { + data: self.vmp_pmat_alloc( + dnum.into(), + (rank + 1).into(), + (rank + 1).into(), + k.0.div_ceil(base2k.0) as usize, + ), + k, base2k, - k, dsize, - }) + } } -} -impl<B: Backend> GGSWCiphertextPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self + fn alloc_ggsw_prepared_from_infos<A>(&self, infos: &A) -> GGSWPrepared<Vec<u8>, B> where A: GGSWInfos, - Module<B>: VmpPMatAlloc<B>, { - Self::alloc_with( - module, + assert_eq!(self.ring_degree(), infos.n()); + self.alloc_ggsw_prepared( infos.base2k(), infos.k(), infos.dnum(),

@@ -184,10 +102,7 @@ infos.rank(),

) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self - where - Module<B>: VmpPMatAlloc<B>, - { + fn bytes_of_ggsw_prepared(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize { let size: usize = k.0.div_ceil(base2k.0) as usize; debug_assert!( size as u32 > dsize.0,

@@ -202,26 +117,15 @@ dnum.0,

dsize.0, ); - Self { - data: module.vmp_pmat_alloc( - dnum.into(), - (rank + 1).into(), - (rank + 1).into(), - k.0.div_ceil(base2k.0) as usize, - ), - k, - base2k, - dsize, - } + self.bytes_of_vmp_pmat(dnum.into(), (rank + 1).into(), (rank + 1).into(), size) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + fn bytes_of_ggsw_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGSWInfos, - Module<B>: VmpPMatAllocBytes, { - Self::alloc_bytes_with( - module, + assert_eq!(self.ring_degree(), infos.n()); + self.bytes_of_ggsw_prepared( infos.base2k(), infos.k(), infos.dnum(),

@@ -229,84 +133,128 @@ infos.dsize(),

infos.rank(), ) } +} - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize +impl<B: Backend> GGSWPreparedAlloc<B> for Module<B> where Self: GetRingDegree + VmpPMatAlloc<B> + VmpPMatBytesOf {} + +impl<B: Backend> GGSWPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where - Module<B>: VmpPMatAllocBytes, + A: GGSWInfos, + M: GGSWPreparedAlloc<B>, { - let size: usize = k.0.div_ceil(base2k.0) as usize; - debug_assert!( - size as u32 > dsize.0, - "invalid ggsw: ceil(k/base2k): {size} <= dsize: {}", - dsize.0 - ); + module.alloc_ggsw_prepared_from_infos(infos) + } - assert!( - dnum.0 * dsize.0 <= size as u32, - "invalid ggsw: dnum: {} * dsize:{} > ceil(k/base2k): {size}", - dnum.0, - dsize.0, - ); + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self + where + M: GGSWPreparedAlloc<B>, + { + module.alloc_ggsw_prepared(base2k, k, dnum, dsize, rank) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGSWInfos, + M: GGSWPreparedAlloc<B>, + { + module.bytes_of_ggsw_prepared_from_infos(infos) + } - module.vmp_pmat_alloc_bytes(dnum.into(), (rank + 1).into(), (rank + 1).into(), size) + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> usize + where + M: GGSWPreparedAlloc<B>, + { + module.bytes_of_ggsw_prepared(base2k, k, dnum, dsize, rank) } } -impl<D: DataRef, B: Backend> GGSWCiphertextPrepared<D, B> { +impl<D: DataRef, B: Backend> GGSWPrepared<D, B> { pub fn data(&self) -> &VmpPMat<D, B> { &self.data } } -impl<B: Backend, A: GGSWInfos> PrepareScratchSpace<B, A> for GGSWCiphertextPrepared<Vec<u8>, B> +pub trait GGSWPrepare<B: Backend> where - Module<B>: VmpPrepareTmpBytes, + Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - module.vmp_prepare_tmp_bytes( + fn ggsw_prepare_tmp_bytes<A>(&self, infos: &A) -> usize + where + A: GGSWInfos, + { + assert_eq!(self.ring_degree(), infos.n()); + self.vmp_prepare_tmp_bytes( infos.dnum().into(), (infos.rank() + 1).into(), (infos.rank() + 1).into(), infos.size(), ) } + fn ggsw_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: GGSWPreparedToMut<B>, + O: GGSWToRef, + { + let mut res: GGSWPrepared<&mut [u8], B> = res.to_mut(); + let other: GGSW<&[u8]> = other.to_ref(); + assert_eq!(res.n(), self.ring_degree()); + assert_eq!(other.n(), self.ring_degree()); + assert_eq!(res.k, other.k); + assert_eq!(res.base2k, other.base2k); + assert_eq!(res.dsize, other.dsize); + self.vmp_prepare(&mut res.data, &other.data, scratch); + } } -impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGSWCiphertext<DR>> for GGSWCiphertextPrepared<D, B> -where - Module<B>: VmpPrepare<B>, -{ - fn prepare(&mut self, module: &Module<B>, other: &GGSWCiphertext<DR>, scratch: &mut Scratch<B>) { - module.vmp_prepare(&mut self.data, &other.data, scratch); - self.k = other.k; - self.base2k = other.base2k; - self.dsize = other.dsize; +impl<B: Backend> GGSWPrepare<B> for Module<B> where Self: GetRingDegree + VmpPrepareTmpBytes + VmpPrepare<B> {} + +impl<B: Backend> GGSWPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) -> usize + where + A: GGSWInfos, + M: GGSWPrepare<B>, + { + module.ggsw_prepare_tmp_bytes(infos) } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GGSWCiphertextPrepared<Vec<u8>, B>> for GGSWCiphertext<D> -where - Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>, -{ - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGSWCiphertextPrepared<Vec<u8>, B> { - let mut ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = GGSWCiphertextPrepared::alloc(module, self); - ggsw_prepared.prepare(module, self, scratch); - ggsw_prepared +impl<D: DataMut, B: Backend> GGSWPrepared<D, B> { + pub fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: GGSWToRef, + M: GGSWPrepare<B>, + { + module.ggsw_prepare(self, other, scratch); } } -pub trait GGSWCiphertextPreparedToRef<B: Backend> { - fn to_ref(&self) -> GGSWCiphertextPrepared<&[u8], B>; +pub trait GGSWPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> GGSWPreparedToMut<B> for GGSWPrepared<D, B> { + fn to_mut(&mut self) -> GGSWPrepared<&mut [u8], B> { + GGSWPrepared { + base2k: self.base2k, + k: self.k, + dsize: self.dsize, + data: self.data.to_mut(), + } + } +} + +pub trait GGSWPreparedToRef<B: Backend> { + fn to_ref(&self) -> GGSWPrepared<&[u8], B>; } -impl<D: DataRef, B: Backend> GGSWCiphertextPreparedToRef<B> for GGSWCiphertextPrepared<D, B> { - fn to_ref(&self) -> GGSWCiphertextPrepared<&[u8], B> { - GGSWCiphertextPrepared::builder() - .base2k(self.base2k()) - .dsize(self.dsize()) - .k(self.k()) - .data(self.data.to_ref()) - .build() - .unwrap() +impl<D: DataRef, B: Backend> GGSWPreparedToRef<B> for GGSWPrepared<D, B> { + fn to_ref(&self) -> GGSWPrepared<&[u8], B> { + GGSWPrepared { + base2k: self.base2k, + k: self.k, + dsize: self.dsize, + data: self.data.to_ref(), + } } }
M poulpy-core/src/layouts/prepared/glwe_pk.rs → poulpy-core/src/layouts/prepared/glwe_pk.rs

@@ -1,14 +1,12 @@

use poulpy_hal::{ - api::{VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VecZnxDft, ZnxInfos}, - oep::VecZnxDftAllocBytesImpl, + api::{VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf}, + layouts::{Backend, Data, DataMut, DataRef, Module, VecZnxDft, VecZnxDftToMut, VecZnxDftToRef, ZnxInfos}, }; use crate::{ dist::Distribution, layouts::{ - Base2K, BuildError, Degree, GLWEInfos, GLWEPublicKey, LWEInfos, Rank, TorusPrecision, - prepared::{Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, GLWEInfos, GLWEPublicKey, GLWEPublicKeyToRef, GetDist, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision, }, };

@@ -20,6 +18,16 @@ pub(crate) k: TorusPrecision,

pub(crate) dist: Distribution, } +pub(crate) trait SetDist { + fn set_dist(&mut self, dist: Distribution); +} + +impl<D: Data, B: Backend> SetDist for GLWEPublicKeyPrepared<D, B> { + fn set_dist(&mut self, dist: Distribution) { + self.dist = dist + } +} + impl<D: Data, B: Backend> LWEInfos for GLWEPublicKeyPrepared<D, B> { fn base2k(&self) -> Base2K { self.base2k

@@ -33,8 +41,8 @@ fn size(&self) -> usize {

self.data.size() } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } }

@@ -44,164 +52,138 @@ Rank(self.data.cols() as u32 - 1)

} } -pub struct GLWEPublicKeyPreparedBuilder<D: Data, B: Backend> { - data: Option<VecZnxDft<D, B>>, - base2k: Option<Base2K>, - k: Option<TorusPrecision>, -} - -impl<D: Data, B: Backend> GLWEPublicKeyPrepared<D, B> { - #[inline] - pub fn builder() -> GLWEPublicKeyPreparedBuilder<D, B> { - GLWEPublicKeyPreparedBuilder { - data: None, - base2k: None, - k: None, +pub trait GLWEPublicKeyPreparedAlloc<B: Backend> +where + Self: GetRingDegree + VecZnxDftAlloc<B> + VecZnxDftBytesOf, +{ + fn alloc_glwe_public_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> GLWEPublicKeyPrepared<Vec<u8>, B> { + GLWEPublicKeyPrepared { + data: self.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize), + base2k, + k, + dist: Distribution::NONE, } } -} -impl<B: Backend> GLWEPublicKeyPreparedBuilder<Vec<u8>, B> { - #[inline] - pub fn layout<A>(mut self, layout: &A) -> Self + fn alloc_glwe_public_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEPublicKeyPrepared<Vec<u8>, B> where A: GLWEInfos, - B: VecZnxDftAllocBytesImpl<B>, { - self.data = Some(VecZnxDft::alloc( - layout.n().into(), - (layout.rank() + 1).into(), - layout.size(), - )); - self.base2k = Some(layout.base2k()); - self.k = Some(layout.k()); - self + self.alloc_glwe_public_key_prepared(infos.base2k(), infos.k(), infos.rank()) } -} -impl<D: Data, B: Backend> GLWEPublicKeyPreparedBuilder<D, B> { - #[inline] - pub fn data(mut self, data: VecZnxDft<D, B>) -> Self { - self.data = Some(data); - self - } - #[inline] - pub fn base2k(mut self, base2k: Base2K) -> Self { - self.base2k = Some(base2k); - self - } - #[inline] - pub fn k(mut self, k: TorusPrecision) -> Self { - self.k = Some(k); - self + fn bytes_of_glwe_public_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize { + self.bytes_of_vec_znx_dft((rank + 1).into(), k.0.div_ceil(base2k.0) as usize) } - pub fn build(self) -> Result<GLWEPublicKeyPrepared<D, B>, BuildError> { - let data: VecZnxDft<D, B> = self.data.ok_or(BuildError::MissingData)?; - let base2k: Base2K = self.base2k.ok_or(BuildError::MissingBase2K)?; - let k: TorusPrecision = self.k.ok_or(BuildError::MissingK)?; - - if base2k == 0_u32 { - return Err(BuildError::ZeroBase2K); - } - - if k == 0_u32 { - return Err(BuildError::ZeroTorusPrecision); - } - - if data.n() == 0 { - return Err(BuildError::ZeroDegree); - } - - if data.cols() == 0 { - return Err(BuildError::ZeroCols); - } - - if data.size() == 0 { - return Err(BuildError::ZeroLimbs); - } - - Ok(GLWEPublicKeyPrepared { - data, - base2k, - k, - dist: Distribution::NONE, - }) + fn bytes_of_glwe_public_key_prepared_from_infos<A>(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + self.bytes_of_glwe_public_key_prepared(infos.base2k(), infos.k(), infos.rank()) } } +impl<B: Backend> GLWEPublicKeyPreparedAlloc<B> for Module<B> where Self: VecZnxDftAlloc<B> + VecZnxDftBytesOf {} + impl<B: Backend> GLWEPublicKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GLWEInfos, - Module<B>: VecZnxDftAlloc<B>, + M: GLWEPublicKeyPreparedAlloc<B>, { - debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()"); - Self::alloc_with(module, infos.base2k(), infos.k(), infos.rank()) + module.alloc_glwe_public_key_prepared_from_infos(infos) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self where - Module<B>: VecZnxDftAlloc<B>, + M: GLWEPublicKeyPreparedAlloc<B>, { - Self { - data: module.vec_znx_dft_alloc((rank + 1).into(), k.0.div_ceil(base2k.0) as usize), - base2k, - k, - dist: Distribution::NONE, - } + module.alloc_glwe_public_key_prepared(base2k, k, rank) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GLWEInfos, - Module<B>: VecZnxDftAllocBytes, + M: GLWEPublicKeyPreparedAlloc<B>, { - debug_assert_eq!(module.n(), infos.n().0 as usize, "module.n() != infos.n()"); - Self::alloc_bytes_with(module, infos.base2k(), infos.k(), infos.rank()) + module.bytes_of_glwe_public_key_prepared_from_infos(infos) } - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank: Rank) -> usize where - Module<B>: VecZnxDftAllocBytes, + M: GLWEPublicKeyPreparedAlloc<B>, { - module.vec_znx_dft_alloc_bytes((rank + 1).into(), k.0.div_ceil(base2k.0) as usize) + module.bytes_of_glwe_public_key_prepared(base2k, k, rank) } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEPublicKeyPrepared<Vec<u8>, B>> for GLWEPublicKey<D> +pub trait GLWEPublicKeyPrepare<B: Backend> where - Module<B>: VecZnxDftAlloc<B> + VecZnxDftApply<B>, + Self: GetRingDegree + VecZnxDftApply<B>, { - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEPublicKeyPrepared<Vec<u8>, B> { - let mut pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = GLWEPublicKeyPrepared::alloc(module, self); - pk_prepared.prepare(module, self, scratch); - pk_prepared + fn prepare_glwe_public_key<R, O>(&self, res: &mut R, other: &O) + where + R: GLWEPublicKeyPreparedToMut<B> + SetDist, + O: GLWEPublicKeyToRef + GetDist, + { + { + let mut res: GLWEPublicKeyPrepared<&mut [u8], B> = res.to_mut(); + let other: GLWEPublicKey<&[u8]> = other.to_ref(); + + assert_eq!(res.n(), self.ring_degree()); + assert_eq!(other.n(), self.ring_degree()); + assert_eq!(res.size(), other.size()); + assert_eq!(res.k(), other.k()); + assert_eq!(res.base2k(), other.base2k()); + + for i in 0..(res.rank() + 1).into() { + self.vec_znx_dft_apply(1, 0, &mut res.data, i, &other.data, i); + } + } + + res.set_dist(other.get_dist()); } } -impl<B: Backend, A: GLWEInfos> PrepareScratchSpace<B, A> for GLWEPublicKeyPrepared<Vec<u8>, B> { - fn prepare_scratch_space(_module: &Module<B>, _infos: &A) -> usize { - 0 +impl<B: Backend> GLWEPublicKeyPrepare<B> for Module<B> where Self: GetRingDegree + VecZnxDftApply<B> {} + +impl<D: DataMut, B: Backend> GLWEPublicKeyPrepared<D, B> { + pub fn prepare<O, M>(&mut self, module: &M, other: &O) + where + O: GLWEPublicKeyToRef + GetDist, + M: GLWEPublicKeyPrepare<B>, + { + module.prepare_glwe_public_key(self, other); } } -impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEPublicKey<DR>> for GLWEPublicKeyPrepared<DM, B> -where - Module<B>: VecZnxDftApply<B>, -{ - fn prepare(&mut self, module: &Module<B>, other: &GLWEPublicKey<DR>, _scratch: &mut Scratch<B>) { - #[cfg(debug_assertions)] - { - assert_eq!(self.n(), other.n()); - assert_eq!(self.size(), other.size()); +pub trait GLWEPublicKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> GLWEPublicKeyPreparedToMut<B> for GLWEPublicKeyPrepared<D, B> { + fn to_mut(&mut self) -> GLWEPublicKeyPrepared<&mut [u8], B> { + GLWEPublicKeyPrepared { + dist: self.dist, + k: self.k, + base2k: self.base2k, + data: self.data.to_mut(), } + } +} - (0..(self.rank() + 1).into()).for_each(|i| { - module.vec_znx_dft_apply(1, 0, &mut self.data, i, &other.data, i); - }); - self.k = other.k(); - self.base2k = other.base2k(); - self.dist = other.dist; +pub trait GLWEPublicKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> GLWEPublicKeyPreparedToRef<B> for GLWEPublicKeyPrepared<D, B> { + fn to_ref(&self) -> GLWEPublicKeyPrepared<&[u8], B> { + GLWEPublicKeyPrepared { + data: self.data.to_ref(), + dist: self.dist, + k: self.k, + base2k: self.base2k, + } } }
M poulpy-core/src/layouts/prepared/glwe_sk.rs → poulpy-core/src/layouts/prepared/glwe_sk.rs

@@ -1,13 +1,13 @@

use poulpy_hal::{ - api::{SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, SvpPPol, ZnxInfos}, + api::{SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare}, + layouts::{Backend, Data, DataMut, DataRef, Module, SvpPPol, SvpPPolToMut, SvpPPolToRef, ZnxInfos}, }; use crate::{ dist::Distribution, layouts::{ - Base2K, Degree, GLWEInfos, GLWESecret, LWEInfos, Rank, TorusPrecision, - prepared::{Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, GLWEInfos, GLWESecret, GLWESecretToRef, GetDist, GetRingDegree, LWEInfos, Rank, RingDegree, TorusPrecision, + prepared::SetDist, }, };

@@ -16,6 +16,12 @@ pub(crate) data: SvpPPol<D, B>,

pub(crate) dist: Distribution, } +impl<D: DataRef, B: Backend> SetDist for GLWESecretPrepared<D, B> { + fn set_dist(&mut self, dist: Distribution) { + self.dist = dist + } +} + impl<D: Data, B: Backend> LWEInfos for GLWESecretPrepared<D, B> { fn base2k(&self) -> Base2K { Base2K(0)

@@ -25,8 +31,8 @@ fn k(&self) -> TorusPrecision {

TorusPrecision(0) } - fn n(&self) -> Degree { - Degree(self.data.n() as u32) + fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } fn size(&self) -> usize {

@@ -38,46 +44,74 @@ fn rank(&self) -> Rank {

Rank(self.data.cols() as u32) } } + +pub trait GLWESecretPreparedAlloc<B: Backend> +where + Self: GetRingDegree + SvpPPolBytesOf + SvpPPolAlloc<B>, +{ + fn alloc_glwe_secret_prepared(&self, rank: Rank) -> GLWESecretPrepared<Vec<u8>, B> { + GLWESecretPrepared { + data: self.svp_ppol_alloc(rank.into()), + dist: Distribution::NONE, + } + } + fn alloc_glwe_secret_prepared_from_infos<A>(&self, infos: &A) -> GLWESecretPrepared<Vec<u8>, B> + where + A: GLWEInfos, + { + assert_eq!(self.ring_degree(), infos.n()); + self.alloc_glwe_secret_prepared(infos.rank()) + } + + fn bytes_of_glwe_secret(&self, rank: Rank) -> usize { + self.bytes_of_svp_ppol(rank.into()) + } + fn bytes_of_glwe_secret_from_infos<A>(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + assert_eq!(self.ring_degree(), infos.n()); + self.bytes_of_glwe_secret(infos.rank()) + } +} + +impl<B: Backend> GLWESecretPreparedAlloc<B> for Module<B> where Self: GetRingDegree + SvpPPolBytesOf + SvpPPolAlloc<B> {} + impl<B: Backend> GLWESecretPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where A: GLWEInfos, - Module<B>: SvpPPolAlloc<B>, + M: GLWESecretPreparedAlloc<B>, { - assert_eq!(module.n() as u32, infos.n()); - Self::alloc_with(module, infos.rank()) + module.alloc_glwe_secret_prepared_from_infos(infos) } - pub fn alloc_with(module: &Module<B>, rank: Rank) -> Self + pub fn alloc<M>(module: &M, rank: Rank) -> Self where - Module<B>: SvpPPolAlloc<B>, + M: GLWESecretPreparedAlloc<B>, { - Self { - data: module.svp_ppol_alloc(rank.into()), - dist: Distribution::NONE, - } + module.alloc_glwe_secret_prepared(rank) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize where A: GLWEInfos, - Module<B>: SvpPPolAllocBytes, + M: GLWESecretPreparedAlloc<B>, { - assert_eq!(module.n() as u32, infos.n()); - Self::alloc_bytes_with(module, infos.rank()) + module.bytes_of_glwe_secret_from_infos(infos) } - pub fn alloc_bytes_with(module: &Module<B>, rank: Rank) -> usize + pub fn bytes_of<M>(module: &M, rank: Rank) -> usize where - Module<B>: SvpPPolAllocBytes, + M: GLWESecretPreparedAlloc<B>, { - module.svp_ppol_alloc_bytes(rank.into()) + module.bytes_of_glwe_secret(rank) } } impl<D: Data, B: Backend> GLWESecretPrepared<D, B> { - pub fn n(&self) -> Degree { - Degree(self.data.n() as u32) + pub fn n(&self) -> RingDegree { + RingDegree(self.data.n() as u32) } pub fn rank(&self) -> Rank {

@@ -85,31 +119,62 @@ Rank(self.data.cols() as u32)

} } -impl<B: Backend, A: GLWEInfos> PrepareScratchSpace<B, A> for GLWESecretPrepared<Vec<u8>, B> { - fn prepare_scratch_space(_module: &Module<B>, _infos: &A) -> usize { - 0 +pub trait GLWESecretPrepare<B: Backend> +where + Self: SvpPrepare<B>, +{ + fn prepare_glwe_secret<R, O>(&self, res: &mut R, other: &O) + where + R: GLWESecretPreparedToMut<B> + SetDist, + O: GLWESecretToRef + GetDist, + { + { + let mut res: GLWESecretPrepared<&mut [u8], _> = res.to_mut(); + let other: GLWESecret<&[u8]> = other.to_ref(); + + for i in 0..res.rank().into() { + self.svp_prepare(&mut res.data, i, &other.data, i); + } + } + + res.set_dist(other.get_dist()); + } +} + +impl<B: Backend> GLWESecretPrepare<B> for Module<B> where Self: SvpPrepare<B> {} + +impl<D: DataMut, B: Backend> GLWESecretPrepared<D, B> { + pub fn prepare<M, O>(&mut self, module: &M, other: &O) + where + M: GLWESecretPrepare<B>, + O: GLWESecretToRef + GetDist, + { + module.prepare_glwe_secret(self, other); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWESecretPrepared<Vec<u8>, B>> for GLWESecret<D> -where - Module<B>: SvpPrepare<B> + SvpPPolAlloc<B>, -{ - fn prepare_alloc(&self, module: &Module<B>, _scratch: &mut Scratch<B>) -> GLWESecretPrepared<Vec<u8>, B> { - let mut sk_dft: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, self); - sk_dft.prepare(module, self, _scratch); - sk_dft +pub trait GLWESecretPreparedToRef<B: Backend> { + fn to_ref(&self) -> GLWESecretPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> GLWESecretPreparedToRef<B> for GLWESecretPrepared<D, B> { + fn to_ref(&self) -> GLWESecretPrepared<&[u8], B> { + GLWESecretPrepared { + data: self.data.to_ref(), + dist: self.dist, + } } } -impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWESecret<DR>> for GLWESecretPrepared<DM, B> -where - Module<B>: SvpPrepare<B>, -{ - fn prepare(&mut self, module: &Module<B>, other: &GLWESecret<DR>, _scratch: &mut Scratch<B>) { - (0..self.rank().into()).for_each(|i| { - module.svp_prepare(&mut self.data, i, &other.data, i); - }); - self.dist = other.dist +pub trait GLWESecretPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> GLWESecretPreparedToMut<B> for GLWESecretPrepared<D, B> { + fn to_mut(&mut self) -> GLWESecretPrepared<&mut [u8], B> { + GLWESecretPrepared { + dist: self.dist, + data: self.data.to_mut(), + } } }
M poulpy-core/src/layouts/prepared/glwe_to_lwe_ksk.rs → poulpy-core/src/layouts/prepared/glwe_to_lwe_ksk.rs

@@ -1,15 +1,15 @@

-use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWEKey, LWEInfos, Rank, TorusPrecision, - prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWEToLWESwitchingKeyToRef, LWEInfos, Rank, RingDegree, TorusPrecision, + prepared::{ + GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut, + GLWESwitchingKeyPreparedToRef, + }, }; #[derive(PartialEq, Eq)] -pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>); +pub struct GLWEToLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>); impl<D: Data, B: Backend> LWEInfos for GLWEToLWESwitchingKeyPrepared<D, B> { fn base2k(&self) -> Base2K {

@@ -20,7 +20,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -53,11 +53,22 @@ self.0.dnum()

} } -impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self +pub trait GLWEToLWESwitchingKeyPreparedAlloc<B: Backend> +where + Self: GLWESwitchingKeyPreparedAlloc<B>, +{ + fn alloc_glwe_to_lwe_switching_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_in: Rank, + dnum: Dnum, + ) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { + GLWEToLWESwitchingKeyPrepared(self.alloc_glwe_switching_key_prepared(base2k, k, rank_in, Rank(1), dnum, Dsize(1))) + } + fn alloc_glwe_to_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { debug_assert_eq!( infos.rank_out().0,

@@ -69,28 +80,16 @@ infos.dsize().0,

1, "dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared" ); - Self(GGLWESwitchingKeyPrepared::alloc(module, infos)) + self.alloc_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum()) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self - where - Module<B>: VmpPMatAlloc<B>, - { - Self(GGLWESwitchingKeyPrepared::alloc_with( - module, - base2k, - k, - rank_in, - Rank(1), - dnum, - Dsize(1), - )) + fn bytes_of_glwe_to_lwe_switching_key_prepared(&self, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key_prepared(base2k, k, rank_in, Rank(1), dnum, Dsize(1)) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + fn bytes_of_glwe_to_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, { debug_assert_eq!( infos.rank_out().0,

@@ -102,42 +101,108 @@ infos.dsize().0,

1, "dsize > 1 is not supported for GLWEToLWESwitchingKeyPrepared" ); - GGLWESwitchingKeyPrepared::alloc_bytes(module, infos) + self.bytes_of_glwe_to_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_in(), infos.dnum()) + } +} + +impl<B: Backend> GLWEToLWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GLWESwitchingKeyPreparedAlloc<B> {} + +impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyPreparedAlloc<B>, + { + module.alloc_glwe_to_lwe_switching_key_prepared_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> Self + where + M: GLWEToLWESwitchingKeyPreparedAlloc<B>, + { + module.alloc_glwe_to_lwe_switching_key_prepared(base2k, k, rank_in, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyPreparedAlloc<B>, + { + module.bytes_of_glwe_to_lwe_switching_key_prepared_from_infos(infos) } - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_in: Rank, dnum: Dnum) -> usize where - Module<B>: VmpPMatAllocBytes, + M: GLWEToLWESwitchingKeyPreparedAlloc<B>, { - GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, rank_in, Rank(1), dnum, Dsize(1)) + module.bytes_of_glwe_to_lwe_switching_key_prepared(base2k, k, rank_in, dnum) } } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> +pub trait GLWEToLWESwitchingKeyPrepare<B: Backend> where - GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>, + Self: GLWESwitchingKeyPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos) + fn prepare_glwe_to_lwe_switching_key_tmp_bytes<A>(&self, infos: &A) + where + A: GGLWEInfos, + { + self.prepare_glwe_switching_key_tmp_bytes(infos); + } + + fn prepare_glwe_to_lwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: GLWEToLWESwitchingKeyPreparedToMut<B>, + O: GLWEToLWESwitchingKeyToRef, + { + self.prepare_glwe_switching(&mut res.to_mut().0, &other.to_ref().0, scratch); + } +} + +impl<B: Backend> GLWEToLWESwitchingKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {} + +impl<B: Backend> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) + where + A: GGLWEInfos, + M: GLWEToLWESwitchingKeyPrepare<B>, + { + module.prepare_glwe_to_lwe_switching_key_tmp_bytes(infos); + } +} + +impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyPrepared<D, B> { + fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: GLWEToLWESwitchingKeyToRef, + M: GLWEToLWESwitchingKeyPrepare<B>, + { + module.prepare_glwe_to_lwe_switching_key(self, other, scratch); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, GLWEToLWESwitchingKeyPrepared<Vec<u8>, B>> for GLWEToLWEKey<D> +pub trait GLWEToLWESwitchingKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> GLWEToLWESwitchingKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> GLWEToLWESwitchingKeyPreparedToRef<B> for GLWEToLWESwitchingKeyPrepared<D, B> where - Module<B>: VmpPrepare<B> + VmpPMatAlloc<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>, { - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> { - let mut ksk_prepared: GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> = GLWEToLWESwitchingKeyPrepared::alloc(module, self); - ksk_prepared.prepare(module, self, scratch); - ksk_prepared + fn to_ref(&self) -> GLWEToLWESwitchingKeyPrepared<&[u8], B> { + GLWEToLWESwitchingKeyPrepared(self.0.to_ref()) } } -impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, GLWEToLWEKey<DR>> for GLWEToLWESwitchingKeyPrepared<DM, B> +pub trait GLWEToLWESwitchingKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> GLWEToLWESwitchingKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> GLWEToLWESwitchingKeyPreparedToMut<B> for GLWEToLWESwitchingKeyPrepared<D, B> where - Module<B>: VmpPrepare<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>, { - fn prepare(&mut self, module: &Module<B>, other: &GLWEToLWEKey<DR>, scratch: &mut Scratch<B>) { - self.0.prepare(module, &other.0, scratch); + fn to_mut(&mut self) -> GLWEToLWESwitchingKeyPrepared<&mut [u8], B> { + GLWEToLWESwitchingKeyPrepared(self.0.to_mut()) } }
M poulpy-core/src/layouts/prepared/lwe_ksk.rs → poulpy-core/src/layouts/prepared/lwe_ksk.rs

@@ -1,15 +1,15 @@

-use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKey, Rank, TorusPrecision, - prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWESwitchingKeyToRef, Rank, RingDegree, TorusPrecision, + prepared::{ + GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut, + GLWESwitchingKeyPreparedToRef, + }, }; #[derive(PartialEq, Eq)] -pub struct LWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>); +pub struct LWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>); impl<D: Data, B: Backend> LWEInfos for LWESwitchingKeyPrepared<D, B> { fn base2k(&self) -> Base2K {

@@ -20,7 +20,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -52,11 +52,22 @@ self.0.dnum()

} } -impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self +pub trait LWESwitchingKeyPreparedAlloc<B: Backend> +where + Self: GLWESwitchingKeyPreparedAlloc<B>, +{ + fn alloc_lwe_switching_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + dnum: Dnum, + ) -> LWESwitchingKeyPrepared<Vec<u8>, B> { + LWESwitchingKeyPrepared(self.alloc_glwe_switching_key_prepared(base2k, k, Rank(1), Rank(1), dnum, Dsize(1))) + } + + fn alloc_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> LWESwitchingKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { debug_assert_eq!( infos.dsize().0,

@@ -73,28 +84,16 @@ infos.rank_out().0,

1, "rank_out > 1 is not supported for LWESwitchingKey" ); - Self(GGLWESwitchingKeyPrepared::alloc(module, infos)) + self.alloc_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.dnum()) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self - where - Module<B>: VmpPMatAlloc<B>, - { - Self(GGLWESwitchingKeyPrepared::alloc_with( - module, - base2k, - k, - Rank(1), - Rank(1), - dnum, - Dsize(1), - )) + fn bytes_of_lwe_switching_key_prepared(&self, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize { + self.bytes_of_glwe_switching_key_prepared(base2k, k, Rank(1), Rank(1), dnum, Dsize(1)) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + fn bytes_of_lwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, { debug_assert_eq!( infos.dsize().0,

@@ -111,42 +110,107 @@ infos.rank_out().0,

1, "rank_out > 1 is not supported for LWESwitchingKey" ); - GGLWESwitchingKeyPrepared::alloc_bytes(module, infos) + self.bytes_of_lwe_switching_key_prepared(infos.base2k(), infos.k(), infos.dnum()) } +} - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize +impl<B: Backend> LWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GLWESwitchingKeyPreparedAlloc<B> {} + +impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self where - Module<B>: VmpPMatAllocBytes, + A: GGLWEInfos, + M: LWESwitchingKeyPreparedAlloc<B>, + { + module.alloc_lwe_switching_key_prepared_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> Self + where + M: LWESwitchingKeyPreparedAlloc<B>, { - GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), Rank(1), dnum, Dsize(1)) + module.alloc_lwe_switching_key_prepared(base2k, k, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: LWESwitchingKeyPreparedAlloc<B>, + { + module.bytes_of_lwe_switching_key_prepared_from_infos(infos) + } + + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, dnum: Dnum) -> usize + where + M: LWESwitchingKeyPreparedAlloc<B>, + { + module.bytes_of_lwe_switching_key_prepared(base2k, k, dnum) } } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for LWESwitchingKeyPrepared<Vec<u8>, B> +pub trait LWESwitchingKeyPrepare<B: Backend> where - GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>, + Self: GLWESwitchingKeyPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos) + fn prepare_lwe_switching_key_tmp_bytes<A>(&self, infos: &A) + where + A: GGLWEInfos, + { + self.prepare_glwe_switching_key_tmp_bytes(infos); + } + fn prepare_lwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: LWESwitchingKeyPreparedToMut<B>, + O: LWESwitchingKeyToRef, + { + self.prepare_glwe_switching(&mut res.to_mut().0, &other.to_ref().0, scratch); + } +} + +impl<B: Backend> LWESwitchingKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {} + +impl<B: Backend> LWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) + where + A: GGLWEInfos, + M: LWESwitchingKeyPrepare<B>, + { + module.prepare_lwe_switching_key_tmp_bytes(infos); + } +} + +impl<D: DataMut, B: Backend> LWESwitchingKeyPrepared<D, B> { + fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: LWESwitchingKeyToRef, + M: LWESwitchingKeyPrepare<B>, + { + module.prepare_lwe_switching_key(self, other, scratch); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, LWESwitchingKeyPrepared<Vec<u8>, B>> for LWESwitchingKey<D> +pub trait LWESwitchingKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> LWESwitchingKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> LWESwitchingKeyPreparedToRef<B> for LWESwitchingKeyPrepared<D, B> where - Module<B>: VmpPrepare<B> + VmpPMatAlloc<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>, { - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> LWESwitchingKeyPrepared<Vec<u8>, B> { - let mut ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = LWESwitchingKeyPrepared::alloc(module, self); - ksk_prepared.prepare(module, self, scratch); - ksk_prepared + fn to_ref(&self) -> LWESwitchingKeyPrepared<&[u8], B> { + LWESwitchingKeyPrepared(self.0.to_ref()) } } -impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWESwitchingKey<DR>> for LWESwitchingKeyPrepared<DM, B> +pub trait LWESwitchingKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> LWESwitchingKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> LWESwitchingKeyPreparedToMut<B> for LWESwitchingKeyPrepared<D, B> where - Module<B>: VmpPrepare<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>, { - fn prepare(&mut self, module: &Module<B>, other: &LWESwitchingKey<DR>, scratch: &mut Scratch<B>) { - self.0.prepare(module, &other.0, scratch); + fn to_mut(&mut self) -> LWESwitchingKeyPrepared<&mut [u8], B> { + LWESwitchingKeyPrepared(self.0.to_mut()) } }
M poulpy-core/src/layouts/prepared/lwe_to_glwe_ksk.rs → poulpy-core/src/layouts/prepared/lwe_to_glwe_ksk.rs

@@ -1,16 +1,16 @@

-use poulpy_hal::{ - api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, - layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, -}; +use poulpy_hal::layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKey, Rank, TorusPrecision, - prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace}, + Base2K, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, LWEToGLWESwitchingKeyToRef, Rank, RingDegree, TorusPrecision, + prepared::{ + GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedAlloc, GLWESwitchingKeyPreparedToMut, + GLWESwitchingKeyPreparedToRef, + }, }; -/// A special [GLWESwitchingKey] required to for the conversion from [LWECiphertext] to [GLWECiphertext]. +/// A special [GLWESwitchingKey] required to for the conversion from [LWE] to [GLWE]. #[derive(PartialEq, Eq)] -pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GGLWESwitchingKeyPrepared<D, B>); +pub struct LWEToGLWESwitchingKeyPrepared<D: Data, B: Backend>(pub(crate) GLWESwitchingKeyPrepared<D, B>); impl<D: Data, B: Backend> LWEInfos for LWEToGLWESwitchingKeyPrepared<D, B> { fn base2k(&self) -> Base2K {

@@ -21,7 +21,7 @@ fn k(&self) -> TorusPrecision {

self.0.k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.0.n() }

@@ -54,11 +54,22 @@ self.0.dnum()

} } -impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { - pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self +pub trait LWEToGLWESwitchingKeyPreparedAlloc<B: Backend> +where + Self: GLWESwitchingKeyPreparedAlloc<B>, +{ + fn alloc_lwe_to_glwe_switching_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_out: Rank, + dnum: Dnum, + ) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { + LWEToGLWESwitchingKeyPrepared(self.alloc_glwe_switching_key_prepared(base2k, k, Rank(1), rank_out, dnum, Dsize(1))) + } + fn alloc_lwe_to_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> where A: GGLWEInfos, - Module<B>: VmpPMatAlloc<B>, { debug_assert_eq!( infos.rank_in().0,

@@ -70,28 +81,22 @@ infos.dsize().0,

1, "dsize > 1 is not supported for LWEToGLWESwitchingKey" ); - Self(GGLWESwitchingKeyPrepared::alloc(module, infos)) + self.alloc_lwe_to_glwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum()) } - pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self - where - Module<B>: VmpPMatAlloc<B>, - { - Self(GGLWESwitchingKeyPrepared::alloc_with( - module, - base2k, - k, - Rank(1), - rank_out, - dnum, - Dsize(1), - )) + fn bytes_of_lwe_to_glwe_switching_key_prepared( + &self, + base2k: Base2K, + k: TorusPrecision, + rank_out: Rank, + dnum: Dnum, + ) -> usize { + self.bytes_of_glwe_switching_key_prepared(base2k, k, Rank(1), rank_out, dnum, Dsize(1)) } - pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize + fn bytes_of_lwe_to_glwe_switching_key_prepared_from_infos<A>(&self, infos: &A) -> usize where A: GGLWEInfos, - Module<B>: VmpPMatAllocBytes, { debug_assert_eq!( infos.rank_in().0,

@@ -103,42 +108,108 @@ infos.dsize().0,

1, "dsize > 1 is not supported for LWEToGLWESwitchingKey" ); - GGLWESwitchingKeyPrepared::alloc_bytes(module, infos) + self.bytes_of_lwe_to_glwe_switching_key_prepared(infos.base2k(), infos.k(), infos.rank_out(), infos.dnum()) + } +} + +impl<B: Backend> LWEToGLWESwitchingKeyPreparedAlloc<B> for Module<B> where Self: GLWESwitchingKeyPreparedAlloc<B> {} + +impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn alloc_from_infos<A, M>(module: &M, infos: &A) -> Self + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyPreparedAlloc<B>, + { + module.alloc_lwe_to_glwe_switching_key_prepared_from_infos(infos) + } + + pub fn alloc<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> Self + where + M: LWEToGLWESwitchingKeyPreparedAlloc<B>, + { + module.alloc_lwe_to_glwe_switching_key_prepared(base2k, k, rank_out, dnum) + } + + pub fn bytes_of_from_infos<A, M>(module: &M, infos: &A) -> usize + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyPreparedAlloc<B>, + { + module.bytes_of_lwe_to_glwe_switching_key_prepared_from_infos(infos) } - pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, rank_out: Rank) -> usize + pub fn bytes_of<M>(module: &M, base2k: Base2K, k: TorusPrecision, rank_out: Rank, dnum: Dnum) -> usize where - Module<B>: VmpPMatAllocBytes, + M: LWEToGLWESwitchingKeyPreparedAlloc<B>, { - GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank_out, dnum, Dsize(1)) + module.bytes_of_lwe_to_glwe_switching_key_prepared(base2k, k, rank_out, dnum) } } -impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> +pub trait LWEToGLWESwitchingKeyPrepare<B: Backend> where - GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>, + Self: GLWESwitchingKeyPrepare<B>, { - fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize { - GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos) + fn prepare_lwe_to_glwe_switching_key_tmp_bytes<A>(&self, infos: &A) + where + A: GGLWEInfos, + { + self.prepare_glwe_switching_key_tmp_bytes(infos); + } + + fn prepare_lwe_to_glwe_switching_key<R, O>(&self, res: &mut R, other: &O, scratch: &mut Scratch<B>) + where + R: LWEToGLWESwitchingKeyPreparedToMut<B>, + O: LWEToGLWESwitchingKeyToRef, + { + self.prepare_glwe_switching(&mut res.to_mut().0, &other.to_ref().0, scratch); + } +} + +impl<B: Backend> LWEToGLWESwitchingKeyPrepare<B> for Module<B> where Self: GLWESwitchingKeyPrepare<B> {} + +impl<B: Backend> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { + pub fn prepare_tmp_bytes<A, M>(&self, module: &M, infos: &A) + where + A: GGLWEInfos, + M: LWEToGLWESwitchingKeyPrepare<B>, + { + module.prepare_lwe_to_glwe_switching_key_tmp_bytes(infos); } } -impl<D: DataRef, B: Backend> PrepareAlloc<B, LWEToGLWESwitchingKeyPrepared<Vec<u8>, B>> for LWEToGLWESwitchingKey<D> +impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyPrepared<D, B> { + fn prepare<O, M>(&mut self, module: &M, other: &O, scratch: &mut Scratch<B>) + where + O: LWEToGLWESwitchingKeyToRef, + M: LWEToGLWESwitchingKeyPrepare<B>, + { + module.prepare_lwe_to_glwe_switching_key(self, other, scratch); + } +} + +pub trait LWEToGLWESwitchingKeyPreparedToRef<B: Backend> { + fn to_ref(&self) -> LWEToGLWESwitchingKeyPrepared<&[u8], B>; +} + +impl<D: DataRef, B: Backend> LWEToGLWESwitchingKeyPreparedToRef<B> for LWEToGLWESwitchingKeyPrepared<D, B> where - Module<B>: VmpPrepare<B> + VmpPMatAlloc<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>, { - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> { - let mut ksk_prepared: LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> = LWEToGLWESwitchingKeyPrepared::alloc(module, self); - ksk_prepared.prepare(module, self, scratch); - ksk_prepared + fn to_ref(&self) -> LWEToGLWESwitchingKeyPrepared<&[u8], B> { + LWEToGLWESwitchingKeyPrepared(self.0.to_ref()) } } -impl<DM: DataMut, DR: DataRef, B: Backend> Prepare<B, LWEToGLWESwitchingKey<DR>> for LWEToGLWESwitchingKeyPrepared<DM, B> +pub trait LWEToGLWESwitchingKeyPreparedToMut<B: Backend> { + fn to_mut(&mut self) -> LWEToGLWESwitchingKeyPrepared<&mut [u8], B>; +} + +impl<D: DataMut, B: Backend> LWEToGLWESwitchingKeyPreparedToMut<B> for LWEToGLWESwitchingKeyPrepared<D, B> where - Module<B>: VmpPrepare<B>, + GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>, { - fn prepare(&mut self, module: &Module<B>, other: &LWEToGLWESwitchingKey<DR>, scratch: &mut Scratch<B>) { - self.0.prepare(module, &other.0, scratch); + fn to_mut(&mut self) -> LWEToGLWESwitchingKeyPrepared<&mut [u8], B> { + LWEToGLWESwitchingKeyPrepared(self.0.to_mut()) } }
M poulpy-core/src/layouts/prepared/mod.rs → poulpy-core/src/layouts/prepared/mod.rs

@@ -19,16 +19,3 @@ pub use glwe_sk::*;

pub use glwe_to_lwe_ksk::*; pub use lwe_ksk::*; pub use lwe_to_glwe_ksk::*; -use poulpy_hal::layouts::{Backend, Module, Scratch}; - -pub trait PrepareScratchSpace<B: Backend, T> { - fn prepare_scratch_space(module: &Module<B>, infos: &T) -> usize; -} - -pub trait PrepareAlloc<B: Backend, T> { - fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> T; -} - -pub trait Prepare<B: Backend, T> { - fn prepare(&mut self, module: &Module<B>, other: &T, scratch: &mut Scratch<B>); -}
M poulpy-core/src/lib.rs → poulpy-core/src/lib.rs

@@ -14,6 +14,7 @@ mod utils;

pub use operations::*; pub mod layouts; +pub use conversion::*; pub use dist::*; pub use external_product::*; pub use glwe_packing::*;

@@ -22,4 +23,4 @@ pub use encryption::SIGMA;

pub use scratch::*; -pub mod tests; +// pub mod tests;
M poulpy-core/src/noise/gglwe_ct.rs → poulpy-core/src/noise/gglwe_ct.rs

@@ -1,16 +1,16 @@

use poulpy_hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, - VecZnxNormalizeTmpBytes, VecZnxSubScalarInplace, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, + VecZnxSubScalarInplace, }, layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned, ZnxZero}, - oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, + oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::layouts::{GGLWECiphertext, GGLWEInfos, GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; +use crate::layouts::{GGLWE, GGLWEInfos, GLWE, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; -impl<D: DataRef> GGLWECiphertext<D> { +impl<D: DataRef> GGLWE<D> { pub fn assert_noise<B, DataSk, DataWant>( &self, module: &Module<B>,

@@ -20,8 +20,8 @@ max_noise: f64,

) where DataSk: DataRef, DataWant: DataRef, - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -30,13 +30,13 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxNormalizeTmpBytes + VecZnxSubScalarInplace, - B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let dsize: usize = self.dsize().into(); let base2k: usize = self.base2k().into(); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self)); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self); + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self)); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, self); (0..self.rank_in().into()).for_each(|col_i| { (0..self.dnum().into()).for_each(|row_i| {
M poulpy-core/src/noise/ggsw_ct.rs → poulpy-core/src/noise/ggsw_ct.rs

@@ -1,19 +1,17 @@

use poulpy_hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxAddScalarInplace, VecZnxBigAddInplace, - VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, - VecZnxNormalizeTmpBytes, VecZnxSubInplace, + VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalizeTmpBytes, + VecZnxSubInplace, }, layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned, VecZnxBig, VecZnxDft, ZnxZero}, - oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, + oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::layouts::{ - GGSWCiphertext, GGSWInfos, GLWECiphertext, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared, -}; +use crate::layouts::{GGSW, GGSWInfos, GLWE, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; -impl<D: DataRef> GGSWCiphertext<D> { +impl<D: DataRef> GGSW<D> { pub fn assert_noise<B, DataSk, DataScalar, F>( &self, module: &Module<B>,

@@ -23,8 +21,8 @@ max_noise: F,

) where DataSk: DataRef, DataScalar: DataRef, - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -38,19 +36,19 @@ + VecZnxBigNormalizeTmpBytes

+ VecZnxIdftApplyTmpA<B> + VecZnxAddScalarInplace + VecZnxSubInplace, - B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, F: Fn(usize) -> f64, { let base2k: usize = self.base2k().into(); let dsize: usize = self.dsize().into(); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, self); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, self); let mut pt_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(1, self.size()); let mut pt_big: VecZnxBig<Vec<u8>, B> = module.vec_znx_big_alloc(1, self.size()); let mut scratch: ScratchOwned<B> = - ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self) | module.vec_znx_normalize_tmp_bytes()); + ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self) | module.vec_znx_normalize_tmp_bytes()); (0..(self.rank() + 1).into()).for_each(|col_j| { (0..self.dnum().into()).for_each(|row_i| {

@@ -87,7 +85,7 @@ });

} } -impl<D: DataRef> GGSWCiphertext<D> { +impl<D: DataRef> GGSW<D> { pub fn print_noise<B, DataSk, DataScalar>( &self, module: &Module<B>,

@@ -96,8 +94,8 @@ pt_want: &ScalarZnx<DataScalar>,

) where DataSk: DataRef, DataScalar: DataRef, - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -111,18 +109,18 @@ + VecZnxBigNormalizeTmpBytes

+ VecZnxIdftApplyTmpA<B> + VecZnxAddScalarInplace + VecZnxSubInplace, - B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { let base2k: usize = self.base2k().into(); let dsize: usize = self.dsize().into(); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, self); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, self); let mut pt_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(1, self.size()); let mut pt_big: VecZnxBig<Vec<u8>, B> = module.vec_znx_big_alloc(1, self.size()); let mut scratch: ScratchOwned<B> = - ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self) | module.vec_znx_normalize_tmp_bytes()); + ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self) | module.vec_znx_normalize_tmp_bytes()); (0..(self.rank() + 1).into()).for_each(|col_j| { (0..self.dnum().into()).for_each(|row_i| {
M poulpy-core/src/noise/glwe_ct.rs → poulpy-core/src/noise/glwe_ct.rs

@@ -1,16 +1,16 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, - VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxIdftApplyConsume, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSubInplace, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeInplace, + VecZnxNormalizeTmpBytes, VecZnxSubInplace, }, layouts::{Backend, DataRef, Module, Scratch, ScratchOwned}, - oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl}, + oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::layouts::{GLWECiphertext, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; +use crate::layouts::{GLWE, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; -impl<D: DataRef> GLWECiphertext<D> { +impl<D: DataRef> GLWE<D> { pub fn noise<B, DataSk, DataPt>( &self, module: &Module<B>,

@@ -30,9 +30,9 @@ + VecZnxIdftApplyConsume<B>

+ VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxBigNormalize<B>, - Scratch<B>: TakeVecZnxDft<B> + TakeVecZnxBig<B>, + Scratch<B>:, { - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(self); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, self); self.decrypt(module, &mut pt_have, sk_prepared, scratch); module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0); module.vec_znx_normalize_inplace(self.base2k().into(), &mut pt_have.data, 0, scratch);

@@ -48,8 +48,8 @@ max_noise: f64,

) where DataSk: DataRef, DataPt: DataRef, - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -59,9 +59,9 @@ + VecZnxBigNormalize<B>

+ VecZnxNormalizeTmpBytes + VecZnxSubInplace + VecZnxNormalizeInplace<B>, - B: Backend + TakeVecZnxDftImpl<B> + TakeVecZnxBigImpl<B> + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, + B: Backend + ScratchOwnedAllocImpl<B> + ScratchOwnedBorrowImpl<B>, { - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWECiphertext::decrypt_scratch_space(module, self)); + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self)); let noise_have: f64 = self.noise(module, sk_prepared, pt_want, scratch.borrow()); assert!(noise_have <= max_noise, "{noise_have} {max_noise}"); }
M poulpy-core/src/operations/glwe.rs → poulpy-core/src/operations/glwe.rs

@@ -7,24 +7,22 @@ },

layouts::{Backend, DataMut, Module, Scratch, VecZnx, ZnxZero}, }; -use crate::layouts::{ - GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, GLWEInfos, GLWELayoutSet, GLWEPlaintext, LWEInfos, TorusPrecision, -}; +use crate::layouts::{GLWE, GLWEInfos, GLWEPlaintext, GLWEToMut, GLWEToRef, LWEInfos, SetGLWEInfos, TorusPrecision}; impl<D> GLWEOperations for GLWEPlaintext<D> where D: DataMut, - GLWEPlaintext<D>: GLWECiphertextToMut + GLWEInfos, + GLWEPlaintext<D>: GLWEToMut + GLWEInfos, { } -impl<D: DataMut> GLWEOperations for GLWECiphertext<D> where GLWECiphertext<D>: GLWECiphertextToMut + GLWEInfos {} +impl<D: DataMut> GLWEOperations for GLWE<D> where GLWE<D>: GLWEToMut + GLWEInfos {} -pub trait GLWEOperations: GLWECiphertextToMut + GLWEInfos + GLWELayoutSet + Sized { +pub trait GLWEOperations: GLWEToMut + GLWEInfos + SetGLWEInfos + Sized { fn add<A, B, BACKEND: Backend>(&mut self, module: &Module<BACKEND>, a: &A, b: &B) where - A: GLWECiphertextToRef + GLWEInfos, - B: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, + B: GLWEToRef + GLWEInfos, Module<BACKEND>: VecZnxAdd + VecZnxCopy, { #[cfg(debug_assertions)]

@@ -39,9 +37,9 @@ let min_col: usize = (a.rank().min(b.rank()) + 1).into();

let max_col: usize = (a.rank().max(b.rank() + 1)).into(); let self_col: usize = (self.rank() + 1).into(); - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); - let b_ref: &GLWECiphertext<&[u8]> = &b.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); + let b_ref: &GLWE<&[u8]> = &b.to_ref(); (0..min_col).for_each(|i| { module.vec_znx_add(&mut self_mut.data, i, &a_ref.data, i, &b_ref.data, i);

@@ -64,13 +62,13 @@ self_mut.data.zero_at(i, j);

}); }); - self.set_basek(a.base2k()); + self.set_base2k(a.base2k()); self.set_k(set_k_binary(self, a, b)); } fn add_inplace<A, BACKEND: Backend>(&mut self, module: &Module<BACKEND>, a: &A) where - A: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, Module<BACKEND>: VecZnxAddInplace, { #[cfg(debug_assertions)]

@@ -80,8 +78,8 @@ assert_eq!(self.base2k(), a.base2k());

assert!(self.rank() >= a.rank()) } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(a.rank() + 1).into()).for_each(|i| { module.vec_znx_add_inplace(&mut self_mut.data, i, &a_ref.data, i);

@@ -92,8 +90,8 @@ }

fn sub<A, B, BACKEND: Backend>(&mut self, module: &Module<BACKEND>, a: &A, b: &B) where - A: GLWECiphertextToRef + GLWEInfos, - B: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, + B: GLWEToRef + GLWEInfos, Module<BACKEND>: VecZnxSub + VecZnxCopy + VecZnxNegateInplace, { #[cfg(debug_assertions)]

@@ -108,9 +106,9 @@ let min_col: usize = (a.rank().min(b.rank()) + 1).into();

let max_col: usize = (a.rank().max(b.rank() + 1)).into(); let self_col: usize = (self.rank() + 1).into(); - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); - let b_ref: &GLWECiphertext<&[u8]> = &b.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); + let b_ref: &GLWE<&[u8]> = &b.to_ref(); (0..min_col).for_each(|i| { module.vec_znx_sub(&mut self_mut.data, i, &a_ref.data, i, &b_ref.data, i);

@@ -134,13 +132,13 @@ self_mut.data.zero_at(i, j);

}); }); - self.set_basek(a.base2k()); + self.set_base2k(a.base2k()); self.set_k(set_k_binary(self, a, b)); } fn sub_inplace_ab<A, BACKEND: Backend>(&mut self, module: &Module<BACKEND>, a: &A) where - A: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, Module<BACKEND>: VecZnxSubInplace, { #[cfg(debug_assertions)]

@@ -150,8 +148,8 @@ assert_eq!(self.base2k(), a.base2k());

assert!(self.rank() >= a.rank()) } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(a.rank() + 1).into()).for_each(|i| { module.vec_znx_sub_inplace(&mut self_mut.data, i, &a_ref.data, i);

@@ -162,7 +160,7 @@ }

fn sub_inplace_ba<A, BACKEND: Backend>(&mut self, module: &Module<BACKEND>, a: &A) where - A: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, Module<BACKEND>: VecZnxSubNegateInplace, { #[cfg(debug_assertions)]

@@ -172,8 +170,8 @@ assert_eq!(self.base2k(), a.base2k());

assert!(self.rank() >= a.rank()) } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(a.rank() + 1).into()).for_each(|i| { module.vec_znx_sub_negate_inplace(&mut self_mut.data, i, &a_ref.data, i);

@@ -184,7 +182,7 @@ }

fn rotate<A, B: Backend>(&mut self, module: &Module<B>, k: i64, a: &A) where - A: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, Module<B>: VecZnxRotate, { #[cfg(debug_assertions)]

@@ -193,14 +191,14 @@ assert_eq!(a.n(), self.n());

assert_eq!(self.rank(), a.rank()) } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(a.rank() + 1).into()).for_each(|i| { module.vec_znx_rotate(k, &mut self_mut.data, i, &a_ref.data, i); }); - self.set_basek(a.base2k()); + self.set_base2k(a.base2k()); self.set_k(set_k_unary(self, a)) }

@@ -208,7 +206,7 @@ fn rotate_inplace<B: Backend>(&mut self, module: &Module<B>, k: i64, scratch: &mut Scratch<B>)

where Module<B>: VecZnxRotateInplace<B>, { - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); (0..(self_mut.rank() + 1).into()).for_each(|i| { module.vec_znx_rotate_inplace(k, &mut self_mut.data, i, scratch);

@@ -217,7 +215,7 @@ }

fn mul_xp_minus_one<A, B: Backend>(&mut self, module: &Module<B>, k: i64, a: &A) where - A: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, Module<B>: VecZnxMulXpMinusOne, { #[cfg(debug_assertions)]

@@ -226,14 +224,14 @@ assert_eq!(a.n(), self.n());

assert_eq!(self.rank(), a.rank()) } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(a.rank() + 1).into()).for_each(|i| { module.vec_znx_mul_xp_minus_one(k, &mut self_mut.data, i, &a_ref.data, i); }); - self.set_basek(a.base2k()); + self.set_base2k(a.base2k()); self.set_k(set_k_unary(self, a)) }

@@ -241,17 +239,17 @@ fn mul_xp_minus_one_inplace<B: Backend>(&mut self, module: &Module<B>, k: i64, scratch: &mut Scratch<B>)

where Module<B>: VecZnxMulXpMinusOneInplace<B>, { - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); (0..(self_mut.rank() + 1).into()).for_each(|i| { module.vec_znx_mul_xp_minus_one_inplace(k, &mut self_mut.data, i, scratch); }); } - fn copy<A, B: Backend>(&mut self, module: &Module<B>, a: &A) + fn copy<A, M>(&mut self, module: &M, a: &A) where - A: GLWECiphertextToRef + GLWEInfos, - Module<B>: VecZnxCopy, + A: GLWEToRef + GLWEInfos, + M: VecZnxCopy, { #[cfg(debug_assertions)] {

@@ -259,15 +257,15 @@ assert_eq!(self.n(), a.n());

assert_eq!(self.rank(), a.rank()); } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(self_mut.rank() + 1).into()).for_each(|i| { module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i); }); self.set_k(a.k().min(self.max_k())); - self.set_basek(a.base2k()); + self.set_base2k(a.base2k()); } fn rsh<B: Backend>(&mut self, module: &Module<B>, k: usize, scratch: &mut Scratch<B>)

@@ -282,7 +280,7 @@ }

fn normalize<A, B: Backend>(&mut self, module: &Module<B>, a: &A, scratch: &mut Scratch<B>) where - A: GLWECiphertextToRef + GLWEInfos, + A: GLWEToRef + GLWEInfos, Module<B>: VecZnxNormalize<B>, { #[cfg(debug_assertions)]

@@ -291,8 +289,8 @@ assert_eq!(self.n(), a.n());

assert_eq!(self.rank(), a.rank()); } - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); - let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); + let a_ref: &GLWE<&[u8]> = &a.to_ref(); (0..(self_mut.rank() + 1).into()).for_each(|i| { module.vec_znx_normalize(

@@ -305,7 +303,7 @@ i,

scratch, ); }); - self.set_basek(a.base2k()); + self.set_base2k(a.base2k()); self.set_k(a.k().min(self.k())); }

@@ -313,16 +311,16 @@ fn normalize_inplace<B: Backend>(&mut self, module: &Module<B>, scratch: &mut Scratch<B>)

where Module<B>: VecZnxNormalizeInplace<B>, { - let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut(); + let self_mut: &mut GLWE<&mut [u8]> = &mut self.to_mut(); (0..(self_mut.rank() + 1).into()).for_each(|i| { module.vec_znx_normalize_inplace(self_mut.base2k().into(), &mut self_mut.data, i, scratch); }); } } -impl GLWECiphertext<Vec<u8>> { - pub fn rsh_scratch_space(n: usize) -> usize { - VecZnx::rsh_scratch_space(n) +impl GLWE<Vec<u8>> { + pub fn rsh_tmp_bytes(n: usize) -> usize { + VecZnx::rsh_tmp_bytes(n) } }
M poulpy-core/src/scratch.rs → poulpy-core/src/scratch.rs

@@ -1,365 +1,230 @@

use poulpy_hal::{ - api::{TakeMatZnx, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxDft, TakeVmpPMat}, + api::{ModuleN, ScratchAvailable, ScratchTakeBasic, SvpPPolBytesOf, VecZnxDftBytesOf, VmpPMatBytesOf}, layouts::{Backend, Scratch}, }; use crate::{ dist::Distribution, layouts::{ - Degree, GGLWEAutomorphismKey, GGLWECiphertext, GGLWEInfos, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, GGSWInfos, - GLWECiphertext, GLWEInfos, GLWEPlaintext, GLWEPublicKey, GLWESecret, Rank, + AutomorphismKey, GGLWE, GGLWEInfos, GGSW, GGSWInfos, GLWE, GLWEInfos, GLWEPlaintext, GLWEPublicKey, GLWESecret, + GLWESwitchingKey, Rank, TensorKey, prepared::{ - GGLWEAutomorphismKeyPrepared, GGLWECiphertextPrepared, GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared, - GGSWCiphertextPrepared, GLWEPublicKeyPrepared, GLWESecretPrepared, + AutomorphismKeyPrepared, GGLWEPrepared, GGSWPrepared, GLWEPublicKeyPrepared, GLWESecretPrepared, + GLWESwitchingKeyPrepared, TensorKeyPrepared, }, }, }; -pub trait TakeGLWECt { - fn take_glwe_ct<A>(&mut self, infos: &A) -> (GLWECiphertext<&mut [u8]>, &mut Self) - where - A: GLWEInfos; -} - -pub trait TakeGLWECtSlice { - fn take_glwe_ct_slice<A>(&mut self, size: usize, infos: &A) -> (Vec<GLWECiphertext<&mut [u8]>>, &mut Self) - where - A: GLWEInfos; -} - -pub trait TakeGLWEPt<B: Backend> { - fn take_glwe_pt<A>(&mut self, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self) - where - A: GLWEInfos; -} - -pub trait TakeGGLWE { - fn take_gglwe<A>(&mut self, infos: &A) -> (GGLWECiphertext<&mut [u8]>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeGGLWEPrepared<B: Backend> { - fn take_gglwe_prepared<A>(&mut self, infos: &A) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeGGSW { - fn take_ggsw<A>(&mut self, infos: &A) -> (GGSWCiphertext<&mut [u8]>, &mut Self) - where - A: GGSWInfos; -} - -pub trait TakeGGSWPrepared<B: Backend> { - fn take_ggsw_prepared<A>(&mut self, infos: &A) -> (GGSWCiphertextPrepared<&mut [u8], B>, &mut Self) - where - A: GGSWInfos; -} - -pub trait TakeGGSWPreparedSlice<B: Backend> { - fn take_ggsw_prepared_slice<A>(&mut self, size: usize, infos: &A) -> (Vec<GGSWCiphertextPrepared<&mut [u8], B>>, &mut Self) - where - A: GGSWInfos; -} - -pub trait TakeGLWESecret { - fn take_glwe_secret(&mut self, n: Degree, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self); -} - -pub trait TakeGLWESecretPrepared<B: Backend> { - fn take_glwe_secret_prepared(&mut self, n: Degree, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self); -} - -pub trait TakeGLWEPk { - fn take_glwe_pk<A>(&mut self, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self) - where - A: GLWEInfos; -} - -pub trait TakeGLWEPkPrepared<B: Backend> { - fn take_glwe_pk_prepared<A>(&mut self, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self) - where - A: GLWEInfos; -} - -pub trait TakeGLWESwitchingKey { - fn take_glwe_switching_key<A>(&mut self, infos: &A) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeGGLWESwitchingKeyPrepared<B: Backend> { - fn take_gglwe_switching_key_prepared<A>(&mut self, infos: &A) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeTensorKey { - fn take_tensor_key<A>(&mut self, infos: &A) -> (GGLWETensorKey<&mut [u8]>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeGGLWETensorKeyPrepared<B: Backend> { - fn take_gglwe_tensor_key_prepared<A>(&mut self, infos: &A) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeGGLWEAutomorphismKey { - fn take_gglwe_automorphism_key<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self) - where - A: GGLWEInfos; -} - -pub trait TakeGGLWEAutomorphismKeyPrepared<B: Backend> { - fn take_gglwe_automorphism_key_prepared<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self) - where - A: GGLWEInfos; -} - -impl<B: Backend> TakeGLWECt for Scratch<B> +pub trait ScratchTakeCore<B: Backend> where - Scratch<B>: TakeVecZnx, + Self: ScratchTakeBasic + ScratchAvailable, { - fn take_glwe_ct<A>(&mut self, infos: &A) -> (GLWECiphertext<&mut [u8]>, &mut Self) + fn take_glwe_ct<A, M>(&mut self, module: &M, infos: &A) -> (GLWE<&mut [u8]>, &mut Self) where A: GLWEInfos, + M: ModuleN, { - let (data, scratch) = self.take_vec_znx(infos.n().into(), (infos.rank() + 1).into(), infos.size()); + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_vec_znx(module, (infos.rank() + 1).into(), infos.size()); ( - GLWECiphertext::builder() - .base2k(infos.base2k()) - .k(infos.k()) - .data(data) - .build() - .unwrap(), + GLWE { + k: infos.k(), + base2k: infos.base2k(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGLWECtSlice for Scratch<B> -where - Scratch<B>: TakeVecZnx, -{ - fn take_glwe_ct_slice<A>(&mut self, size: usize, infos: &A) -> (Vec<GLWECiphertext<&mut [u8]>>, &mut Self) + fn take_glwe_ct_slice<A, M>(&mut self, module: &M, size: usize, infos: &A) -> (Vec<GLWE<&mut [u8]>>, &mut Self) where A: GLWEInfos, + M: ModuleN, { - let mut scratch: &mut Scratch<B> = self; - let mut cts: Vec<GLWECiphertext<&mut [u8]>> = Vec::with_capacity(size); + let mut scratch: &mut Self = self; + let mut cts: Vec<GLWE<&mut [u8]>> = Vec::with_capacity(size); for _ in 0..size { - let (ct, new_scratch) = scratch.take_glwe_ct(infos); + let (ct, new_scratch) = scratch.take_glwe_ct(module, infos); scratch = new_scratch; cts.push(ct); } (cts, scratch) } -} -impl<B: Backend> TakeGLWEPt<B> for Scratch<B> -where - Scratch<B>: TakeVecZnx, -{ - fn take_glwe_pt<A>(&mut self, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self) + fn take_glwe_pt<A, M>(&mut self, module: &M, infos: &A) -> (GLWEPlaintext<&mut [u8]>, &mut Self) where A: GLWEInfos, + M: ModuleN, { - let (data, scratch) = self.take_vec_znx(infos.n().into(), 1, infos.size()); + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_vec_znx(module, 1, infos.size()); ( - GLWEPlaintext::builder() - .base2k(infos.base2k()) - .k(infos.k()) - .data(data) - .build() - .unwrap(), + GLWEPlaintext { + k: infos.k(), + base2k: infos.base2k(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGGLWE for Scratch<B> -where - Scratch<B>: TakeMatZnx, -{ - fn take_gglwe<A>(&mut self, infos: &A) -> (GGLWECiphertext<&mut [u8]>, &mut Self) + fn take_gglwe<A, M>(&mut self, module: &M, infos: &A) -> (GGLWE<&mut [u8]>, &mut Self) where A: GGLWEInfos, + M: ModuleN, { + assert_eq!(module.n() as u32, infos.n()); let (data, scratch) = self.take_mat_znx( - infos.n().into(), + module, infos.dnum().0.div_ceil(infos.dsize().0) as usize, infos.rank_in().into(), (infos.rank_out() + 1).into(), infos.size(), ); ( - GGLWECiphertext::builder() - .base2k(infos.base2k()) - .k(infos.k()) - .dsize(infos.dsize()) - .data(data) - .build() - .unwrap(), + GGLWE { + k: infos.k(), + base2k: infos.base2k(), + dsize: infos.dsize(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGGLWEPrepared<B> for Scratch<B> -where - Scratch<B>: TakeVmpPMat<B>, -{ - fn take_gglwe_prepared<A>(&mut self, infos: &A) -> (GGLWECiphertextPrepared<&mut [u8], B>, &mut Self) + fn take_gglwe_prepared<A, M>(&mut self, module: &M, infos: &A) -> (GGLWEPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, + M: ModuleN + VmpPMatBytesOf, { + assert_eq!(module.n() as u32, infos.n()); let (data, scratch) = self.take_vmp_pmat( - infos.n().into(), + module, infos.dnum().into(), infos.rank_in().into(), (infos.rank_out() + 1).into(), infos.size(), ); ( - GGLWECiphertextPrepared::builder() - .base2k(infos.base2k()) - .dsize(infos.dsize()) - .k(infos.k()) - .data(data) - .build() - .unwrap(), + GGLWEPrepared { + k: infos.k(), + base2k: infos.base2k(), + dsize: infos.dsize(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGGSW for Scratch<B> -where - Scratch<B>: TakeMatZnx, -{ - fn take_ggsw<A>(&mut self, infos: &A) -> (GGSWCiphertext<&mut [u8]>, &mut Self) + fn take_ggsw<A, M>(&mut self, module: &M, infos: &A) -> (GGSW<&mut [u8]>, &mut Self) where A: GGSWInfos, + M: ModuleN, { + assert_eq!(module.n() as u32, infos.n()); let (data, scratch) = self.take_mat_znx( - infos.n().into(), + module, infos.dnum().into(), (infos.rank() + 1).into(), (infos.rank() + 1).into(), infos.size(), ); ( - GGSWCiphertext::builder() - .base2k(infos.base2k()) - .dsize(infos.dsize()) - .k(infos.k()) - .data(data) - .build() - .unwrap(), + GGSW { + k: infos.k(), + base2k: infos.base2k(), + dsize: infos.dsize(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGGSWPrepared<B> for Scratch<B> -where - Scratch<B>: TakeVmpPMat<B>, -{ - fn take_ggsw_prepared<A>(&mut self, infos: &A) -> (GGSWCiphertextPrepared<&mut [u8], B>, &mut Self) + fn take_ggsw_prepared<A, M>(&mut self, module: &M, infos: &A) -> (GGSWPrepared<&mut [u8], B>, &mut Self) where A: GGSWInfos, + M: ModuleN + VmpPMatBytesOf, { + assert_eq!(module.n() as u32, infos.n()); let (data, scratch) = self.take_vmp_pmat( - infos.n().into(), + module, infos.dnum().into(), (infos.rank() + 1).into(), (infos.rank() + 1).into(), infos.size(), ); ( - GGSWCiphertextPrepared::builder() - .base2k(infos.base2k()) - .dsize(infos.dsize()) - .k(infos.k()) - .data(data) - .build() - .unwrap(), + GGSWPrepared { + k: infos.k(), + base2k: infos.base2k(), + dsize: infos.dsize(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGGSWPreparedSlice<B> for Scratch<B> -where - Scratch<B>: TakeGGSWPrepared<B>, -{ - fn take_ggsw_prepared_slice<A>(&mut self, size: usize, infos: &A) -> (Vec<GGSWCiphertextPrepared<&mut [u8], B>>, &mut Self) + fn take_ggsw_prepared_slice<A, M>( + &mut self, + module: &M, + size: usize, + infos: &A, + ) -> (Vec<GGSWPrepared<&mut [u8], B>>, &mut Self) where A: GGSWInfos, + M: ModuleN + VmpPMatBytesOf, { - let mut scratch: &mut Scratch<B> = self; - let mut cts: Vec<GGSWCiphertextPrepared<&mut [u8], B>> = Vec::with_capacity(size); + let mut scratch: &mut Self = self; + let mut cts: Vec<GGSWPrepared<&mut [u8], B>> = Vec::with_capacity(size); for _ in 0..size { - let (ct, new_scratch) = scratch.take_ggsw_prepared(infos); + let (ct, new_scratch) = scratch.take_ggsw_prepared(module, infos); scratch = new_scratch; cts.push(ct) } (cts, scratch) } -} -impl<B: Backend> TakeGLWEPk for Scratch<B> -where - Scratch<B>: TakeVecZnx, -{ - fn take_glwe_pk<A>(&mut self, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self) + fn take_glwe_pk<A, M>(&mut self, module: &M, infos: &A) -> (GLWEPublicKey<&mut [u8]>, &mut Self) where A: GLWEInfos, + M: ModuleN, { - let (data, scratch) = self.take_vec_znx(infos.n().into(), (infos.rank() + 1).into(), infos.size()); + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_vec_znx(module, (infos.rank() + 1).into(), infos.size()); ( - GLWEPublicKey::builder() - .base2k(infos.base2k()) - .k(infos.k()) - .base2k(infos.base2k()) - .data(data) - .build() - .unwrap(), + GLWEPublicKey { + k: infos.k(), + dist: Distribution::NONE, + base2k: infos.base2k(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGLWEPkPrepared<B> for Scratch<B> -where - Scratch<B>: TakeVecZnxDft<B>, -{ - fn take_glwe_pk_prepared<A>(&mut self, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self) + fn take_glwe_pk_prepared<A, M>(&mut self, module: &M, infos: &A) -> (GLWEPublicKeyPrepared<&mut [u8], B>, &mut Self) where A: GLWEInfos, + M: ModuleN + VecZnxDftBytesOf, { - let (data, scratch) = self.take_vec_znx_dft(infos.n().into(), (infos.rank() + 1).into(), infos.size()); + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_vec_znx_dft(module, (infos.rank() + 1).into(), infos.size()); ( - GLWEPublicKeyPrepared::builder() - .base2k(infos.base2k()) - .k(infos.k()) - .data(data) - .build() - .unwrap(), + GLWEPublicKeyPrepared { + k: infos.k(), + dist: Distribution::NONE, + base2k: infos.base2k(), + data, + }, scratch, ) } -} -impl<B: Backend> TakeGLWESecret for Scratch<B> -where - Scratch<B>: TakeScalarZnx, -{ - fn take_glwe_secret(&mut self, n: Degree, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self) { - let (data, scratch) = self.take_scalar_znx(n.into(), rank.into()); + fn take_glwe_secret<M>(&mut self, module: &M, rank: Rank) -> (GLWESecret<&mut [u8]>, &mut Self) + where + M: ModuleN, + { + let (data, scratch) = self.take_scalar_znx(module, rank.into()); ( GLWESecret { data,

@@ -368,14 +233,12 @@ },

scratch, ) } -} -impl<B: Backend> TakeGLWESecretPrepared<B> for Scratch<B> -where - Scratch<B>: TakeSvpPPol<B>, -{ - fn take_glwe_secret_prepared(&mut self, n: Degree, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self) { - let (data, scratch) = self.take_svp_ppol(n.into(), rank.into()); + fn take_glwe_secret_prepared<M>(&mut self, module: &M, rank: Rank) -> (GLWESecretPrepared<&mut [u8], B>, &mut Self) + where + M: ModuleN + SvpPPolBytesOf, + { + let (data, scratch) = self.take_svp_ppol(module, rank.into()); ( GLWESecretPrepared { data,

@@ -384,19 +247,16 @@ },

scratch, ) } -} -impl<B: Backend> TakeGLWESwitchingKey for Scratch<B> -where - Scratch<B>: TakeMatZnx, -{ - fn take_glwe_switching_key<A>(&mut self, infos: &A) -> (GGLWESwitchingKey<&mut [u8]>, &mut Self) + fn take_glwe_switching_key<A, M>(&mut self, module: &M, infos: &A) -> (GLWESwitchingKey<&mut [u8]>, &mut Self) where A: GGLWEInfos, + M: ModuleN, { - let (data, scratch) = self.take_gglwe(infos); + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_gglwe(module, infos); ( - GGLWESwitchingKey { + GLWESwitchingKey { key: data, sk_in_n: 0, sk_out_n: 0,

@@ -404,19 +264,20 @@ },

scratch, ) } -} -impl<B: Backend> TakeGGLWESwitchingKeyPrepared<B> for Scratch<B> -where - Scratch<B>: TakeGGLWEPrepared<B>, -{ - fn take_gglwe_switching_key_prepared<A>(&mut self, infos: &A) -> (GGLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self) + fn take_gglwe_switching_key_prepared<A, M>( + &mut self, + module: &M, + infos: &A, + ) -> (GLWESwitchingKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, + M: ModuleN + VmpPMatBytesOf, { - let (data, scratch) = self.take_gglwe_prepared(infos); + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_gglwe_prepared(module, infos); ( - GGLWESwitchingKeyPrepared { + GLWESwitchingKeyPrepared { key: data, sk_in_n: 0, sk_out_n: 0,

@@ -424,101 +285,95 @@ },

scratch, ) } -} -impl<B: Backend> TakeGGLWEAutomorphismKey for Scratch<B> -where - Scratch<B>: TakeMatZnx, -{ - fn take_gglwe_automorphism_key<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKey<&mut [u8]>, &mut Self) + fn take_gglwe_automorphism_key<A, M>(&mut self, module: &M, infos: &A) -> (AutomorphismKey<&mut [u8]>, &mut Self) where A: GGLWEInfos, + M: ModuleN, { - let (data, scratch) = self.take_glwe_switching_key(infos); - (GGLWEAutomorphismKey { key: data, p: 0 }, scratch) + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_glwe_switching_key(module, infos); + (AutomorphismKey { key: data, p: 0 }, scratch) } -} -impl<B: Backend> TakeGGLWEAutomorphismKeyPrepared<B> for Scratch<B> -where - Scratch<B>: TakeGGLWESwitchingKeyPrepared<B>, -{ - fn take_gglwe_automorphism_key_prepared<A>(&mut self, infos: &A) -> (GGLWEAutomorphismKeyPrepared<&mut [u8], B>, &mut Self) + fn take_gglwe_automorphism_key_prepared<A, M>( + &mut self, + module: &M, + infos: &A, + ) -> (AutomorphismKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, + M: ModuleN + VmpPMatBytesOf, { - let (data, scratch) = self.take_gglwe_switching_key_prepared(infos); - (GGLWEAutomorphismKeyPrepared { key: data, p: 0 }, scratch) + assert_eq!(module.n() as u32, infos.n()); + let (data, scratch) = self.take_gglwe_switching_key_prepared(module, infos); + (AutomorphismKeyPrepared { key: data, p: 0 }, scratch) } -} -impl<B: Backend> TakeTensorKey for Scratch<B> -where - Scratch<B>: TakeMatZnx, -{ - fn take_tensor_key<A>(&mut self, infos: &A) -> (GGLWETensorKey<&mut [u8]>, &mut Self) + fn take_tensor_key<A, M>(&mut self, module: &M, infos: &A) -> (TensorKey<&mut [u8]>, &mut Self) where A: GGLWEInfos, + M: ModuleN, { + assert_eq!(module.n() as u32, infos.n()); assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKey" ); - let mut keys: Vec<GGLWESwitchingKey<&mut [u8]>> = Vec::new(); + let mut keys: Vec<GLWESwitchingKey<&mut [u8]>> = Vec::new(); let pairs: usize = (((infos.rank_out().0 + 1) * infos.rank_out().0) >> 1).max(1) as usize; - let mut scratch: &mut Scratch<B> = self; + let mut scratch: &mut Self = self; - let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.layout(); + let mut ksk_infos: crate::layouts::GGLWELayout = infos.gglwe_layout(); ksk_infos.rank_in = Rank(1); if pairs != 0 { - let (gglwe, s) = scratch.take_glwe_switching_key(&ksk_infos); + let (gglwe, s) = scratch.take_glwe_switching_key(module, &ksk_infos); scratch = s; keys.push(gglwe); } for _ in 1..pairs { - let (gglwe, s) = scratch.take_glwe_switching_key(&ksk_infos); + let (gglwe, s) = scratch.take_glwe_switching_key(module, &ksk_infos); scratch = s; keys.push(gglwe); } - (GGLWETensorKey { keys }, scratch) + (TensorKey { keys }, scratch) } -} -impl<B: Backend> TakeGGLWETensorKeyPrepared<B> for Scratch<B> -where - Scratch<B>: TakeVmpPMat<B>, -{ - fn take_gglwe_tensor_key_prepared<A>(&mut self, infos: &A) -> (GGLWETensorKeyPrepared<&mut [u8], B>, &mut Self) + fn take_gglwe_tensor_key_prepared<A, M>(&mut self, module: &M, infos: &A) -> (TensorKeyPrepared<&mut [u8], B>, &mut Self) where A: GGLWEInfos, + M: ModuleN + VmpPMatBytesOf, { + assert_eq!(module.n() as u32, infos.n()); assert_eq!( infos.rank_in(), infos.rank_out(), "rank_in != rank_out is not supported for GGLWETensorKeyPrepared" ); - let mut keys: Vec<GGLWESwitchingKeyPrepared<&mut [u8], B>> = Vec::new(); + let mut keys: Vec<GLWESwitchingKeyPrepared<&mut [u8], B>> = Vec::new(); let pairs: usize = (((infos.rank_out().0 + 1) * infos.rank_out().0) >> 1).max(1) as usize; - let mut scratch: &mut Scratch<B> = self; + let mut scratch: &mut Self = self; - let mut ksk_infos: crate::layouts::GGLWECiphertextLayout = infos.layout(); + let mut ksk_infos: crate::layouts::GGLWELayout = infos.gglwe_layout(); ksk_infos.rank_in = Rank(1); if pairs != 0 { - let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(&ksk_infos); + let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(module, &ksk_infos); scratch = s; keys.push(gglwe); } for _ in 1..pairs { - let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(&ksk_infos); + let (gglwe, s) = scratch.take_gglwe_switching_key_prepared(module, &ksk_infos); scratch = s; keys.push(gglwe); } - (GGLWETensorKeyPrepared { keys }, scratch) + (TensorKeyPrepared { keys }, scratch) } } + +impl<B: Backend> ScratchTakeCore<B> for Scratch<B> where Self: ScratchTakeBasic + ScratchAvailable {}
M poulpy-core/src/tests/serialization.rs → poulpy-core/src/tests/serialization.rs

@@ -1,12 +1,12 @@

use poulpy_hal::test_suite::serialization::test_reader_writer_interface; use crate::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKey, GGLWECiphertext, GGLWESwitchingKey, GGLWETensorKey, GGSWCiphertext, - GLWECiphertext, GLWEToLWEKey, LWECiphertext, LWESwitchingKey, LWEToGLWESwitchingKey, Rank, TorusPrecision, + AutomorphismKey, Base2K, Degree, Dnum, Dsize, GGLWE, GGSW, GLWE, GLWESwitchingKey, GLWEToLWESwitchingKey, LWE, + LWESwitchingKey, LWEToGLWESwitchingKey, Rank, TensorKey, TorusPrecision, compressed::{ - GGLWEAutomorphismKeyCompressed, GGLWECiphertextCompressed, GGLWESwitchingKeyCompressed, GGLWETensorKeyCompressed, - GGSWCiphertextCompressed, GLWECiphertextCompressed, GLWEToLWESwitchingKeyCompressed, LWECiphertextCompressed, - LWESwitchingKeyCompressed, LWEToGLWESwitchingKeyCompressed, + AutomorphismKeyCompressed, GGLWECompressed, GGSWCompressed, GLWECompressed, GLWESwitchingKeyCompressed, + GLWEToLWESwitchingKeyCompressed, LWECompressed, LWESwitchingKeyCompressed, LWEToGLWESwitchingKeyCompressed, + TensorKeyCompressed, }, };

@@ -20,95 +20,93 @@ const DSIZE: Dsize = Dsize(1);

#[test] fn glwe_serialization() { - let original: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc_with(N_GLWE, BASE2K, K, RANK); + let original: GLWE<Vec<u8>> = GLWE::alloc(N_GLWE, BASE2K, K, RANK); poulpy_hal::test_suite::serialization::test_reader_writer_interface(original); } #[test] fn glwe_compressed_serialization() { - let original: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, RANK); + let original: GLWECompressed<Vec<u8>> = GLWECompressed::alloc(N_GLWE, BASE2K, K, RANK); test_reader_writer_interface(original); } #[test] fn lwe_serialization() { - let original: LWECiphertext<Vec<u8>> = LWECiphertext::alloc_with(N_LWE, BASE2K, K); + let original: LWE<Vec<u8>> = LWE::alloc(N_LWE, BASE2K, K); test_reader_writer_interface(original); } #[test] fn lwe_compressed_serialization() { - let original: LWECiphertextCompressed<Vec<u8>> = LWECiphertextCompressed::alloc_with(BASE2K, K); + let original: LWECompressed<Vec<u8>> = LWECompressed::alloc(BASE2K, K); test_reader_writer_interface(original); } #[test] fn test_gglwe_serialization() { - let original: GGLWECiphertext<Vec<u8>> = GGLWECiphertext::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); + let original: GGLWE<Vec<u8>> = GGLWE::alloc(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_gglwe_compressed_serialization() { - let original: GGLWECiphertextCompressed<Vec<u8>> = - GGLWECiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); + let original: GGLWECompressed<Vec<u8>> = GGLWECompressed::alloc(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_glwe_switching_key_serialization() { - let original: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); + let original: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_glwe_switching_key_compressed_serialization() { - let original: GGLWESwitchingKeyCompressed<Vec<u8>> = - GGLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); + let original: GLWESwitchingKeyCompressed<Vec<u8>> = + GLWESwitchingKeyCompressed::alloc(N_GLWE, BASE2K, K, RANK, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_automorphism_key_serialization() { - let original: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); + let original: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_automorphism_key_compressed_serialization() { - let original: GGLWEAutomorphismKeyCompressed<Vec<u8>> = - GGLWEAutomorphismKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); + let original: AutomorphismKeyCompressed<Vec<u8>> = AutomorphismKeyCompressed::alloc(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_tensor_key_serialization() { - let original: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); + let original: TensorKey<Vec<u8>> = TensorKey::alloc(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn test_tensor_key_compressed_serialization() { - let original: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); + let original: TensorKeyCompressed<Vec<u8>> = TensorKeyCompressed::alloc(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn glwe_to_lwe_switching_key_serialization() { - let original: GLWEToLWEKey<Vec<u8>> = GLWEToLWEKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM); + let original: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(N_GLWE, BASE2K, K, RANK, DNUM); test_reader_writer_interface(original); } #[test] fn glwe_to_lwe_switching_key_compressed_serialization() { let original: GLWEToLWESwitchingKeyCompressed<Vec<u8>> = - GLWEToLWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM); + GLWEToLWESwitchingKeyCompressed::alloc(N_GLWE, BASE2K, K, RANK, DNUM); test_reader_writer_interface(original); } #[test] fn lwe_to_glwe_switching_key_serialization() { - let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM); + let original: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(N_GLWE, BASE2K, K, RANK, DNUM); test_reader_writer_interface(original); }

@@ -121,24 +119,24 @@ }

#[test] fn lwe_switching_key_serialization() { - let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc_with(N_GLWE, BASE2K, K, DNUM); + let original: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(N_GLWE, BASE2K, K, DNUM); test_reader_writer_interface(original); } #[test] fn lwe_switching_key_compressed_serialization() { - let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc_with(N_GLWE, BASE2K, K, DNUM); + let original: LWESwitchingKeyCompressed<Vec<u8>> = LWESwitchingKeyCompressed::alloc(N_GLWE, BASE2K, K, DNUM); test_reader_writer_interface(original); } #[test] fn ggsw_serialization() { - let original: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); + let original: GGSW<Vec<u8>> = GGSW::alloc(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); test_reader_writer_interface(original); } #[test] fn ggsw_compressed_serialization() { - let original: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc_with(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); + let original: GGSWCompressed<Vec<u8>> = GGSWCompressed::alloc(N_GLWE, BASE2K, K, RANK, DNUM, DSIZE); test_reader_writer_interface(original); }
M poulpy-core/src/tests/test_suite/automorphism/gglwe_atk.rs → poulpy-core/src/tests/test_suite/automorphism/gglwe_atk.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSubScalarInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, },

@@ -18,8 +18,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWEInfos, GLWEPlaintext, GLWESecret, - prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, + AutomorphismKey, AutomorphismKeyLayout, GGLWEInfos, GLWEPlaintext, GLWESecret, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, };

@@ -27,7 +27,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_gglwe_automorphism_key_automorphism<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -38,8 +38,8 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxAutomorphism + VecZnxAutomorphismInplace<B> - + SvpPPolAllocBytes - + VecZnxDftAllocBytes + + SvpPPolBytesOf + + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + VmpPMatAlloc<B> + VmpPrepare<B>

@@ -84,7 +84,7 @@ let dnum_in: usize = k_in / (base2k * di);

let dnum_out: usize = k_out / (base2k * di); let dnum_apply: usize = k_in.div_ceil(base2k * di); - let auto_key_in_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let auto_key_in_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_in.into(),

@@ -93,7 +93,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let auto_key_out_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let auto_key_out_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -102,7 +102,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let auto_key_apply_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let auto_key_apply_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_apply.into(),

@@ -111,18 +111,18 @@ dsize: di.into(),

rank: rank.into(), }; - let mut auto_key_in: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_in_infos); - let mut auto_key_out: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_out_infos); - let mut auto_key_apply: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_apply_infos); + let mut auto_key_in: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_in_infos); + let mut auto_key_out: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_out_infos); + let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_apply_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &auto_key_in_infos) - | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &auto_key_apply_infos) - | GGLWEAutomorphismKey::automorphism_scratch_space( + AutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key_in_infos) + | AutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key_apply_infos) + | AutomorphismKey::automorphism_tmp_bytes( module, &auto_key_out_infos, &auto_key_in_infos,

@@ -130,7 +130,7 @@ &auto_key_apply_infos,

), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&auto_key_in); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&auto_key_in); sk.fill_ternary_prob(0.5, &mut source_xs); // gglwe_{s1}(s0) = s0 -> s1

@@ -153,8 +153,8 @@ &mut source_xe,

scratch.borrow(), ); - let mut auto_key_apply_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = - GGLWEAutomorphismKeyPrepared::alloc(module, &auto_key_apply_infos); + let mut auto_key_apply_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = + AutomorphismKeyPrepared::alloc_from_infos(module, &auto_key_apply_infos); auto_key_apply_prepared.prepare(module, &auto_key_apply, scratch.borrow());

@@ -166,9 +166,9 @@ &auto_key_apply_prepared,

scratch.borrow(), ); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&auto_key_out_infos); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&auto_key_out_infos); - let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(&auto_key_out_infos); + let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&auto_key_out_infos); sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk for i in 0..rank { module.vec_znx_automorphism(

@@ -224,7 +224,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_gglwe_automorphism_key_automorphism_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -238,9 +238,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDftTmpBytes

@@ -255,8 +255,8 @@ + VecZnxSwitchRing

+ VecZnxAddScalarInplace + VecZnxAutomorphism + VecZnxAutomorphismInplace<B> - + VecZnxDftAllocBytes - + VecZnxBigAllocBytes + + VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -293,7 +293,7 @@

let dnum_in: usize = k_in / (base2k * di); let dnum_apply: usize = k_in.div_ceil(base2k * di); - let auto_key_layout: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let auto_key_layout: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_in.into(),

@@ -302,7 +302,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let auto_key_apply_layout: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let auto_key_apply_layout: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_apply.into(),

@@ -311,20 +311,20 @@ dsize: di.into(),

rank: rank.into(), }; - let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_layout); - let mut auto_key_apply: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_apply_layout); + let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_layout); + let mut auto_key_apply: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_apply_layout); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &auto_key) - | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &auto_key_apply) - | GGLWEAutomorphismKey::automorphism_inplace_scratch_space(module, &auto_key, &auto_key_apply), + AutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key) + | AutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key_apply) + | AutomorphismKey::automorphism_inplace_tmp_bytes(module, &auto_key, &auto_key_apply), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&auto_key); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&auto_key); sk.fill_ternary_prob(0.5, &mut source_xs); // gglwe_{s1}(s0) = s0 -> s1

@@ -347,17 +347,17 @@ &mut source_xe,

scratch.borrow(), ); - let mut auto_key_apply_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = - GGLWEAutomorphismKeyPrepared::alloc(module, &auto_key_apply_layout); + let mut auto_key_apply_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = + AutomorphismKeyPrepared::alloc_from_infos(module, &auto_key_apply_layout); auto_key_apply_prepared.prepare(module, &auto_key_apply, scratch.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) auto_key.automorphism_inplace(module, &auto_key_apply_prepared, scratch.borrow()); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&auto_key); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&auto_key); - let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc(&auto_key); + let mut sk_auto: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&auto_key); sk_auto.fill_zero(); // Necessary to avoid panic of unfilled sk for i in 0..rank {
M poulpy-core/src/tests/test_suite/automorphism/ggsw_ct.rs → poulpy-core/src/tests/test_suite/automorphism/ggsw_ct.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigBytesOf, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare,

@@ -19,16 +19,16 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWEAutomorphismKey, GGLWETensorKey, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, - prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, + AutomorphismKey, GGSW, GGSWCiphertextLayout, GLWESecret, TensorKey, TensorKeyLayout, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc, TensorKeyPrepared}, }, noise::noise_ggsw_keyswitch, }; pub fn test_ggsw_automorphism<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -41,7 +41,7 @@ + VecZnxDftAlloc<B>

+ VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpA<B> + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxAddScalarInplace + VecZnxCopy

@@ -110,7 +110,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let tensor_key_layout: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let tensor_key_layout: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -119,7 +119,7 @@ dsize: di.into(),

rank: rank.into(), }; - let auto_key_layout: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let auto_key_layout: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -128,10 +128,10 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ct_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_in_layout); - let mut ct_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_out_layout); - let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&tensor_key_layout); - let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_layout); + let mut ct_in: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_in_layout); + let mut ct_out: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_out_layout); + let mut tensor_key: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&tensor_key_layout); + let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_layout); let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); let mut source_xs: Source = Source::new([0u8; 32]);

@@ -139,15 +139,15 @@ let mut source_xe: Source = Source::new([0u8; 32]);

let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ct_in) - | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &auto_key) - | GGLWETensorKey::encrypt_sk_scratch_space(module, &tensor_key) - | GGSWCiphertext::automorphism_scratch_space(module, &ct_out, &ct_in, &auto_key, &tensor_key), + GGSW::encrypt_sk_tmp_bytes(module, &ct_in) + | AutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key) + | TensorKey::encrypt_sk_tmp_bytes(module, &tensor_key) + | GGSW::automorphism_tmp_bytes(module, &ct_out, &ct_in, &auto_key, &tensor_key), ); let var_xs: f64 = 0.5; - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&ct_out); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&ct_out); sk.fill_ternary_prob(var_xs, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -178,11 +178,11 @@ &mut source_xe,

scratch.borrow(), ); - let mut auto_key_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = - GGLWEAutomorphismKeyPrepared::alloc(module, &auto_key_layout); + let mut auto_key_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = + AutomorphismKeyPrepared::alloc_from_infos(module, &auto_key_layout); auto_key_prepared.prepare(module, &auto_key, scratch.borrow()); - let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc(module, &tensor_key_layout); + let mut tsk_prepared: TensorKeyPrepared<Vec<u8>, B> = TensorKeyPrepared::alloc_from_infos(module, &tensor_key_layout); tsk_prepared.prepare(module, &tensor_key, scratch.borrow()); ct_out.automorphism(

@@ -219,8 +219,8 @@

#[allow(clippy::too_many_arguments)] pub fn test_ggsw_automorphism_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -233,7 +233,7 @@ + VecZnxDftAlloc<B>

+ VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpA<B> + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxAddScalarInplace + VecZnxCopy

@@ -291,7 +291,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let tensor_key_layout: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let tensor_key_layout: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -300,7 +300,7 @@ dsize: di.into(),

rank: rank.into(), }; - let auto_key_layout: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let auto_key_layout: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -309,9 +309,9 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_out_layout); - let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&tensor_key_layout); - let mut auto_key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&auto_key_layout); + let mut ct: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_out_layout); + let mut tensor_key: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&tensor_key_layout); + let mut auto_key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&auto_key_layout); let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); let mut source_xs: Source = Source::new([0u8; 32]);

@@ -319,15 +319,15 @@ let mut source_xe: Source = Source::new([0u8; 32]);

let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ct) - | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &auto_key) - | GGLWETensorKey::encrypt_sk_scratch_space(module, &tensor_key) - | GGSWCiphertext::automorphism_inplace_scratch_space(module, &ct, &auto_key, &tensor_key), + GGSW::encrypt_sk_tmp_bytes(module, &ct) + | AutomorphismKey::encrypt_sk_tmp_bytes(module, &auto_key) + | TensorKey::encrypt_sk_tmp_bytes(module, &tensor_key) + | GGSW::automorphism_inplace_tmp_bytes(module, &ct, &auto_key, &tensor_key), ); let var_xs: f64 = 0.5; - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&ct); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&ct); sk.fill_ternary_prob(var_xs, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -358,11 +358,11 @@ &mut source_xe,

scratch.borrow(), ); - let mut auto_key_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = - GGLWEAutomorphismKeyPrepared::alloc(module, &auto_key_layout); + let mut auto_key_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = + AutomorphismKeyPrepared::alloc_from_infos(module, &auto_key_layout); auto_key_prepared.prepare(module, &auto_key, scratch.borrow()); - let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc(module, &tensor_key_layout); + let mut tsk_prepared: TensorKeyPrepared<Vec<u8>, B> = TensorKeyPrepared::alloc_from_infos(module, &tensor_key_layout); tsk_prepared.prepare(module, &tensor_key, scratch.borrow()); ct.automorphism_inplace(module, &auto_key_prepared, &tsk_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/automorphism/glwe_ct.rs → poulpy-core/src/tests/test_suite/automorphism/glwe_ct.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, },

@@ -18,15 +18,15 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, - prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, + AutomorphismKey, AutomorphismKeyLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, Prepare, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, }; pub fn test_glwe_automorphism<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -40,9 +40,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VmpApplyDftToDftTmpBytes

@@ -77,21 +77,21 @@

let n: usize = module.n(); let dnum: usize = k_in.div_ceil(base2k * dsize); - let ct_in_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let ct_in_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_in.into(), rank: rank.into(), }; - let ct_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let ct_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_out.into(), rank: rank.into(), }; - let autokey_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let autokey_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -100,10 +100,10 @@ dnum: dnum.into(),

dsize: di.into(), }; - let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&autokey_infos); - let mut ct_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&ct_in_infos); - let mut ct_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&ct_out_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&ct_out_infos); + let mut autokey: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&autokey_infos); + let mut ct_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ct_in_infos); + let mut ct_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ct_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ct_out_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -112,13 +112,13 @@

module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &autokey) - | GLWECiphertext::decrypt_scratch_space(module, &ct_out) - | GLWECiphertext::encrypt_sk_scratch_space(module, &ct_in) - | GLWECiphertext::automorphism_scratch_space(module, &ct_out, &ct_in, &autokey), + AutomorphismKey::encrypt_sk_tmp_bytes(module, &autokey) + | GLWE::decrypt_tmp_bytes(module, &ct_out) + | GLWE::encrypt_sk_tmp_bytes(module, &ct_in) + | GLWE::automorphism_tmp_bytes(module, &ct_out, &ct_in, &autokey), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&ct_out); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&ct_out); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -140,8 +140,8 @@ &mut source_xe,

scratch.borrow(), ); - let mut autokey_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = - GGLWEAutomorphismKeyPrepared::alloc(module, &autokey_infos); + let mut autokey_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = + AutomorphismKeyPrepared::alloc_from_infos(module, &autokey_infos); autokey_prepared.prepare(module, &autokey, scratch.borrow()); ct_out.automorphism(module, &ct_in, &autokey_prepared, scratch.borrow());

@@ -169,7 +169,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_glwe_automorphism_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -183,9 +183,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VmpApplyDftToDftTmpBytes

@@ -219,14 +219,14 @@

let n: usize = module.n(); let dnum: usize = k_out.div_ceil(base2k * dsize); - let ct_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let ct_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_out.into(), rank: rank.into(), }; - let autokey_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let autokey_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -235,9 +235,9 @@ dnum: dnum.into(),

dsize: di.into(), }; - let mut autokey: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&autokey_infos); - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&ct_out_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&ct_out_infos); + let mut autokey: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&autokey_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ct_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ct_out_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -246,13 +246,13 @@

module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &autokey) - | GLWECiphertext::decrypt_scratch_space(module, &ct) - | GLWECiphertext::encrypt_sk_scratch_space(module, &ct) - | GLWECiphertext::automorphism_inplace_scratch_space(module, &ct, &autokey), + AutomorphismKey::encrypt_sk_tmp_bytes(module, &autokey) + | GLWE::decrypt_tmp_bytes(module, &ct) + | GLWE::encrypt_sk_tmp_bytes(module, &ct) + | GLWE::automorphism_inplace_tmp_bytes(module, &ct, &autokey), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&ct); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&ct); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -274,8 +274,8 @@ &mut source_xe,

scratch.borrow(), ); - let mut autokey_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = - GGLWEAutomorphismKeyPrepared::alloc(module, &autokey); + let mut autokey_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = + AutomorphismKeyPrepared::alloc_from_infos(module, &autokey); autokey_prepared.prepare(module, &autokey, scratch.borrow()); ct.automorphism_inplace(module, &autokey_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/conversion.rs → poulpy-core/src/tests/test_suite/conversion.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, - VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, + VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform, ZnNormalizeInplace, },

@@ -16,15 +16,14 @@ source::Source,

}; use crate::layouts::{ - Base2K, Degree, Dnum, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, GLWEToLWEKey, GLWEToLWEKeyLayout, - LWECiphertext, LWECiphertextLayout, LWEPlaintext, LWESecret, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyLayout, Rank, - TorusPrecision, + Base2K, Degree, Dnum, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, LWE, + LWECiphertextLayout, LWEPlaintext, LWESecret, LWEToGLWESwitchingKey, LWEToGLWESwitchingKeyLayout, Rank, TorusPrecision, prepared::{GLWESecretPrepared, GLWEToLWESwitchingKeyPrepared, LWEToGLWESwitchingKeyPrepared, PrepareAlloc}, }; pub fn test_lwe_to_glwe<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -37,9 +36,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -83,7 +82,7 @@ dnum: Dnum(2),

rank_out: rank, }; - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n_glwe, base2k: Base2K(17), k: TorusPrecision(34),

@@ -97,12 +96,12 @@ k: TorusPrecision(34),

}; let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - LWEToGLWESwitchingKey::encrypt_sk_scratch_space(module, &lwe_to_glwe_infos) - | GLWECiphertext::from_lwe_scratch_space(module, &glwe_infos, &lwe_infos, &lwe_to_glwe_infos) - | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos), + LWEToGLWESwitchingKey::encrypt_sk_tmp_bytes(module, &lwe_to_glwe_infos) + | GLWE::from_lwe_tmp_bytes(module, &glwe_infos, &lwe_infos, &lwe_to_glwe_infos) + | GLWE::decrypt_tmp_bytes(module, &glwe_infos), ); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow());

@@ -112,13 +111,13 @@ sk_lwe.fill_ternary_prob(0.5, &mut source_xs);

let data: i64 = 17; - let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_infos); + let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_infos); lwe_pt.encode_i64(data, k_lwe_pt); - let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos); + let mut lwe_ct: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos); lwe_ct.encrypt_sk(module, &lwe_pt, &sk_lwe, &mut source_xa, &mut source_xe); - let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc(&lwe_to_glwe_infos); + let mut ksk: LWEToGLWESwitchingKey<Vec<u8>> = LWEToGLWESwitchingKey::alloc_from_infos(&lwe_to_glwe_infos); ksk.encrypt_sk( module,

@@ -129,13 +128,13 @@ &mut source_xe,

scratch.borrow(), ); - let mut glwe_ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); + let mut glwe_ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); let ksk_prepared: LWEToGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); glwe_ct.from_lwe(module, &lwe_ct, &ksk_prepared, scratch.borrow()); - let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); glwe_ct.decrypt(module, &mut glwe_pt, &sk_glwe_prepared, scratch.borrow()); assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);

@@ -143,7 +142,7 @@ }

pub fn test_glwe_to_lwe<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -156,9 +155,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -196,7 +195,7 @@ dnum: Dnum(2),

rank_in: rank, }; - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n_glwe, base2k: Base2K(17), k: TorusPrecision(34),

@@ -214,12 +213,12 @@ let mut source_xa: Source = Source::new([0u8; 32]);

let mut source_xe: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWEToLWEKey::encrypt_sk_scratch_space(module, &glwe_to_lwe_infos) - | LWECiphertext::from_glwe_scratch_space(module, &lwe_infos, &glwe_infos, &glwe_to_lwe_infos) - | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos), + GLWEToLWESwitchingKey::encrypt_sk_tmp_bytes(module, &glwe_to_lwe_infos) + | LWE::from_glwe_tmp_bytes(module, &lwe_infos, &glwe_infos, &glwe_to_lwe_infos) + | GLWE::decrypt_tmp_bytes(module, &glwe_infos), ); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow());

@@ -228,10 +227,10 @@ let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);

sk_lwe.fill_ternary_prob(0.5, &mut source_xs); let data: i64 = 17; - let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut glwe_pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); glwe_pt.encode_coeff_i64(data, k_lwe_pt, 0); - let mut glwe_ct = GLWECiphertext::alloc(&glwe_infos); + let mut glwe_ct = GLWE::alloc_from_infos(&glwe_infos); glwe_ct.encrypt_sk( module, &glwe_pt,

@@ -241,7 +240,7 @@ &mut source_xe,

scratch.borrow(), ); - let mut ksk: GLWEToLWEKey<Vec<u8>> = GLWEToLWEKey::alloc(&glwe_to_lwe_infos); + let mut ksk: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&glwe_to_lwe_infos); ksk.encrypt_sk( module,

@@ -252,13 +251,13 @@ &mut source_xe,

scratch.borrow(), ); - let mut lwe_ct: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos); + let mut lwe_ct: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos); let ksk_prepared: GLWEToLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); lwe_ct.from_glwe(module, &glwe_ct, &ksk_prepared, scratch.borrow()); - let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_infos); + let mut lwe_pt: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_infos); lwe_ct.decrypt(module, &mut lwe_pt, &sk_lwe); assert_eq!(glwe_pt.data.at(0, 0)[0], lwe_pt.data.at(0, 0)[0]);
M poulpy-core/src/tests/test_suite/encryption/gglwe_atk.rs → poulpy-core/src/tests/test_suite/encryption/gglwe_atk.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSubScalarInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, },

@@ -18,15 +18,15 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GLWEInfos, GLWESecret, - compressed::{Decompress, GGLWEAutomorphismKeyCompressed}, + AutomorphismKey, AutomorphismKeyLayout, GLWEInfos, GLWESecret, + compressed::{AutomorphismKeyCompressed, Decompress}, prepared::{GLWESecretPrepared, PrepareAlloc}, }, }; pub fn test_gglwe_automorphisk_key_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -40,7 +40,7 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes

@@ -51,7 +51,7 @@ + VecZnxAutomorphism

+ VecZnxSwitchRing + VecZnxAddScalarInplace + VecZnxAutomorphismInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxSubScalarInplace + VecZnxCopy

@@ -75,7 +75,7 @@ for di in 1..dsize + 1 {

let n: usize = module.n(); let dnum: usize = (k_ksk - di * base2k) / (di * base2k); - let atk_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let atk_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -84,17 +84,17 @@ dsize: di.into(),

rank: rank.into(), }; - let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&atk_infos); + let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&atk_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_tmp_bytes( module, &atk_infos, )); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&atk_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&atk_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let p = -5;

@@ -129,7 +129,7 @@ }

pub fn test_gglwe_automorphisk_key_compressed_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -143,7 +143,7 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes

@@ -154,7 +154,7 @@ + VecZnxAutomorphism

+ VecZnxSwitchRing + VecZnxAddScalarInplace + VecZnxAutomorphismInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxSubScalarInplace + VecZnxCopy

@@ -178,7 +178,7 @@ for di in 1..dsize + 1 {

let n: usize = module.n(); let dnum: usize = (k_ksk - di * base2k) / (di * base2k); - let atk_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let atk_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -187,16 +187,16 @@ dsize: di.into(),

rank: rank.into(), }; - let mut atk_compressed: GGLWEAutomorphismKeyCompressed<Vec<u8>> = GGLWEAutomorphismKeyCompressed::alloc(&atk_infos); + let mut atk_compressed: AutomorphismKeyCompressed<Vec<u8>> = AutomorphismKeyCompressed::alloc_from_infos(&atk_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWEAutomorphismKey::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(AutomorphismKey::encrypt_sk_tmp_bytes( module, &atk_infos, )); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&atk_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&atk_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let p = -5;

@@ -217,7 +217,7 @@ );

}); let sk_out_prepared = sk_out.prepare_alloc(module, scratch.borrow()); - let mut atk: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&atk_infos); + let mut atk: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&atk_infos); atk.decompress(module, &atk_compressed); atk.key
M poulpy-core/src/tests/test_suite/encryption/gglwe_ct.rs → poulpy-core/src/tests/test_suite/encryption/gglwe_ct.rs

@@ -1,8 +1,8 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSubScalarInplace, VecZnxSwitchRing, VmpPMatAlloc, VmpPrepare, },

@@ -17,15 +17,15 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWECiphertextLayout, GGLWESwitchingKey, GLWESecret, - compressed::{Decompress, GGLWESwitchingKeyCompressed}, + GGLWECiphertextLayout, GLWESecret, GLWESwitchingKey, + compressed::{Decompress, GLWESwitchingKeyCompressed}, prepared::{GLWESecretPrepared, PrepareAlloc}, }, }; pub fn test_gglwe_switching_key_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -39,12 +39,12 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxBigAddSmallInplace<B> + VecZnxSwitchRing + VecZnxAddScalarInplace - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxSubScalarInplace + VecZnxCopy

@@ -81,21 +81,21 @@ rank_in: rank_in.into(),

rank_out: rank_out.into(), }; - let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_infos); + let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_tmp_bytes( module, &gglwe_infos, )); - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into()); sk_in.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk_out.fill_ternary_prob(0.5, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -117,7 +117,7 @@ }

pub fn test_gglwe_switching_key_compressed_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -131,12 +131,12 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxBigAddSmallInplace<B> + VecZnxSwitchRing + VecZnxAddScalarInplace - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxSubScalarInplace + VecZnxCopy

@@ -173,20 +173,21 @@ rank_in: rank_in.into(),

rank_out: rank_out.into(), }; - let mut ksk_compressed: GGLWESwitchingKeyCompressed<Vec<u8>> = GGLWESwitchingKeyCompressed::alloc(&gglwe_infos); + let mut ksk_compressed: GLWESwitchingKeyCompressed<Vec<u8>> = + GLWESwitchingKeyCompressed::alloc_from_infos(&gglwe_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKeyCompressed::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKeyCompressed::encrypt_sk_tmp_bytes( module, &gglwe_infos, )); - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into()); sk_in.fill_ternary_prob(0.5, &mut source_xs); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk_out.fill_ternary_prob(0.5, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -201,7 +202,7 @@ &mut source_xe,

scratch.borrow(), ); - let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_infos); + let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_infos); ksk.decompress(module, &ksk_compressed); ksk.key
M poulpy-core/src/tests/test_suite/encryption/ggsw_ct.rs → poulpy-core/src/tests/test_suite/encryption/ggsw_ct.rs

@@ -1,10 +1,10 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VmpPMatAlloc, VmpPrepare, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAlloc, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, + VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VmpPMatAlloc, VmpPrepare, }, layouts::{Backend, Module, ScalarZnx, ScratchOwned}, oep::{

@@ -17,53 +17,16 @@

use crate::{ encryption::SIGMA, layouts::{ - GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, - compressed::{Decompress, GGSWCiphertextCompressed}, + GGSW, GGSWCiphertextLayout, GLWESecret, + compressed::{Decompress, GGSWCompressed}, prepared::{GLWESecretPrepared, PrepareAlloc}, }, }; -pub fn test_ggsw_encrypt_sk<B>(module: &Module<B>) +pub fn test_ggsw_encrypt_sk<B: Backend>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigNormalize<B> - + VecZnxDftApply<B> - + SvpApplyDftToDftInplace<B> - + VecZnxIdftApplyConsume<B> - + VecZnxNormalizeTmpBytes - + VecZnxFillUniform - + VecZnxSubInplace - + VecZnxAddInplace - + VecZnxNormalizeInplace<B> - + VecZnxAddNormal - + VecZnxNormalize<B> - + VecZnxSub - + SvpPrepare<B> - + SvpPPolAllocBytes - + SvpPPolAlloc<B> - + VecZnxBigAddSmallInplace<B> - + VecZnxAddScalarInplace - + VecZnxBigAllocBytes - + VecZnxBigAddInplace<B> - + VecZnxCopy - + VmpPMatAlloc<B> - + VmpPrepare<B> - + VecZnxBigAlloc<B> - + VecZnxDftAlloc<B> - + VecZnxBigNormalizeTmpBytes - + VecZnxIdftApplyTmpA<B>, - B: Backend - + TakeVecZnxDftImpl<B> - + TakeVecZnxBigImpl<B> - + TakeSvpPPolImpl<B> - + ScratchOwnedAllocImpl<B> - + ScratchOwnedBorrowImpl<B> - + ScratchAvailableImpl<B> - + TakeScalarZnxImpl<B> - + TakeVecZnxImpl<B> - + VecZnxDftAllocBytesImpl<B> - + VecZnxBigAllocBytesImpl<B> - + TakeSvpPPolImpl<B>, + ScratchOwned<B>: ScratchOwnedAlloc<B>, + Module<B>: SvpPrepare<B>, { let base2k: usize = 12; let k: usize = 54;

@@ -82,7 +45,7 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut ct: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);

@@ -92,12 +55,9 @@ let mut source_xa: Source = Source::new([0u8; 32]);

pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertext::encrypt_sk_scratch_space( - module, - &ggsw_infos, - )); + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSW::encrypt_sk_tmp_bytes(module, &ggsw_infos)); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&ggsw_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&ggsw_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -119,7 +79,7 @@ }

pub fn test_ggsw_compressed_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -133,11 +93,11 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxBigAddSmallInplace<B> + VecZnxAddScalarInplace - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxCopy + VmpPMatAlloc<B>

@@ -175,7 +135,7 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ct_compressed: GGSWCiphertextCompressed<Vec<u8>> = GGSWCiphertextCompressed::alloc(&ggsw_infos); + let mut ct_compressed: GGSWCompressed<Vec<u8>> = GGSWCompressed::alloc_from_infos(&ggsw_infos); let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);

@@ -184,12 +144,12 @@ let mut source_xe: Source = Source::new([0u8; 32]);

pt_scalar.fill_ternary_hw(0, n, &mut source_xs); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCiphertextCompressed::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGSWCompressed::encrypt_sk_tmp_bytes( module, &ggsw_infos, )); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&ggsw_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&ggsw_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -206,7 +166,7 @@ );

let noise_f = |_col_i: usize| -(k as f64) + SIGMA.log2() + 0.5; - let mut ct: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut ct: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); ct.decompress(module, &ct_compressed); ct.assert_noise(module, &sk_prepared, &pt_scalar, noise_f);
M poulpy-core/src/tests/test_suite/encryption/glwe_ct.rs → poulpy-core/src/tests/test_suite/encryption/glwe_ct.rs

@@ -1,10 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxBigAddInplace, VecZnxBigAddNormal, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, - VecZnxSubInplace, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, }, layouts::{Backend, Module, ScratchOwned}, oep::{

@@ -17,8 +16,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWEPlaintextLayout, GLWEPublicKey, GLWESecret, LWEInfos, - compressed::{Decompress, GLWECiphertextCompressed}, + GLWE, GLWELayout, GLWEPlaintext, GLWEPlaintextLayout, GLWEPublicKey, GLWESecret, LWEInfos, + compressed::{Decompress, GLWECompressed}, prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, operations::GLWEOperations,

@@ -26,8 +25,8 @@ };

pub fn test_glwe_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -36,7 +35,7 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxNormalizeTmpBytes + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + SvpApplyDftToDft<B> + VecZnxBigAddNormal<B>

@@ -64,7 +63,7 @@

for rank in 1_usize..3 { let n: usize = module.n(); - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_ct.into(),

@@ -77,20 +76,19 @@ base2k: base2k.into(),

k: k_pt.into(), }; - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_infos) - | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos), + GLWE::encrypt_sk_tmp_bytes(module, &glwe_infos) | GLWE::decrypt_tmp_bytes(module, &glwe_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -118,8 +116,8 @@ }

pub fn test_glwe_compressed_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -128,7 +126,7 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxNormalizeTmpBytes + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + SvpApplyDftToDft<B> + VecZnxBigAddNormal<B>

@@ -157,7 +155,7 @@

for rank in 1_usize..3 { let n: usize = module.n(); - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_ct.into(),

@@ -170,21 +168,20 @@ base2k: base2k.into(),

k: k_pt.into(), }; - let mut ct_compressed: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(&glwe_infos); + let mut ct_compressed: GLWECompressed<Vec<u8>> = GLWECompressed::alloc_from_infos(&glwe_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertextCompressed::encrypt_sk_scratch_space(module, &glwe_infos) - | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos), + GLWECompressed::encrypt_sk_tmp_bytes(module, &glwe_infos) | GLWE::decrypt_tmp_bytes(module, &glwe_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -201,7 +198,7 @@ &mut source_xe,

scratch.borrow(), ); - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); ct.decompress(module, &ct_compressed); ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());

@@ -221,8 +218,8 @@ }

pub fn test_glwe_encrypt_zero_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<B>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B> + VecZnxIdftApplyConsume<B>

@@ -231,7 +228,7 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxNormalizeTmpBytes + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + SvpApplyDftToDft<B> + VecZnxBigAddNormal<B>

@@ -258,29 +255,28 @@

for rank in 1_usize..3 { let n: usize = module.n(); - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_ct.into(), rank: rank.into(), }; - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([1u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertext::decrypt_scratch_space(module, &glwe_infos) - | GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_infos), + GLWE::decrypt_tmp_bytes(module, &glwe_infos) | GLWE::encrypt_sk_tmp_bytes(module, &glwe_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); ct.encrypt_zero_sk( module,

@@ -297,7 +293,7 @@ }

pub fn test_glwe_encrypt_pk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -311,10 +307,10 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxBigAddSmallInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxCopy + VecZnxDftAlloc<B>

@@ -336,16 +332,16 @@

for rank in 1_usize..3 { let n: usize = module.n(); - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_ct.into(), rank: rank.into(), }; - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -353,17 +349,17 @@ let mut source_xa: Source = Source::new([0u8; 32]);

let mut source_xu: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_infos) - | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos) - | GLWECiphertext::encrypt_pk_scratch_space(module, &glwe_infos), + GLWE::encrypt_sk_tmp_bytes(module, &glwe_infos) + | GLWE::decrypt_tmp_bytes(module, &glwe_infos) + | GLWE::encrypt_pk_tmp_bytes(module, &glwe_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); - let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc(&glwe_infos); - pk.generate_from_sk(module, &sk_prepared, &mut source_xa, &mut source_xe); + let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc_from_infos(&glwe_infos); + pk.generate(module, &sk_prepared, &mut source_xa, &mut source_xe); module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
M poulpy-core/src/tests/test_suite/encryption/glwe_tsk.rs → poulpy-core/src/tests/test_suite/encryption/glwe_tsk.rs

@@ -1,8 +1,8 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, + VecZnxBigAlloc, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSubScalarInplace, VecZnxSwitchRing, },

@@ -17,15 +17,15 @@

use crate::{ encryption::SIGMA, layouts::{ - Dsize, GGLWETensorKey, GGLWETensorKeyLayout, GLWEPlaintext, GLWESecret, - compressed::{Decompress, GGLWETensorKeyCompressed}, + Dsize, GLWEPlaintext, GLWESecret, TensorKey, TensorKeyLayout, + compressed::{Decompress, TensorKeyCompressed}, prepared::{GLWESecretPrepared, PrepareAlloc}, }, }; pub fn test_gglwe_tensor_key_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -39,10 +39,10 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxBigAddSmallInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxCopy + VecZnxDftAlloc<B>

@@ -71,7 +71,7 @@ for rank in 1_usize..3 {

let n: usize = module.n(); let dnum: usize = k / base2k; - let tensor_key_infos = GGLWETensorKeyLayout { + let tensor_key_infos = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k.into(),

@@ -80,18 +80,18 @@ dsize: Dsize(1),

rank: rank.into(), }; - let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&tensor_key_infos); + let mut tensor_key: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&tensor_key_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKey::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(TensorKey::encrypt_sk_tmp_bytes( module, &tensor_key_infos, )); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&tensor_key_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&tensor_key_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -103,11 +103,11 @@ &mut source_xe,

scratch.borrow(), ); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&tensor_key_infos); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&tensor_key_infos); let mut sk_ij_dft = module.vec_znx_dft_alloc(1, 1); let mut sk_ij_big = module.vec_znx_big_alloc(1, 1); - let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), 1_u32.into()); + let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), 1_u32.into()); let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(rank, 1); for i in 0..rank {

@@ -145,7 +145,7 @@ }

pub fn test_gglwe_tensor_key_compressed_encrypt_sk<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -159,10 +159,10 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxBigAddSmallInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxCopy + VecZnxDftAlloc<B>

@@ -190,7 +190,7 @@ for rank in 1_usize..3 {

let n: usize = module.n(); let dnum: usize = k / base2k; - let tensor_key_infos: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let tensor_key_infos: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k.into(),

@@ -199,17 +199,17 @@ dsize: Dsize(1),

rank: rank.into(), }; - let mut tensor_key_compressed: GGLWETensorKeyCompressed<Vec<u8>> = GGLWETensorKeyCompressed::alloc(&tensor_key_infos); + let mut tensor_key_compressed: TensorKeyCompressed<Vec<u8>> = TensorKeyCompressed::alloc_from_infos(&tensor_key_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); - let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKeyCompressed::encrypt_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(TensorKeyCompressed::encrypt_sk_tmp_bytes( module, &tensor_key_infos, )); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&tensor_key_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&tensor_key_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -217,14 +217,14 @@ let seed_xa: [u8; 32] = [1u8; 32];

tensor_key_compressed.encrypt_sk(module, &sk, seed_xa, &mut source_xe, scratch.borrow()); - let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&tensor_key_infos); + let mut tensor_key: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&tensor_key_infos); tensor_key.decompress(module, &tensor_key_compressed); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&tensor_key_infos); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&tensor_key_infos); let mut sk_ij_dft = module.vec_znx_dft_alloc(1, 1); let mut sk_ij_big = module.vec_znx_big_alloc(1, 1); - let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), 1_u32.into()); + let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), 1_u32.into()); let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(rank, 1); for i in 0..rank {
M poulpy-core/src/tests/test_suite/external_product/gglwe_ksk.rs → poulpy-core/src/tests/test_suite/external_product/gglwe_ksk.rs

@@ -1,8 +1,8 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubInplace, VecZnxSubScalarInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare,

@@ -18,8 +18,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWESwitchingKey, GGLWESwitchingKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, + GGSW, GGSWCiphertextLayout, GLWESecret, GLWESwitchingKey, GLWESwitchingKeyLayout, + prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_product, };

@@ -27,7 +27,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_gglwe_switching_key_external_product<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -41,9 +41,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxSwitchRing

@@ -81,7 +81,7 @@ let n: usize = module.n();

let dnum: usize = k_in.div_ceil(base2k * di); let dsize_in: usize = 1; - let gglwe_in_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_in_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_in.into(),

@@ -91,7 +91,7 @@ rank_in: rank_in.into(),

rank_out: rank_out.into(), }; - let gglwe_out_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_out_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -110,9 +110,9 @@ dsize: di.into(),

rank: rank_out.into(), }; - let mut ct_gglwe_in: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_in_infos); - let mut ct_gglwe_out: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_out_infos); - let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut ct_gglwe_in: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_in_infos); + let mut ct_gglwe_out: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_out_infos); + let mut ct_rgsw: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);

@@ -121,14 +121,14 @@ let mut source_xe: Source = Source::new([0u8; 32]);

let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_in_infos) - | GGLWESwitchingKey::external_product_scratch_space( + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_in_infos) + | GLWESwitchingKey::external_product_tmp_bytes( module, &gglwe_out_infos, &gglwe_in_infos, &ggsw_infos, ) - | GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_infos), + | GGSW::encrypt_sk_tmp_bytes(module, &ggsw_infos), ); let r: usize = 1;

@@ -137,10 +137,10 @@ pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r}

let var_xs: f64 = 0.5; - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into()); sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk_out.fill_ternary_prob(var_xs, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -163,7 +163,7 @@ &mut source_xe,

scratch.borrow(), ); - let ct_rgsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow()); + let ct_rgsw_prepared: GGSWPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow()); // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) ct_gglwe_out.external_product(module, &ct_gglwe_in, &ct_rgsw_prepared, scratch.borrow());

@@ -209,7 +209,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_gglwe_switching_key_external_product_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -223,9 +223,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxSwitchRing

@@ -263,7 +263,7 @@ let dnum: usize = k_out.div_ceil(base2k * di);

let dsize_in: usize = 1; - let gglwe_out_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_out_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -282,8 +282,8 @@ dsize: di.into(),

rank: rank_out.into(), }; - let mut ct_gglwe: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_out_infos); - let mut ct_rgsw: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut ct_gglwe: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_out_infos); + let mut ct_rgsw: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); let mut pt_rgsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);

@@ -292,9 +292,9 @@ let mut source_xe: Source = Source::new([0u8; 32]);

let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_out_infos) - | GGLWESwitchingKey::external_product_inplace_scratch_space(module, &gglwe_out_infos, &ggsw_infos) - | GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_infos), + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_out_infos) + | GLWESwitchingKey::external_product_inplace_tmp_bytes(module, &gglwe_out_infos, &ggsw_infos) + | GGSW::encrypt_sk_tmp_bytes(module, &ggsw_infos), ); let r: usize = 1;

@@ -303,10 +303,10 @@ pt_rgsw.to_mut().raw_mut()[r] = 1; // X^{r}

let var_xs: f64 = 0.5; - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into()); sk_in.fill_ternary_prob(var_xs, &mut source_xs); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk_out.fill_ternary_prob(var_xs, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -329,7 +329,7 @@ &mut source_xe,

scratch.borrow(), ); - let ct_rgsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow()); + let ct_rgsw_prepared: GGSWPrepared<Vec<u8>, B> = ct_rgsw.prepare_alloc(module, scratch.borrow()); // gglwe_(m) (x) RGSW_(X^k) = gglwe_(m * X^k) ct_gglwe.external_product_inplace(module, &ct_rgsw_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/external_product/ggsw_ct.rs → poulpy-core/src/tests/test_suite/external_product/ggsw_ct.rs

@@ -1,11 +1,11 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAlloc, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAlloc, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, + VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubInplace, VmpApplyDftToDft, + VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, }, layouts::{Backend, Module, ScalarZnx, ScalarZnxToMut, ScratchOwned, ZnxViewMut}, oep::{

@@ -18,8 +18,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, + GGSW, GGSWCiphertextLayout, GLWESecret, + prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_product, };

@@ -27,7 +27,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_ggsw_external_product<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -41,9 +41,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxAddScalarInplace

@@ -111,9 +111,9 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ggsw_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_in_infos); - let mut ggsw_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_out_infos); - let mut ggsw_apply: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_apply_infos); + let mut ggsw_in: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_in_infos); + let mut ggsw_out: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_out_infos); + let mut ggsw_apply: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_apply_infos); let mut pt_in: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); let mut pt_apply: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);

@@ -128,12 +128,12 @@

pt_apply.to_mut().raw_mut()[k] = 1; //X^{k} let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_apply_infos) - | GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_in_infos) - | GGSWCiphertext::external_product_scratch_space(module, &ggsw_out_infos, &ggsw_in_infos, &ggsw_apply_infos), + GGSW::encrypt_sk_tmp_bytes(module, &ggsw_apply_infos) + | GGSW::encrypt_sk_tmp_bytes(module, &ggsw_in_infos) + | GGSW::external_product_tmp_bytes(module, &ggsw_out_infos, &ggsw_in_infos, &ggsw_apply_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -155,7 +155,7 @@ &mut source_xe,

scratch.borrow(), ); - let ct_rhs_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); + let ct_rhs_prepared: GGSWPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); ggsw_out.external_product(module, &ggsw_in, &ct_rhs_prepared, scratch.borrow());

@@ -192,7 +192,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_ggsw_external_product_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -206,9 +206,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxAddScalarInplace

@@ -265,8 +265,8 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ggsw_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_out_infos); - let mut ggsw_apply: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_apply_infos); + let mut ggsw_out: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_out_infos); + let mut ggsw_apply: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_apply_infos); let mut pt_in: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); let mut pt_apply: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1);

@@ -282,12 +282,12 @@

pt_apply.to_mut().raw_mut()[k] = 1; //X^{k} let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_apply_infos) - | GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_out_infos) - | GGSWCiphertext::external_product_inplace_scratch_space(module, &ggsw_out_infos, &ggsw_apply_infos), + GGSW::encrypt_sk_tmp_bytes(module, &ggsw_apply_infos) + | GGSW::encrypt_sk_tmp_bytes(module, &ggsw_out_infos) + | GGSW::external_product_inplace_tmp_bytes(module, &ggsw_out_infos, &ggsw_apply_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -309,7 +309,7 @@ &mut source_xe,

scratch.borrow(), ); - let ct_rhs_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); + let ct_rhs_prepared: GGSWPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); ggsw_out.external_product_inplace(module, &ct_rhs_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/external_product/glwe_ct.rs → poulpy-core/src/tests/test_suite/external_product/glwe_ct.rs

@@ -1,8 +1,8 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxSub, VecZnxSubInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, },

@@ -17,8 +17,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GGSWCiphertext, GGSWCiphertextLayout, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, + GGSW, GGSWCiphertextLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, + prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::noise_ggsw_product, };

@@ -26,7 +26,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_glwe_external_product<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -39,9 +39,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -73,14 +73,14 @@

let n: usize = module.n(); let dnum: usize = k_in.div_ceil(base2k * dsize); - let glwe_in_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_in_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_in.into(), rank: rank.into(), }; - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -96,11 +96,11 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ggsw_apply: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_apply_infos); - let mut glwe_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_in_infos); - let mut glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); + let mut ggsw_apply: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_apply_infos); + let mut glwe_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_in_infos); + let mut glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); let mut pt_ggsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_in_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_in_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -116,12 +116,12 @@

pt_ggsw.raw_mut()[k] = 1; // X^{k} let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_apply_infos) - | GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_in_infos) - | GLWECiphertext::external_product_scratch_space(module, &glwe_out_infos, &glwe_in_infos, &ggsw_apply_infos), + GGSW::encrypt_sk_tmp_bytes(module, &ggsw_apply_infos) + | GLWE::encrypt_sk_tmp_bytes(module, &glwe_in_infos) + | GLWE::external_product_tmp_bytes(module, &glwe_out_infos, &glwe_in_infos, &ggsw_apply_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -143,7 +143,7 @@ &mut source_xe,

scratch.borrow(), ); - let ct_ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); + let ct_ggsw_prepared: GGSWPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); glwe_out.external_product(module, &glwe_in, &ct_ggsw_prepared, scratch.borrow());

@@ -178,7 +178,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_glwe_external_product_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -191,9 +191,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -224,7 +224,7 @@

let n: usize = module.n(); let dnum: usize = k_out.div_ceil(base2k * dsize); - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -240,10 +240,10 @@ dsize: di.into(),

rank: rank.into(), }; - let mut ggsw_apply: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_apply_infos); - let mut glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); + let mut ggsw_apply: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_apply_infos); + let mut glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); let mut pt_ggsw: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_out_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -259,12 +259,12 @@

pt_ggsw.raw_mut()[k] = 1; // X^{k} let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_apply_infos) - | GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_out_infos) - | GLWECiphertext::external_product_inplace_scratch_space(module, &glwe_out_infos, &ggsw_apply_infos), + GGSW::encrypt_sk_tmp_bytes(module, &ggsw_apply_infos) + | GLWE::encrypt_sk_tmp_bytes(module, &glwe_out_infos) + | GLWE::external_product_inplace_tmp_bytes(module, &glwe_out_infos, &ggsw_apply_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -286,7 +286,7 @@ &mut source_xe,

scratch.borrow(), ); - let ct_ggsw_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); + let ct_ggsw_prepared: GGSWPrepared<Vec<u8>, B> = ggsw_apply.prepare_alloc(module, scratch.borrow()); glwe_out.external_product_inplace(module, &ct_ggsw_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/keyswitch/gglwe_ct.rs → poulpy-core/src/tests/test_suite/keyswitch/gglwe_ct.rs

@@ -1,11 +1,11 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, - VecZnxSubInplace, VecZnxSubScalarInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, - VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, + VecZnxSubScalarInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, + VmpPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{

@@ -18,15 +18,15 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWESwitchingKey, GGLWESwitchingKeyLayout, GLWESecret, - prepared::{GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + GLWESecret, GLWESwitchingKey, GLWESwitchingKeyLayout, + prepared::{GLWESecretPrepared, GLWESwitchingKeyPrepared, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, }; pub fn test_gglwe_switching_key_keyswitch<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -39,9 +39,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -80,7 +80,7 @@ let dnum: usize = k_in / base2k;

let dnum_apply: usize = k_in.div_ceil(base2k * di); let dsize_in: usize = 1; - let gglwe_s0s1_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_s0s1_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_in.into(),

@@ -90,7 +90,7 @@ rank_in: rank_in_s0s1.into(),

rank_out: rank_out_s0s1.into(), }; - let gglwe_s1s2_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_s1s2_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -100,7 +100,7 @@ rank_in: rank_out_s0s1.into(),

rank_out: rank_out_s1s2.into(), }; - let gglwe_s0s2_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_s0s2_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -110,33 +110,33 @@ rank_in: rank_in_s0s1.into(),

rank_out: rank_out_s1s2.into(), }; - let mut gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_s0s1_infos); - let mut gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_s1s2_infos); - let mut gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_s0s2_infos); + let mut gglwe_s0s1: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_s0s1_infos); + let mut gglwe_s1s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_s1s2_infos); + let mut gglwe_s0s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_s0s2_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_s0s1_infos) - | GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_s1s2_infos) - | GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_s0s2_infos), + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_s0s1_infos) + | GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_s1s2_infos) + | GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_s0s2_infos), ); - let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::keyswitch_scratch_space( + let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_tmp_bytes( module, &gglwe_s0s1_infos, &gglwe_s0s2_infos, &gglwe_s1s2_infos, )); - let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in_s0s1.into()); + let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in_s0s1.into()); sk0.fill_ternary_prob(0.5, &mut source_xs); - let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out_s0s1.into()); + let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out_s0s1.into()); sk1.fill_ternary_prob(0.5, &mut source_xs); - let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out_s1s2.into()); + let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out_s1s2.into()); sk2.fill_ternary_prob(0.5, &mut source_xs); let sk2_prepared: GLWESecretPrepared<Vec<u8>, B> = sk2.prepare_alloc(module, scratch_apply.borrow());

@@ -160,7 +160,7 @@ &mut source_xe,

scratch_enc.borrow(), ); - let gglwe_s1s2_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = + let gglwe_s1s2_prepared: GLWESwitchingKeyPrepared<Vec<u8>, B> = gglwe_s1s2.prepare_alloc(module, scratch_apply.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0)

@@ -196,7 +196,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_gglwe_switching_key_keyswitch_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -209,9 +209,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -246,7 +246,7 @@ let n: usize = module.n();

let dnum: usize = k_out.div_ceil(base2k * di); let dsize_in: usize = 1; - let gglwe_s0s1_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_s0s1_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_out.into(),

@@ -256,7 +256,7 @@ rank_in: rank_in.into(),

rank_out: rank_out.into(), }; - let gglwe_s1s2_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let gglwe_s1s2_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -266,18 +266,18 @@ rank_in: rank_out.into(),

rank_out: rank_out.into(), }; - let mut gglwe_s0s1: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_s0s1_infos); - let mut gglwe_s1s2: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&gglwe_s1s2_infos); + let mut gglwe_s0s1: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_s0s1_infos); + let mut gglwe_s1s2: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_s1s2_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch_enc: ScratchOwned<B> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_s0s1_infos) - | GGLWESwitchingKey::encrypt_sk_scratch_space(module, &gglwe_s1s2_infos), + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_s0s1_infos) + | GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_s1s2_infos), ); - let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GGLWESwitchingKey::keyswitch_inplace_scratch_space( + let mut scratch_apply: ScratchOwned<B> = ScratchOwned::alloc(GLWESwitchingKey::keyswitch_inplace_tmp_bytes( module, &gglwe_s0s1_infos, &gglwe_s1s2_infos,

@@ -285,13 +285,13 @@ ));

let var_xs: f64 = 0.5; - let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in.into()); + let mut sk0: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into()); sk0.fill_ternary_prob(var_xs, &mut source_xs); - let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk1: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk1.fill_ternary_prob(var_xs, &mut source_xs); - let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk2: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk2.fill_ternary_prob(var_xs, &mut source_xs); let sk2_prepared: GLWESecretPrepared<Vec<u8>, B> = sk2.prepare_alloc(module, scratch_apply.borrow());

@@ -315,13 +315,13 @@ &mut source_xe,

scratch_enc.borrow(), ); - let gglwe_s1s2_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = + let gglwe_s1s2_prepared: GLWESwitchingKeyPrepared<Vec<u8>, B> = gglwe_s1s2.prepare_alloc(module, scratch_apply.borrow()); // gglwe_{s1}(s0) (x) gglwe_{s2}(s1) = gglwe_{s2}(s0) gglwe_s0s1.keyswitch_inplace(module, &gglwe_s1s2_prepared, scratch_apply.borrow()); - let gglwe_s0s2: GGLWESwitchingKey<Vec<u8>> = gglwe_s0s1; + let gglwe_s0s2: GLWESwitchingKey<Vec<u8>> = gglwe_s0s1; let max_noise: f64 = log2_std_noise_gglwe_product( n as f64,
M poulpy-core/src/tests/test_suite/keyswitch/ggsw_ct.rs → poulpy-core/src/tests/test_suite/keyswitch/ggsw_ct.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAddInplace, VecZnxDftAlloc, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, + VecZnxBigAlloc, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAddInplace, VecZnxDftAlloc, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, },

@@ -18,9 +18,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWESwitchingKey, GGLWESwitchingKeyLayout, GGLWETensorKey, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, - GLWESecret, - prepared::{GGLWESwitchingKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + GGSW, GGSWCiphertextLayout, GLWESecret, GLWESwitchingKey, GLWESwitchingKeyLayout, TensorKey, TensorKeyLayout, + prepared::{GLWESecretPrepared, GLWESwitchingKeyPrepared, PrepareAlloc, TensorKeyPrepared}, }, noise::noise_ggsw_keyswitch, };

@@ -28,7 +27,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_ggsw_keyswitch<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -41,9 +40,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -103,7 +102,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let tsk_infos: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let tsk_infos: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -112,7 +111,7 @@ dsize: di.into(),

rank: rank.into(), }; - let ksk_apply_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let ksk_apply_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -122,10 +121,10 @@ rank_in: rank.into(),

rank_out: rank.into(), }; - let mut ggsw_in: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_in_infos); - let mut ggsw_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_out_infos); - let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&tsk_infos); - let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&ksk_apply_infos); + let mut ggsw_in: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_in_infos); + let mut ggsw_out: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_out_infos); + let mut tsk: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&tsk_infos); + let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&ksk_apply_infos); let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); let mut source_xs: Source = Source::new([0u8; 32]);

@@ -133,10 +132,10 @@ let mut source_xe: Source = Source::new([0u8; 32]);

let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_in_infos) - | GGLWESwitchingKey::encrypt_sk_scratch_space(module, &ksk_apply_infos) - | GGLWETensorKey::encrypt_sk_scratch_space(module, &tsk_infos) - | GGSWCiphertext::keyswitch_scratch_space( + GGSW::encrypt_sk_tmp_bytes(module, &ggsw_in_infos) + | GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &ksk_apply_infos) + | TensorKey::encrypt_sk_tmp_bytes(module, &tsk_infos) + | GGSW::keyswitch_tmp_bytes( module, &ggsw_out_infos, &ggsw_in_infos,

@@ -147,11 +146,11 @@ );

let var_xs: f64 = 0.5; - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk_in.fill_ternary_prob(var_xs, &mut source_xs); let sk_in_dft: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk_out.fill_ternary_prob(var_xs, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -182,8 +181,8 @@ &mut source_xe,

scratch.borrow(), ); - let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - let tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow()); + let ksk_prepared: GLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); + let tsk_prepared: TensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow()); ggsw_out.keyswitch( module,

@@ -217,7 +216,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_ggsw_keyswitch_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -230,9 +229,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -282,7 +281,7 @@ dsize: dsize_in.into(),

rank: rank.into(), }; - let tsk_infos: GGLWETensorKeyLayout = GGLWETensorKeyLayout { + let tsk_infos: TensorKeyLayout = TensorKeyLayout { n: n.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -291,7 +290,7 @@ dsize: di.into(),

rank: rank.into(), }; - let ksk_apply_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let ksk_apply_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -301,9 +300,9 @@ rank_in: rank.into(),

rank_out: rank.into(), }; - let mut ggsw_out: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_out_infos); - let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&tsk_infos); - let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&ksk_apply_infos); + let mut ggsw_out: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_out_infos); + let mut tsk: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&tsk_infos); + let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&ksk_apply_infos); let mut pt_scalar: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(n, 1); let mut source_xs: Source = Source::new([0u8; 32]);

@@ -311,19 +310,19 @@ let mut source_xe: Source = Source::new([0u8; 32]);

let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGSWCiphertext::encrypt_sk_scratch_space(module, &ggsw_out_infos) - | GGLWESwitchingKey::encrypt_sk_scratch_space(module, &ksk_apply_infos) - | GGLWETensorKey::encrypt_sk_scratch_space(module, &tsk_infos) - | GGSWCiphertext::keyswitch_inplace_scratch_space(module, &ggsw_out_infos, &ksk_apply_infos, &tsk_infos), + GGSW::encrypt_sk_tmp_bytes(module, &ggsw_out_infos) + | GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &ksk_apply_infos) + | TensorKey::encrypt_sk_tmp_bytes(module, &tsk_infos) + | GGSW::keyswitch_inplace_tmp_bytes(module, &ggsw_out_infos, &ksk_apply_infos, &tsk_infos), ); let var_xs: f64 = 0.5; - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk_in.fill_ternary_prob(var_xs, &mut source_xs); let sk_in_dft: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk_out.fill_ternary_prob(var_xs, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -354,8 +353,8 @@ &mut source_xe,

scratch.borrow(), ); - let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); - let tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow()); + let ksk_prepared: GLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); + let tsk_prepared: TensorKeyPrepared<Vec<u8>, B> = tsk.prepare_alloc(module, scratch.borrow()); ggsw_out.keyswitch_inplace(module, &ksk_prepared, &tsk_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/keyswitch/glwe_ct.rs → poulpy-core/src/tests/test_suite/keyswitch/glwe_ct.rs

@@ -1,11 +1,10 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, - VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, - VmpPrepare, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, + VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, + VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, }, layouts::{Backend, Module, ScratchOwned}, oep::{

@@ -18,8 +17,8 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWESwitchingKey, GGLWESwitchingKeyLayout, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, - prepared::{GGLWESwitchingKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + GLWE, GLWELayout, GLWEPlaintext, GLWESecret, GLWESwitchingKey, GLWESwitchingKeyLayout, + prepared::{GLWESecretPrepared, GLWESwitchingKeyPrepared, PrepareAlloc}, }, noise::log2_std_noise_gglwe_product, };

@@ -27,7 +26,7 @@

#[allow(clippy::too_many_arguments)] pub fn test_glwe_keyswitch<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -40,9 +39,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -77,21 +76,21 @@

let n: usize = module.n(); let dnum: usize = k_in.div_ceil(base2k * dsize); - let glwe_in_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_in_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_in.into(), rank: rank_in.into(), }; - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_out.into(), rank: rank_out.into(), }; - let key_apply: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let key_apply: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -101,10 +100,10 @@ rank_in: rank_in.into(),

rank_out: rank_out.into(), }; - let mut ksk: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&key_apply); - let mut glwe_in: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_in_infos); - let mut glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_in_infos); + let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&key_apply); + let mut glwe_in: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_in_infos); + let mut glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_in_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -113,16 +112,16 @@

module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(module, &key_apply) - | GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_in_infos) - | GLWECiphertext::keyswitch_scratch_space(module, &glwe_out_infos, &glwe_in_infos, &key_apply), + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &key_apply) + | GLWE::encrypt_sk_tmp_bytes(module, &glwe_in_infos) + | GLWE::keyswitch_tmp_bytes(module, &glwe_out_infos, &glwe_in_infos, &key_apply), ); - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_in.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into()); sk_in.fill_ternary_prob(0.5, &mut source_xs); let sk_in_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank_out.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into()); sk_out.fill_ternary_prob(0.5, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -144,7 +143,7 @@ &mut source_xe,

scratch.borrow(), ); - let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); + let ksk_prepared: GLWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); glwe_out.keyswitch(module, &glwe_in, &ksk_prepared, scratch.borrow());

@@ -169,7 +168,7 @@ }

pub fn test_glwe_keyswitch_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -182,9 +181,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -217,14 +216,14 @@

let n: usize = module.n(); let dnum: usize = k_out.div_ceil(base2k * dsize); - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_out.into(), rank: rank.into(), }; - let key_apply_infos: GGLWESwitchingKeyLayout = GGLWESwitchingKeyLayout { + let key_apply_infos: GLWESwitchingKeyLayout = GLWESwitchingKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -234,9 +233,9 @@ rank_in: rank.into(),

rank_out: rank.into(), }; - let mut key_apply: GGLWESwitchingKey<Vec<u8>> = GGLWESwitchingKey::alloc(&key_apply_infos); - let mut glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_out_infos); + let mut key_apply: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&key_apply_infos); + let mut glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_out_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]);

@@ -245,16 +244,16 @@

module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GGLWESwitchingKey::encrypt_sk_scratch_space(module, &key_apply_infos) - | GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_out_infos) - | GLWECiphertext::keyswitch_inplace_scratch_space(module, &glwe_out_infos, &key_apply_infos), + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &key_apply_infos) + | GLWE::encrypt_sk_tmp_bytes(module, &glwe_out_infos) + | GLWE::keyswitch_inplace_tmp_bytes(module, &glwe_out_infos, &key_apply_infos), ); - let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk_in.fill_ternary_prob(0.5, &mut source_xs); let sk_in_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_in.prepare_alloc(module, scratch.borrow()); - let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n.into(), rank.into()); + let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank.into()); sk_out.fill_ternary_prob(0.5, &mut source_xs); let sk_out_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_out.prepare_alloc(module, scratch.borrow());

@@ -276,7 +275,7 @@ &mut source_xe,

scratch.borrow(), ); - let ksk_prepared: GGLWESwitchingKeyPrepared<Vec<u8>, B> = key_apply.prepare_alloc(module, scratch.borrow()); + let ksk_prepared: GLWESwitchingKeyPrepared<Vec<u8>, B> = key_apply.prepare_alloc(module, scratch.borrow()); glwe_out.keyswitch_inplace(module, &ksk_prepared, scratch.borrow());
M poulpy-core/src/tests/test_suite/keyswitch/lwe_ct.rs → poulpy-core/src/tests/test_suite/keyswitch/lwe_ct.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, - VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, + VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform, ZnNormalizeInplace, },

@@ -16,13 +16,13 @@ source::Source,

}; use crate::layouts::{ - LWECiphertext, LWECiphertextLayout, LWEPlaintext, LWESecret, LWESwitchingKey, LWESwitchingKeyLayout, + LWE, LWECiphertextLayout, LWEPlaintext, LWESecret, LWESwitchingKey, LWESwitchingKeyLayout, prepared::{LWESwitchingKeyPrepared, PrepareAlloc}, }; pub fn test_lwe_keyswitch<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -35,9 +35,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -99,8 +99,8 @@ base2k: base2k.into(),

}; let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - LWESwitchingKey::encrypt_sk_scratch_space(module, &key_apply_infos) - | LWECiphertext::keyswitch_scratch_space(module, &lwe_out_infos, &lwe_in_infos, &key_apply_infos), + LWESwitchingKey::encrypt_sk_tmp_bytes(module, &key_apply_infos) + | LWE::keyswitch_tmp_bytes(module, &lwe_out_infos, &lwe_in_infos, &key_apply_infos), ); let mut sk_lwe_in: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe_in.into());

@@ -111,10 +111,10 @@ sk_lwe_out.fill_ternary_prob(0.5, &mut source_xs);

let data: i64 = 17; - let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_with(base2k.into(), k_lwe_pt.into()); + let mut lwe_pt_in: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into()); lwe_pt_in.encode_i64(data, k_lwe_pt.into()); - let mut lwe_ct_in: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_in_infos); + let mut lwe_ct_in: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_in_infos); lwe_ct_in.encrypt_sk( module, &lwe_pt_in,

@@ -123,7 +123,7 @@ &mut source_xa,

&mut source_xe, ); - let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc(&key_apply_infos); + let mut ksk: LWESwitchingKey<Vec<u8>> = LWESwitchingKey::alloc_from_infos(&key_apply_infos); ksk.encrypt_sk( module,

@@ -134,13 +134,13 @@ &mut source_xe,

scratch.borrow(), ); - let mut lwe_ct_out: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_out_infos); + let mut lwe_ct_out: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_out_infos); let ksk_prepared: LWESwitchingKeyPrepared<Vec<u8>, B> = ksk.prepare_alloc(module, scratch.borrow()); lwe_ct_out.keyswitch(module, &lwe_ct_in, &ksk_prepared, scratch.borrow()); - let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_out_infos); + let mut lwe_pt_out: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_out_infos); lwe_ct_out.decrypt(module, &mut lwe_pt_out, &sk_lwe_out); assert_eq!(lwe_pt_in.data.at(0, 0)[0], lwe_pt_out.data.at(0, 0)[0]);
M poulpy-core/src/tests/test_suite/packing.rs → poulpy-core/src/tests/test_suite/packing.rs

@@ -2,10 +2,10 @@ use std::collections::HashMap;

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigBytesOf, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare,

@@ -21,14 +21,14 @@

use crate::{ GLWEOperations, GLWEPacker, layouts::{ - GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, - prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + AutomorphismKey, AutomorphismKeyLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, }; pub fn test_glwe_packing<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxAutomorphism + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B>

@@ -48,9 +48,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -88,14 +88,14 @@ let k_ksk: usize = k_ct + base2k * dsize;

let dnum: usize = k_ct.div_ceil(base2k * dsize); - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k_ct.into(), rank: rank.into(), }; - let key_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let key_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_ksk.into(),

@@ -105,16 +105,16 @@ dnum: dnum.into(),

}; let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_out_infos) - | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &key_infos) - | GLWEPacker::scratch_space(module, &glwe_out_infos, &key_infos), + GLWE::encrypt_sk_tmp_bytes(module, &glwe_out_infos) + | AutomorphismKey::encrypt_sk_tmp_bytes(module, &key_infos) + | GLWEPacker::tmp_bytes(module, &glwe_out_infos, &key_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_out_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_out_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow()); - let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_out_infos); + let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_out_infos); let mut data: Vec<i64> = vec![0i64; n]; data.iter_mut().enumerate().for_each(|(i, x)| { *x = i as i64;

@@ -124,8 +124,8 @@ pt.encode_vec_i64(&data, pt_k.into());

let gal_els: Vec<i64> = GLWEPacker::galois_elements(module); - let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); - let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&key_infos); + let mut auto_keys: HashMap<i64, AutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); + let mut tmp: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&key_infos); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk( module,

@@ -135,7 +135,7 @@ &mut source_xa,

&mut source_xe, scratch.borrow(), ); - let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow()); + let atk_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow()); auto_keys.insert(*gal_el, atk_prepared); });

@@ -143,7 +143,7 @@ let log_batch: usize = 0;

let mut packer: GLWEPacker = GLWEPacker::new(&glwe_out_infos, log_batch); - let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); + let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); ct.encrypt_sk( module,

@@ -171,19 +171,14 @@

if reverse_bits_msb(i, log_n as u32).is_multiple_of(5) { packer.add(module, Some(&ct), &auto_keys, scratch.borrow()); } else { - packer.add( - module, - None::<&GLWECiphertext<Vec<u8>>>, - &auto_keys, - scratch.borrow(), - ) + packer.add(module, None::<&GLWE<Vec<u8>>>, &auto_keys, scratch.borrow()) } }); - let mut res: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); + let mut res: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); packer.flush(module, &mut res); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_out_infos); let mut data: Vec<i64> = vec![0i64; n]; data.iter_mut().enumerate().for_each(|(i, x)| { if i.is_multiple_of(5) {
M poulpy-core/src/tests/test_suite/trace.rs → poulpy-core/src/tests/test_suite/trace.rs

@@ -2,13 +2,13 @@ use std::collections::HashMap;

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxBigAddInplace, - VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftAllocBytes, VecZnxDftApply, - VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, - VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, - VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, + VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, + VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, + VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, + VmpPrepare, }, layouts::{Backend, Module, ScratchOwned, ZnxView, ZnxViewMut}, oep::{

@@ -21,16 +21,15 @@

use crate::{ encryption::SIGMA, layouts::{ - GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, - LWEInfos, - prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + AutomorphismKey, AutomorphismKeyLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWEInfos, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc}, }, noise::var_noise_gglwe_product, }; pub fn test_glwe_trace_inplace<B>(module: &Module<B>) where - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VecZnxAutomorphism + VecZnxBigAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B>

@@ -48,9 +47,9 @@ + VecZnxAddNormal

+ VecZnxNormalize<B> + VecZnxSub + SvpPrepare<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxBigAddInplace<B> + VecZnxBigAddSmallInplace<B> + VecZnxNormalizeTmpBytes

@@ -83,14 +82,14 @@

let dsize: usize = 1; let dnum: usize = k.div_ceil(base2k * dsize); - let glwe_out_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_out_infos: GLWELayout = GLWELayout { n: n.into(), base2k: base2k.into(), k: k.into(), rank: rank.into(), }; - let key_infos: GGLWEAutomorphismKeyLayout = GGLWEAutomorphismKeyLayout { + let key_infos: AutomorphismKeyLayout = AutomorphismKeyLayout { n: n.into(), base2k: base2k.into(), k: k_autokey.into(),

@@ -99,22 +98,22 @@ dsize: dsize.into(),

dnum: dnum.into(), }; - let mut glwe_out: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_out_infos); - let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_out_infos); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_out_infos); + let mut glwe_out: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_out_infos); + let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_out_infos); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_out_infos); let mut source_xs: Source = Source::new([0u8; 32]); let mut source_xe: Source = Source::new([0u8; 32]); let mut source_xa: Source = Source::new([0u8; 32]); let mut scratch: ScratchOwned<B> = ScratchOwned::alloc( - GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_out_infos) - | GLWECiphertext::decrypt_scratch_space(module, &glwe_out_infos) - | GGLWEAutomorphismKey::encrypt_sk_scratch_space(module, &key_infos) - | GLWECiphertext::trace_inplace_scratch_space(module, &glwe_out_infos, &key_infos), + GLWE::encrypt_sk_tmp_bytes(module, &glwe_out_infos) + | GLWE::decrypt_tmp_bytes(module, &glwe_out_infos) + | AutomorphismKey::encrypt_sk_tmp_bytes(module, &key_infos) + | GLWE::trace_inplace_tmp_bytes(module, &glwe_out_infos, &key_infos), ); - let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_out_infos); + let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_out_infos); sk.fill_ternary_prob(0.5, &mut source_xs); let sk_dft: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());

@@ -135,9 +134,9 @@ &mut source_xe,

scratch.borrow(), ); - let mut auto_keys: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); - let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(module); - let mut tmp: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&key_infos); + let mut auto_keys: HashMap<i64, AutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); + let gal_els: Vec<i64> = GLWE::trace_galois_elements(module); + let mut tmp: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&key_infos); gal_els.iter().for_each(|gal_el| { tmp.encrypt_sk( module,

@@ -147,7 +146,7 @@ &mut source_xa,

&mut source_xe, scratch.borrow(), ); - let atk_prepared: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow()); + let atk_prepared: AutomorphismKeyPrepared<Vec<u8>, B> = tmp.prepare_alloc(module, scratch.borrow()); auto_keys.insert(*gal_el, atk_prepared); });
M poulpy-hal/src/api/module.rs → poulpy-hal/src/api/module.rs

@@ -4,3 +4,7 @@ /// Instantiate a new [crate::layouts::Module].

pub trait ModuleNew<B: Backend> { fn new(n: u64) -> Self; } + +pub trait ModuleN { + fn n(&self) -> usize; +}
M poulpy-hal/src/api/scratch.rs → poulpy-hal/src/api/scratch.rs

@@ -1,4 +1,7 @@

-use crate::layouts::{Backend, MatZnx, ScalarZnx, Scratch, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}; +use crate::{ + api::{ModuleN, SvpPPolBytesOf, VecZnxBigBytesOf, VecZnxDftBytesOf, VmpPMatBytesOf}, + layouts::{Backend, MatZnx, ScalarZnx, Scratch, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, +}; /// Allocates a new [crate::layouts::ScratchOwned] of `size` aligned bytes. pub trait ScratchOwnedAlloc<B: Backend> {

@@ -25,76 +28,130 @@ pub trait TakeSlice {

fn take_slice<T>(&mut self, len: usize) -> (&mut [T], &mut Self); } -/// Take a slice of bytes from a [Scratch], wraps it into a [ScalarZnx] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeScalarZnx { - fn take_scalar_znx(&mut self, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Self); -} +pub trait ScratchTakeBasic +where + Self: TakeSlice, +{ + fn take_scalar_znx<M>(&mut self, module: &M, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Self) + where + M: ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(ScalarZnx::bytes_of(module.n(), cols)); + ( + ScalarZnx::from_data(take_slice, module.n(), cols), + rem_slice, + ) + } -/// Take a slice of bytes from a [Scratch], wraps it into a [SvpPPol] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeSvpPPol<B: Backend> { - fn take_svp_ppol(&mut self, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Self); -} + fn take_svp_ppol<M, B: Backend>(&mut self, module: &M, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Self) + where + M: SvpPPolBytesOf + ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(module.bytes_of_svp_ppol(cols)); + (SvpPPol::from_data(take_slice, module.n(), cols), rem_slice) + } -/// Take a slice of bytes from a [Scratch], wraps it into a [VecZnx] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeVecZnx { - fn take_vec_znx(&mut self, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Self); -} + fn take_vec_znx<M>(&mut self, module: &M, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Self) + where + M: ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(VecZnx::bytes_of(module.n(), cols, size)); + ( + VecZnx::from_data(take_slice, module.n(), cols, size), + rem_slice, + ) + } -/// Take a slice of bytes from a [Scratch], slices it into a vector of [VecZnx] aand returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeVecZnxSlice { - fn take_vec_znx_slice(&mut self, len: usize, n: usize, cols: usize, size: usize) -> (Vec<VecZnx<&mut [u8]>>, &mut Self); -} + fn take_vec_znx_big<M, B: Backend>(&mut self, module: &M, cols: usize, size: usize) -> (VecZnxBig<&mut [u8], B>, &mut Self) + where + M: VecZnxBigBytesOf + ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(module.bytes_of_vec_znx_big(cols, size)); + ( + VecZnxBig::from_data(take_slice, module.n(), cols, size), + rem_slice, + ) + } -/// Take a slice of bytes from a [Scratch], wraps it into a [VecZnxBig] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeVecZnxBig<B: Backend> { - fn take_vec_znx_big(&mut self, n: usize, cols: usize, size: usize) -> (VecZnxBig<&mut [u8], B>, &mut Self); -} + fn take_vec_znx_dft<M, B: Backend>(&mut self, module: &M, cols: usize, size: usize) -> (VecZnxDft<&mut [u8], B>, &mut Self) + where + M: VecZnxDftBytesOf + ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(module.bytes_of_vec_znx_dft(cols, size)); -/// Take a slice of bytes from a [Scratch], wraps it into a [VecZnxDft] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeVecZnxDft<B: Backend> { - fn take_vec_znx_dft(&mut self, n: usize, cols: usize, size: usize) -> (VecZnxDft<&mut [u8], B>, &mut Self); -} + ( + VecZnxDft::from_data(take_slice, module.n(), cols, size), + rem_slice, + ) + } -/// Take a slice of bytes from a [Scratch], slices it into a vector of [VecZnxDft] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeVecZnxDftSlice<B: Backend> { - fn take_vec_znx_dft_slice( + fn take_vec_znx_dft_slice<M, B: Backend>( &mut self, + module: &M, len: usize, - n: usize, cols: usize, size: usize, - ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Self); -} + ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Self) + where + M: VecZnxDftBytesOf + ModuleN, + { + let mut scratch: &mut Self = self; + let mut slice: Vec<VecZnxDft<&mut [u8], B>> = Vec::with_capacity(len); + for _ in 0..len { + let (znx, new_scratch) = scratch.take_vec_znx_dft(module, cols, size); + scratch = new_scratch; + slice.push(znx); + } + (slice, scratch) + } + + fn take_vec_znx_slice<M>(&mut self, module: &M, len: usize, cols: usize, size: usize) -> (Vec<VecZnx<&mut [u8]>>, &mut Self) + where + M: ModuleN, + { + let mut scratch: &mut Self = self; + let mut slice: Vec<VecZnx<&mut [u8]>> = Vec::with_capacity(len); + for _ in 0..len { + let (znx, new_scratch) = scratch.take_vec_znx(module, cols, size); + scratch = new_scratch; + slice.push(znx); + } + (slice, scratch) + } -/// Take a slice of bytes from a [Scratch], wraps it into a [VmpPMat] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeVmpPMat<B: Backend> { - fn take_vmp_pmat( + fn take_vmp_pmat<M, B: Backend>( &mut self, - n: usize, + module: &M, rows: usize, cols_in: usize, cols_out: usize, size: usize, - ) -> (VmpPMat<&mut [u8], B>, &mut Self); -} + ) -> (VmpPMat<&mut [u8], B>, &mut Self) + where + M: VmpPMatBytesOf + ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(module.bytes_of_vmp_pmat(rows, cols_in, cols_out, size)); + ( + VmpPMat::from_data(take_slice, module.n(), rows, cols_in, cols_out, size), + rem_slice, + ) + } -/// Take a slice of bytes from a [Scratch], wraps it into a [MatZnx] and returns it -/// as well as a new [Scratch] minus the taken array of bytes. -pub trait TakeMatZnx { - fn take_mat_znx( + fn take_mat_znx<M>( &mut self, - n: usize, + module: &M, rows: usize, cols_in: usize, cols_out: usize, size: usize, - ) -> (MatZnx<&mut [u8]>, &mut Self); + ) -> (MatZnx<&mut [u8]>, &mut Self) + where + M: ModuleN, + { + let (take_slice, rem_slice) = self.take_slice(MatZnx::bytes_of(module.n(), rows, cols_in, cols_out, size)); + ( + MatZnx::from_data(take_slice, module.n(), rows, cols_in, cols_out, size), + rem_slice, + ) + } }
M poulpy-hal/src/api/svp_ppol.rs → poulpy-hal/src/api/svp_ppol.rs

@@ -8,8 +8,8 @@ fn svp_ppol_alloc(&self, cols: usize) -> SvpPPolOwned<B>;

} /// Returns the size in bytes to allocate a [crate::layouts::SvpPPol]. -pub trait SvpPPolAllocBytes { - fn svp_ppol_alloc_bytes(&self, cols: usize) -> usize; +pub trait SvpPPolBytesOf { + fn bytes_of_svp_ppol(&self, cols: usize) -> usize; } /// Consume a vector of bytes into a [crate::layouts::MatZnx].
M poulpy-hal/src/api/vec_znx_big.rs → poulpy-hal/src/api/vec_znx_big.rs

@@ -16,8 +16,8 @@ fn vec_znx_big_alloc(&self, cols: usize, size: usize) -> VecZnxBigOwned<B>;

} /// Returns the size in bytes to allocate a [crate::layouts::VecZnxBig]. -pub trait VecZnxBigAllocBytes { - fn vec_znx_big_alloc_bytes(&self, cols: usize, size: usize) -> usize; +pub trait VecZnxBigBytesOf { + fn bytes_of_vec_znx_big(&self, cols: usize, size: usize) -> usize; } /// Consume a vector of bytes into a [crate::layouts::VecZnxBig].
M poulpy-hal/src/api/vec_znx_dft.rs → poulpy-hal/src/api/vec_znx_dft.rs

@@ -10,8 +10,8 @@ pub trait VecZnxDftFromBytes<B: Backend> {

fn vec_znx_dft_from_bytes(&self, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B>; } -pub trait VecZnxDftAllocBytes { - fn vec_znx_dft_alloc_bytes(&self, cols: usize, size: usize) -> usize; +pub trait VecZnxDftBytesOf { + fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize; } pub trait VecZnxDftApply<B: Backend> {
M poulpy-hal/src/api/vmp_pmat.rs → poulpy-hal/src/api/vmp_pmat.rs

@@ -6,8 +6,8 @@ pub trait VmpPMatAlloc<B: Backend> {

fn vmp_pmat_alloc(&self, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> VmpPMatOwned<B>; } -pub trait VmpPMatAllocBytes { - fn vmp_pmat_alloc_bytes(&self, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize; +pub trait VmpPMatBytesOf { + fn bytes_of_vmp_pmat(&self, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize; } pub trait VmpPMatFromBytes<B: Backend> {
M poulpy-hal/src/delegates/scratch.rs → poulpy-hal/src/delegates/scratch.rs

@@ -1,14 +1,7 @@

use crate::{ - api::{ - ScratchAvailable, ScratchFromBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, TakeMatZnx, TakeScalarZnx, TakeSlice, - TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, TakeVecZnxSlice, TakeVmpPMat, - }, - layouts::{Backend, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}, - oep::{ - ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeMatZnxImpl, - TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl, - TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl, - }, + api::{ScratchAvailable, ScratchFromBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, TakeSlice}, + layouts::{Backend, Scratch, ScratchOwned}, + oep::{ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeSliceImpl}, }; impl<B> ScratchOwnedAlloc<B> for ScratchOwned<B>

@@ -55,104 +48,3 @@ fn take_slice<T>(&mut self, len: usize) -> (&mut [T], &mut Self) {

B::take_slice_impl(self, len) } } - -impl<B> TakeScalarZnx for Scratch<B> -where - B: Backend + TakeScalarZnxImpl<B>, -{ - fn take_scalar_znx(&mut self, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Self) { - B::take_scalar_znx_impl(self, n, cols) - } -} - -impl<B> TakeSvpPPol<B> for Scratch<B> -where - B: Backend + TakeSvpPPolImpl<B>, -{ - fn take_svp_ppol(&mut self, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Self) { - B::take_svp_ppol_impl(self, n, cols) - } -} - -impl<B> TakeVecZnx for Scratch<B> -where - B: Backend + TakeVecZnxImpl<B>, -{ - fn take_vec_znx(&mut self, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Self) { - B::take_vec_znx_impl(self, n, cols, size) - } -} - -impl<B> TakeVecZnxSlice for Scratch<B> -where - B: Backend + TakeVecZnxSliceImpl<B>, -{ - fn take_vec_znx_slice(&mut self, len: usize, n: usize, cols: usize, size: usize) -> (Vec<VecZnx<&mut [u8]>>, &mut Self) { - B::take_vec_znx_slice_impl(self, len, n, cols, size) - } -} - -impl<B> TakeVecZnxBig<B> for Scratch<B> -where - B: Backend + TakeVecZnxBigImpl<B>, -{ - fn take_vec_znx_big(&mut self, n: usize, cols: usize, size: usize) -> (VecZnxBig<&mut [u8], B>, &mut Self) { - B::take_vec_znx_big_impl(self, n, cols, size) - } -} - -impl<B> TakeVecZnxDft<B> for Scratch<B> -where - B: Backend + TakeVecZnxDftImpl<B>, -{ - fn take_vec_znx_dft(&mut self, n: usize, cols: usize, size: usize) -> (VecZnxDft<&mut [u8], B>, &mut Self) { - B::take_vec_znx_dft_impl(self, n, cols, size) - } -} - -impl<B> TakeVecZnxDftSlice<B> for Scratch<B> -where - B: Backend + TakeVecZnxDftSliceImpl<B>, -{ - fn take_vec_znx_dft_slice( - &mut self, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Self) { - B::take_vec_znx_dft_slice_impl(self, len, n, cols, size) - } -} - -impl<B> TakeVmpPMat<B> for Scratch<B> -where - B: Backend + TakeVmpPMatImpl<B>, -{ - fn take_vmp_pmat( - &mut self, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (VmpPMat<&mut [u8], B>, &mut Self) { - B::take_vmp_pmat_impl(self, n, rows, cols_in, cols_out, size) - } -} - -impl<B> TakeMatZnx for Scratch<B> -where - B: Backend + TakeMatZnxImpl<B>, -{ - fn take_mat_znx( - &mut self, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (MatZnx<&mut [u8]>, &mut Self) { - B::take_mat_znx_impl(self, n, rows, cols_in, cols_out, size) - } -}
M poulpy-hal/src/delegates/svp_ppol.rs → poulpy-hal/src/delegates/svp_ppol.rs

@@ -1,6 +1,6 @@

use crate::{ api::{ - SvpApplyDft, SvpApplyDftToDft, SvpApplyDftToDftAdd, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + SvpApplyDft, SvpApplyDftToDft, SvpApplyDftToDftAdd, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPPolFromBytes, SvpPrepare, }, layouts::{

@@ -30,12 +30,12 @@ B::svp_ppol_alloc_impl(self.n(), cols)

} } -impl<B> SvpPPolAllocBytes for Module<B> +impl<B> SvpPPolBytesOf for Module<B> where B: Backend + SvpPPolAllocBytesImpl<B>, { - fn svp_ppol_alloc_bytes(&self, cols: usize) -> usize { - B::svp_ppol_alloc_bytes_impl(self.n(), cols) + fn bytes_of_svp_ppol(&self, cols: usize) -> usize { + B::svp_ppol_bytes_of_impl(self.n(), cols) } }
M poulpy-hal/src/delegates/vec_znx_big.rs → poulpy-hal/src/delegates/vec_znx_big.rs

@@ -1,7 +1,7 @@

use crate::{ api::{ VecZnxBigAdd, VecZnxBigAddInplace, VecZnxBigAddNormal, VecZnxBigAddSmall, VecZnxBigAddSmallInplace, VecZnxBigAlloc, - VecZnxBigAllocBytes, VecZnxBigAutomorphism, VecZnxBigAutomorphismInplace, VecZnxBigAutomorphismInplaceTmpBytes, + VecZnxBigAutomorphism, VecZnxBigAutomorphismInplace, VecZnxBigAutomorphismInplaceTmpBytes, VecZnxBigBytesOf, VecZnxBigFromBytes, VecZnxBigFromSmall, VecZnxBigNegate, VecZnxBigNegateInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSub, VecZnxBigSubInplace, VecZnxBigSubNegateInplace, VecZnxBigSubSmallA, VecZnxBigSubSmallB, VecZnxBigSubSmallInplace, VecZnxBigSubSmallNegateInplace,

@@ -49,12 +49,12 @@ B::vec_znx_big_from_bytes_impl(self.n(), cols, size, bytes)

} } -impl<B> VecZnxBigAllocBytes for Module<B> +impl<B> VecZnxBigBytesOf for Module<B> where B: Backend + VecZnxBigAllocBytesImpl<B>, { - fn vec_znx_big_alloc_bytes(&self, cols: usize, size: usize) -> usize { - B::vec_znx_big_alloc_bytes_impl(self.n(), cols, size) + fn bytes_of_vec_znx_big(&self, cols: usize, size: usize) -> usize { + B::vec_znx_big_bytes_of_impl(self.n(), cols, size) } }
M poulpy-hal/src/delegates/vec_znx_dft.rs → poulpy-hal/src/delegates/vec_znx_dft.rs

@@ -1,8 +1,8 @@

use crate::{ api::{ - VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, - VecZnxDftFromBytes, VecZnxDftSub, VecZnxDftSubInplace, VecZnxDftSubNegateInplace, VecZnxDftZero, VecZnxIdftApply, - VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxIdftApplyTmpBytes, + VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxDftFromBytes, + VecZnxDftSub, VecZnxDftSubInplace, VecZnxDftSubNegateInplace, VecZnxDftZero, VecZnxIdftApply, VecZnxIdftApplyConsume, + VecZnxIdftApplyTmpA, VecZnxIdftApplyTmpBytes, }, layouts::{ Backend, Data, Module, Scratch, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftOwned, VecZnxDftToMut, VecZnxDftToRef,

@@ -24,12 +24,12 @@ B::vec_znx_dft_from_bytes_impl(self.n(), cols, size, bytes)

} } -impl<B> VecZnxDftAllocBytes for Module<B> +impl<B> VecZnxDftBytesOf for Module<B> where B: Backend + VecZnxDftAllocBytesImpl<B>, { - fn vec_znx_dft_alloc_bytes(&self, cols: usize, size: usize) -> usize { - B::vec_znx_dft_alloc_bytes_impl(self.n(), cols, size) + fn bytes_of_vec_znx_dft(&self, cols: usize, size: usize) -> usize { + B::vec_znx_dft_bytes_of_impl(self.n(), cols, size) } }
M poulpy-hal/src/delegates/vmp_pmat.rs → poulpy-hal/src/delegates/vmp_pmat.rs

@@ -1,7 +1,7 @@

use crate::{ api::{ VmpApplyDft, VmpApplyDftTmpBytes, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftAddTmpBytes, - VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatFromBytes, VmpPrepare, VmpPrepareTmpBytes, + VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPMatBytesOf, VmpPMatFromBytes, VmpPrepare, VmpPrepareTmpBytes, }, layouts::{ Backend, MatZnxToRef, Module, Scratch, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef, VmpPMatOwned, VmpPMatToMut,

@@ -23,12 +23,12 @@ B::vmp_pmat_alloc_impl(self.n(), rows, cols_in, cols_out, size)

} } -impl<B> VmpPMatAllocBytes for Module<B> +impl<B> VmpPMatBytesOf for Module<B> where B: Backend + VmpPMatAllocBytesImpl<B>, { - fn vmp_pmat_alloc_bytes(&self, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { - B::vmp_pmat_alloc_bytes_impl(self.n(), rows, cols_in, cols_out, size) + fn bytes_of_vmp_pmat(&self, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { + B::vmp_pmat_bytes_of_impl(self.n(), rows, cols_in, cols_out, size) } }
M poulpy-hal/src/layouts/mat_znx.rs → poulpy-hal/src/layouts/mat_znx.rs

@@ -114,12 +114,12 @@ }

} impl MatZnx<Vec<u8>> { - pub fn alloc_bytes(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { - rows * cols_in * VecZnx::<Vec<u8>>::alloc_bytes(n, cols_out, size) + pub fn bytes_of(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize { + rows * cols_in * VecZnx::<Vec<u8>>::bytes_of(n, cols_out, size) } pub fn alloc(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self { - let data: Vec<u8> = alloc_aligned(Self::alloc_bytes(n, rows, cols_in, cols_out, size)); + let data: Vec<u8> = alloc_aligned(Self::bytes_of(n, rows, cols_in, cols_out, size)); Self { data, n,

@@ -132,7 +132,7 @@ }

pub fn from_bytes(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == Self::alloc_bytes(n, rows, cols_in, cols_out, size)); + assert!(data.len() == Self::bytes_of(n, rows, cols_in, cols_out, size)); Self { data, n,

@@ -153,7 +153,7 @@ assert!(col < self.cols_in(), "cols: {} >= {}", col, self.cols_in());

} let self_ref: MatZnx<&[u8]> = self.to_ref(); - let nb_bytes: usize = VecZnx::<Vec<u8>>::alloc_bytes(self.n, self.cols_out, self.size); + let nb_bytes: usize = VecZnx::<Vec<u8>>::bytes_of(self.n, self.cols_out, self.size); let start: usize = nb_bytes * self.cols() * row + col * nb_bytes; let end: usize = start + nb_bytes;

@@ -181,7 +181,7 @@ let cols_in: usize = self.cols_in();

let size: usize = self.size(); let self_ref: MatZnx<&mut [u8]> = self.to_mut(); - let nb_bytes: usize = VecZnx::<Vec<u8>>::alloc_bytes(n, cols_out, size); + let nb_bytes: usize = VecZnx::<Vec<u8>>::bytes_of(n, cols_out, size); let start: usize = nb_bytes * cols_in * row + col * nb_bytes; let end: usize = start + nb_bytes;
M poulpy-hal/src/layouts/scalar_znx.rs → poulpy-hal/src/layouts/scalar_znx.rs

@@ -132,18 +132,18 @@ }

} impl ScalarZnx<Vec<u8>> { - pub fn alloc_bytes(n: usize, cols: usize) -> usize { + pub fn bytes_of(n: usize, cols: usize) -> usize { n * cols * size_of::<i64>() } pub fn alloc(n: usize, cols: usize) -> Self { - let data: Vec<u8> = alloc_aligned::<u8>(Self::alloc_bytes(n, cols)); + let data: Vec<u8> = alloc_aligned::<u8>(Self::bytes_of(n, cols)); Self { data, n, cols } } pub fn from_bytes(n: usize, cols: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == Self::alloc_bytes(n, cols)); + assert!(data.len() == Self::bytes_of(n, cols)); Self { data, n, cols } } }
M poulpy-hal/src/layouts/svp_ppol.rs → poulpy-hal/src/layouts/svp_ppol.rs

@@ -77,7 +77,7 @@ where

B: SvpPPolAllocBytesImpl<B>, { pub fn alloc(n: usize, cols: usize) -> Self { - let data: Vec<u8> = alloc_aligned::<u8>(B::svp_ppol_alloc_bytes_impl(n, cols)); + let data: Vec<u8> = alloc_aligned::<u8>(B::svp_ppol_bytes_of_impl(n, cols)); Self { data: data.into(), n,

@@ -88,7 +88,7 @@ }

pub fn from_bytes(n: usize, cols: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == B::svp_ppol_alloc_bytes_impl(n, cols)); + assert!(data.len() == B::svp_ppol_bytes_of_impl(n, cols)); Self { data: data.into(), n,
M poulpy-hal/src/layouts/vec_znx.rs → poulpy-hal/src/layouts/vec_znx.rs

@@ -110,7 +110,7 @@ type Scalar = i64;

} impl VecZnx<Vec<u8>> { - pub fn rsh_scratch_space(n: usize) -> usize { + pub fn rsh_tmp_bytes(n: usize) -> usize { n * std::mem::size_of::<i64>() } }

@@ -125,12 +125,12 @@ }

} impl VecZnx<Vec<u8>> { - pub fn alloc_bytes(n: usize, cols: usize, size: usize) -> usize { + pub fn bytes_of(n: usize, cols: usize, size: usize) -> usize { n * cols * size * size_of::<i64>() } pub fn alloc(n: usize, cols: usize, size: usize) -> Self { - let data: Vec<u8> = alloc_aligned::<u8>(Self::alloc_bytes(n, cols, size)); + let data: Vec<u8> = alloc_aligned::<u8>(Self::bytes_of(n, cols, size)); Self { data, n,

@@ -142,7 +142,7 @@ }

pub fn from_bytes<Scalar: Sized>(n: usize, cols: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == Self::alloc_bytes(n, cols, size)); + assert!(data.len() == Self::bytes_of(n, cols, size)); Self { data, n,
M poulpy-hal/src/layouts/vec_znx_big.rs → poulpy-hal/src/layouts/vec_znx_big.rs

@@ -96,7 +96,7 @@ where

B: VecZnxBigAllocBytesImpl<B>, { pub fn alloc(n: usize, cols: usize, size: usize) -> Self { - let data = alloc_aligned::<u8>(B::vec_znx_big_alloc_bytes_impl(n, cols, size)); + let data = alloc_aligned::<u8>(B::vec_znx_big_bytes_of_impl(n, cols, size)); Self { data: data.into(), n,

@@ -109,7 +109,7 @@ }

pub fn from_bytes(n: usize, cols: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == B::vec_znx_big_alloc_bytes_impl(n, cols, size)); + assert!(data.len() == B::vec_znx_big_bytes_of_impl(n, cols, size)); Self { data: data.into(), n,
M poulpy-hal/src/layouts/vec_znx_dft.rs → poulpy-hal/src/layouts/vec_znx_dft.rs

@@ -116,7 +116,7 @@ where

B: VecZnxDftAllocBytesImpl<B>, { pub fn alloc(n: usize, cols: usize, size: usize) -> Self { - let data: Vec<u8> = alloc_aligned::<u8>(B::vec_znx_dft_alloc_bytes_impl(n, cols, size)); + let data: Vec<u8> = alloc_aligned::<u8>(B::vec_znx_dft_bytes_of_impl(n, cols, size)); Self { data: data.into(), n,

@@ -129,7 +129,7 @@ }

pub fn from_bytes(n: usize, cols: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == B::vec_znx_dft_alloc_bytes_impl(n, cols, size)); + assert!(data.len() == B::vec_znx_dft_bytes_of_impl(n, cols, size)); Self { data: data.into(), n,
M poulpy-hal/src/layouts/vmp_pmat.rs → poulpy-hal/src/layouts/vmp_pmat.rs

@@ -88,9 +88,7 @@ where

B: VmpPMatAllocBytesImpl<B>, { pub fn alloc(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self { - let data: Vec<u8> = alloc_aligned(B::vmp_pmat_alloc_bytes_impl( - n, rows, cols_in, cols_out, size, - )); + let data: Vec<u8> = alloc_aligned(B::vmp_pmat_bytes_of_impl(n, rows, cols_in, cols_out, size)); Self { data: data.into(), n,

@@ -104,7 +102,7 @@ }

pub fn from_bytes(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size)); + assert!(data.len() == B::vmp_pmat_bytes_of_impl(n, rows, cols_in, cols_out, size)); Self { data: data.into(), n,
M poulpy-hal/src/layouts/zn.rs → poulpy-hal/src/layouts/zn.rs

@@ -98,7 +98,7 @@ type Scalar = i64;

} impl Zn<Vec<u8>> { - pub fn rsh_scratch_space(n: usize) -> usize { + pub fn rsh_tmp_bytes(n: usize) -> usize { n * std::mem::size_of::<i64>() } }

@@ -113,12 +113,12 @@ }

} impl Zn<Vec<u8>> { - pub fn alloc_bytes(n: usize, cols: usize, size: usize) -> usize { + pub fn bytes_of(n: usize, cols: usize, size: usize) -> usize { n * cols * size * size_of::<i64>() } pub fn alloc(n: usize, cols: usize, size: usize) -> Self { - let data: Vec<u8> = alloc_aligned::<u8>(Self::alloc_bytes(n, cols, size)); + let data: Vec<u8> = alloc_aligned::<u8>(Self::bytes_of(n, cols, size)); Self { data, n,

@@ -130,7 +130,7 @@ }

pub fn from_bytes<Scalar: Sized>(n: usize, cols: usize, size: usize, bytes: impl Into<Vec<u8>>) -> Self { let data: Vec<u8> = bytes.into(); - assert!(data.len() == Self::alloc_bytes(n, cols, size)); + assert!(data.len() == Self::bytes_of(n, cols, size)); Self { data, n,
M poulpy-hal/src/oep/scratch.rs → poulpy-hal/src/oep/scratch.rs

@@ -1,4 +1,4 @@

-use crate::layouts::{Backend, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat}; +use crate::layouts::{Backend, Scratch, ScratchOwned}; /// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) /// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation.

@@ -39,111 +39,3 @@ /// # Safety [crate::doc::backend_safety] for safety contract.

pub unsafe trait TakeSliceImpl<B: Backend> { fn take_slice_impl<T>(scratch: &mut Scratch<B>, len: usize) -> (&mut [T], &mut Scratch<B>); } - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeScalarZnx] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeScalarZnxImpl<B: Backend> { - fn take_scalar_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (ScalarZnx<&mut [u8]>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeSvpPPol] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeSvpPPolImpl<B: Backend> { - fn take_svp_ppol_impl(scratch: &mut Scratch<B>, n: usize, cols: usize) -> (SvpPPol<&mut [u8], B>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeVecZnx] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeVecZnxImpl<B: Backend> { - fn take_vec_znx_impl(scratch: &mut Scratch<B>, n: usize, cols: usize, size: usize) -> (VecZnx<&mut [u8]>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeVecZnxSlice] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeVecZnxSliceImpl<B: Backend> { - fn take_vec_znx_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnx<&mut [u8]>>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeVecZnxBig] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeVecZnxBigImpl<B: Backend> { - fn take_vec_znx_big_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxBig<&mut [u8], B>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeVecZnxDft] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeVecZnxDftImpl<B: Backend> { - fn take_vec_znx_dft_impl( - scratch: &mut Scratch<B>, - n: usize, - cols: usize, - size: usize, - ) -> (VecZnxDft<&mut [u8], B>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeVecZnxDftSlice] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeVecZnxDftSliceImpl<B: Backend> { - fn take_vec_znx_dft_slice_impl( - scratch: &mut Scratch<B>, - len: usize, - n: usize, - cols: usize, - size: usize, - ) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeVmpPMat] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeVmpPMatImpl<B: Backend> { - fn take_vmp_pmat_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (VmpPMat<&mut [u8], B>, &mut Scratch<B>); -} - -/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe) -/// * See the [poulpy-backend/src/cpu_fft64_ref/scratch.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/scratch.rs) reference implementation. -/// * See [crate::api::TakeMatZnx] for corresponding public API. -/// # Safety [crate::doc::backend_safety] for safety contract. -pub unsafe trait TakeMatZnxImpl<B: Backend> { - fn take_mat_znx_impl( - scratch: &mut Scratch<B>, - n: usize, - rows: usize, - cols_in: usize, - cols_out: usize, - size: usize, - ) -> (MatZnx<&mut [u8]>, &mut Scratch<B>); -}
M poulpy-hal/src/oep/svp_ppol.rs → poulpy-hal/src/oep/svp_ppol.rs

@@ -23,7 +23,7 @@ /// * See the [poulpy-backend/src/cpu_fft64_ref/svp.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/svp.rs) reference implementation.

/// * See [crate::api::SvpPPolAllocBytes] for corresponding public API. /// # Safety [crate::doc::backend_safety] for safety contract. pub unsafe trait SvpPPolAllocBytesImpl<B: Backend> { - fn svp_ppol_alloc_bytes_impl(n: usize, cols: usize) -> usize; + fn svp_ppol_bytes_of_impl(n: usize, cols: usize) -> usize; } /// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
M poulpy-hal/src/oep/vec_znx_big.rs → poulpy-hal/src/oep/vec_znx_big.rs

@@ -35,7 +35,7 @@ /// * See the [poulpy-backend/src/cpu_fft64_ref/vec_znx_big.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/vec_znx_big.rs) reference implementation.

/// * See [crate::api::VecZnxBigAllocBytes] for corresponding public API. /// # Safety [crate::doc::backend_safety] for safety contract. pub unsafe trait VecZnxBigAllocBytesImpl<B: Backend> { - fn vec_znx_big_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize; + fn vec_znx_big_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize; } #[allow(clippy::too_many_arguments)]
M poulpy-hal/src/oep/vec_znx_dft.rs → poulpy-hal/src/oep/vec_znx_dft.rs

@@ -42,7 +42,7 @@ /// * See the [poulpy-backend/src/cpu_fft64_ref/vec_znx_dft.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/vec_znx_dft.rs) reference implementation.

/// * See [crate::api::VecZnxDftAllocBytes] for corresponding public API. /// # Safety [crate::doc::backend_safety] for safety contract. pub unsafe trait VecZnxDftAllocBytesImpl<B: Backend> { - fn vec_znx_dft_alloc_bytes_impl(n: usize, cols: usize, size: usize) -> usize; + fn vec_znx_dft_bytes_of_impl(n: usize, cols: usize, size: usize) -> usize; } /// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
M poulpy-hal/src/oep/vmp_pmat.rs → poulpy-hal/src/oep/vmp_pmat.rs

@@ -15,7 +15,7 @@ /// * See [poulpy-backend/src/cpu_fft64_ref/vmp.rs](https://github.com/phantomzone-org/poulpy/blob/main/poulpy-backend/src/cpu_fft64_ref/vmp.rs) for reference implementation.

/// * See [crate::api::VmpPMatAllocBytes] for corresponding public API. /// # Safety [crate::doc::backend_safety] for safety contract. pub unsafe trait VmpPMatAllocBytesImpl<B: Backend> { - fn vmp_pmat_alloc_bytes_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize; + fn vmp_pmat_bytes_of_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize; } /// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
M poulpy-hal/src/reference/fft64/vmp.rs → poulpy-hal/src/reference/fft64/vmp.rs

@@ -140,7 +140,7 @@ assert!(tmp_bytes.len() >= vmp_apply_dft_tmp_bytes(n, size, pmat.rows(), cols));

assert!(a.cols() <= cols); } - let (data, tmp_bytes) = tmp_bytes.split_at_mut(BE::vec_znx_dft_alloc_bytes_impl(n, cols, size)); + let (data, tmp_bytes) = tmp_bytes.split_at_mut(BE::vec_znx_dft_bytes_of_impl(n, cols, size)); let mut a_dft: VecZnxDft<&mut [u8], BE> = VecZnxDft::from_data(cast_mut(data), n, cols, size);
M poulpy-schemes/benches/circuit_bootstrapping.rs → poulpy-schemes/benches/circuit_bootstrapping.rs

@@ -3,16 +3,16 @@

use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main}; use poulpy_backend::{FFT64Avx, FFT64Ref, FFT64Spqlios}; use poulpy_core::layouts::{ - Dsize, GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWESecret, LWECiphertext, - LWECiphertextLayout, LWESecret, prepared::PrepareAlloc, + AutomorphismKeyLayout, Dsize, GGSW, GGSWLayout, GLWESecret, LWE, LWELayout, LWESecret, TensorKeyLayout, + prepared::PrepareAlloc, }; use poulpy_hal::{ api::{ ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, - SvpPPolAllocBytes, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, - VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, - VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, - VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform, + SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, + VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAutomorphismInplace, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, + VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc,

@@ -42,7 +42,7 @@ Module<B>: ModuleNew<B>

+ VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -55,7 +55,7 @@ + VecZnxSub

+ VecZnxAddScalarInplace + VecZnxAutomorphism + VecZnxSwitchRing - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxIdftApplyTmpA<B> + SvpApplyDftToDft<B> + VecZnxBigAddInplace<B>

@@ -70,7 +70,7 @@ + SvpPPolAlloc<B>

+ VmpApplyDftToDftTmpBytes + VmpApplyDftToDft<B> + VmpApplyDftToDftAdd<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + VecZnxRotateInplace<B> + VecZnxBigAutomorphismInplace<B> + VecZnxRshInplace<B>

@@ -80,7 +80,7 @@ + VecZnxCopy

+ VecZnxAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B> + VecZnxRotateInplaceTmpBytes - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<B> + VecZnxRotate + ZnFillUniform

@@ -113,8 +113,8 @@ name: String,

extension_factor: usize, k_pt: usize, block_size: usize, - lwe_infos: LWECiphertextLayout, - ggsw_infos: GGSWCiphertextLayout, + lwe_infos: LWELayout, + ggsw_infos: GGSWLayout, cbt_infos: CircuitBootstrappingKeyLayout, }

@@ -124,7 +124,7 @@ Module<B>: ModuleNew<B>

+ VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -137,7 +137,7 @@ + VecZnxSub

+ VecZnxAddScalarInplace + VecZnxAutomorphism + VecZnxSwitchRing - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxIdftApplyTmpA<B> + SvpApplyDftToDft<B> + VecZnxBigAddInplace<B>

@@ -152,7 +152,7 @@ + SvpPPolAlloc<B>

+ VmpApplyDftToDftTmpBytes + VmpApplyDftToDft<B> + VmpApplyDftToDftAdd<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + VecZnxRotateInplace<B> + VecZnxBigAutomorphismInplace<B> + VecZnxRshInplace<B>

@@ -162,7 +162,7 @@ + VecZnxCopy

+ VecZnxAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B> + VecZnxRotateInplaceTmpBytes - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<B> + VecZnxRotate + ZnFillUniform

@@ -188,8 +188,8 @@ {

// Scratch space (4MB) let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(1 << 22); - let n_glwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_glwe(); - let n_lwe: poulpy_core::layouts::Degree = params.cbt_infos.layout_brk.n_lwe(); + let n_glwe: poulpy_core::layouts::RingDegree = params.cbt_infos.layout_brk.n_glwe(); + let n_lwe: poulpy_core::layouts::RingDegree = params.cbt_infos.layout_brk.n_lwe(); let rank: poulpy_core::layouts::Rank = params.cbt_infos.layout_brk.rank; let module: Module<B> = Module::<B>::new(n_glwe.as_u32() as u64);

@@ -202,10 +202,10 @@ let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe);

sk_lwe.fill_binary_block(params.block_size, &mut source_xs); sk_lwe.fill_zero(); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n_glwe, rank); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe, rank); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); - let ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&params.lwe_infos); + let ct_lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&params.lwe_infos); // Circuit bootstrapping evaluation key let cbt_key: CircuitBootstrappingKey<Vec<u8>, BRA> = CircuitBootstrappingKey::encrypt_sk(

@@ -218,7 +218,7 @@ &mut source_xe,

scratch.borrow(), ); - let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&params.ggsw_infos); + let mut res: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&params.ggsw_infos); let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> = cbt_key.prepare_alloc(&module, scratch.borrow()); move || {

@@ -238,13 +238,13 @@ for params in [Params {

name: String::from("1-bit"), extension_factor: 1, k_pt: 1, - lwe_infos: LWECiphertextLayout { + lwe_infos: LWELayout { n: 574_u32.into(), k: 13_u32.into(), base2k: 13_u32.into(), }, block_size: 7, - ggsw_infos: GGSWCiphertextLayout { + ggsw_infos: GGSWLayout { n: 1024_u32.into(), base2k: 13_u32.into(), k: 26_u32.into(),

@@ -261,7 +261,7 @@ k: 52_u32.into(),

dnum: 3_u32.into(), rank: 2_u32.into(), }, - layout_atk: GGLWEAutomorphismKeyLayout { + layout_atk: AutomorphismKeyLayout { n: 1024_u32.into(), base2k: 13_u32.into(), k: 52_u32.into(),

@@ -269,7 +269,7 @@ dnum: 3_u32.into(),

dsize: Dsize(1), rank: 2_u32.into(), }, - layout_tsk: GGLWETensorKeyLayout { + layout_tsk: TensorKeyLayout { n: 1024_u32.into(), base2k: 13_u32.into(), k: 52_u32.into(),
M poulpy-schemes/examples/circuit_bootstrapping.rs → poulpy-schemes/examples/circuit_bootstrapping.rs

@@ -1,9 +1,9 @@

use poulpy_core::{ GLWEOperations, layouts::{ - GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertext, GGSWCiphertextLayout, GLWECiphertext, - GLWECiphertextLayout, GLWEPlaintext, GLWESecret, LWECiphertext, LWECiphertextLayout, LWEInfos, LWEPlaintext, LWESecret, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared, PrepareAlloc}, + AutomorphismKeyLayout, GGSW, GGSWLayout, GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWEInfos, LWELayout, + LWEPlaintext, LWESecret, TensorKeyLayout, + prepared::{GGSWPrepared, GLWESecretPrepared, PrepareAlloc}, }, }; use std::time::Instant;

@@ -89,7 +89,7 @@ k: k_brk.into(),

dnum: rows_brk.into(), rank: rank.into(), }, - layout_atk: GGLWEAutomorphismKeyLayout { + layout_atk: AutomorphismKeyLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_trace.into(),

@@ -97,7 +97,7 @@ dnum: rows_trace.into(),

dsize: 1_u32.into(), rank: rank.into(), }, - layout_tsk: GGLWETensorKeyLayout { + layout_tsk: TensorKeyLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -107,7 +107,7 @@ rank: rank.into(),

}, }; - let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout { + let ggsw_infos: GGSWLayout = GGSWLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_ggsw_res.into(),

@@ -116,7 +116,7 @@ dsize: 1_u32.into(),

rank: rank.into(), }; - let lwe_infos = LWECiphertextLayout { + let lwe_infos = LWELayout { n: n_lwe.into(), k: k_lwe_ct.into(), base2k: base2k.into(),

@@ -140,7 +140,7 @@ sk_lwe.fill_binary_block(block_size, &mut source_xs);

sk_lwe.fill_zero(); // GLWE secret - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n_glwe.into(), rank.into()); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe.into(), rank.into()); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); // sk_glwe.fill_zero();

@@ -151,7 +151,7 @@ // Plaintext value to circuit bootstrap

let data: i64 = 1 % (1 << k_lwe_pt); // LWE plaintext - let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_with(base2k.into(), k_lwe_pt.into()); + let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into()); // LWE plaintext(data * 2^{- (k_lwe_pt - 1)}) pt_lwe.encode_i64(data, (k_lwe_pt + 1).into()); // +1 for padding bit

@@ -167,7 +167,7 @@ );

println!("pt_lwe: {pt_lwe}"); // LWE ciphertext - let mut ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos); + let mut ct_lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos); // Encrypt LWE Plaintext ct_lwe.encrypt_sk(&module, &pt_lwe, &sk_lwe, &mut source_xa, &mut source_xe);

@@ -187,7 +187,7 @@ );

println!("CBT-KGEN: {} ms", now.elapsed().as_millis()); // Output GGSW - let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut res: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); // Circuit bootstrapping key prepared (opaque backend dependant write only struct) let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, CGGI, BackendImpl> =

@@ -214,7 +214,7 @@ res.print_noise(&module, &sk_glwe_prepared, &pt_ggsw);

// Tests RLWE(1) * GGSW(data) - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n_glwe.into(), base2k: base2k.into(), k: (k_ggsw_res - base2k).into(),

@@ -222,11 +222,11 @@ rank: rank.into(),

}; // GLWE ciphertext modulus - let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); + let mut ct_glwe: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); // Some GLWE plaintext with signed data let k_glwe_pt: usize = 3; - let mut pt_glwe: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut pt_glwe: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); let mut data_vec: Vec<i64> = vec![0i64; n_glwe]; data_vec .iter_mut()

@@ -249,13 +249,13 @@ scratch.borrow(),

); // Prepare GGSW output of circuit bootstrapping (opaque backend dependant write only struct) - let res_prepared: GGSWCiphertextPrepared<Vec<u8>, BackendImpl> = res.prepare_alloc(&module, scratch.borrow()); + let res_prepared: GGSWPrepared<Vec<u8>, BackendImpl> = res.prepare_alloc(&module, scratch.borrow()); // Apply GLWE x GGSW ct_glwe.external_product_inplace(&module, &res_prepared, scratch.borrow()); // Decrypt - let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); ct_glwe.decrypt(&module, &mut pt_res, &sk_glwe_prepared, scratch.borrow()); println!("pt_res: {:?}", &pt_res.data.at(0, 0)[..64]);
M poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/bdd_2w_to_1w.rs

@@ -1,5 +1,5 @@

use itertools::Itertools; -use poulpy_core::layouts::prepared::GGSWCiphertextPreparedToRef; +use poulpy_core::layouts::prepared::GGSWPreparedToRef; use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; use crate::tfhe::bdd_arithmetic::{

@@ -60,15 +60,11 @@ assert_eq!(b.blocks.len(), T::WORD_SIZE);

} // Collects inputs into a single array - let inputs: Vec<&dyn GGSWCiphertextPreparedToRef<BE>> = a + let inputs: Vec<&dyn GGSWPreparedToRef<BE>> = a .blocks .iter() - .map(|x| x as &dyn GGSWCiphertextPreparedToRef<BE>) - .chain( - b.blocks - .iter() - .map(|x| x as &dyn GGSWCiphertextPreparedToRef<BE>), - ) + .map(|x| x as &dyn GGSWPreparedToRef<BE>) + .chain(b.blocks.iter().map(|x| x as &dyn GGSWPreparedToRef<BE>)) .collect_vec(); // Evaluates out[i] = circuit[i](a, b)
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block.rs

@@ -1,9 +1,9 @@

use std::marker::PhantomData; -use poulpy_core::layouts::{Base2K, GLWECiphertext, GLWEInfos, GLWEPlaintextLayout, LWEInfos, Rank, TorusPrecision}; +use poulpy_core::layouts::{Base2K, GLWE, GLWEInfos, GLWEPlaintextLayout, LWEInfos, Rank, TorusPrecision}; -use poulpy_core::{TakeGLWEPt, layouts::prepared::GLWESecretPrepared}; -use poulpy_hal::api::VecZnxBigAllocBytes; +use poulpy_core::{TakeGLWEPlaintext, layouts::prepared::GLWESecretPrepared}; +use poulpy_hal::api::VecZnxBigBytesOf; #[cfg(test)] use poulpy_hal::api::{ ScratchAvailable, TakeVecZnx, VecZnxAddInplace, VecZnxAddNormal, VecZnxFillUniform, VecZnxNormalize, VecZnxSub,

@@ -12,8 +12,8 @@ #[cfg(test)]

use poulpy_hal::source::Source; use poulpy_hal::{ api::{ - TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, - VecZnxDftApply, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, + TakeVecZnxBig, TakeVecZnxDft, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxDftApply, + VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, }, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, };

@@ -24,7 +24,7 @@ use crate::tfhe::bdd_arithmetic::{FromBits, ToBits, UnsignedInteger};

/// An FHE ciphertext encrypting the bits of an [UnsignedInteger]. pub struct FheUintBlocks<D: Data, T: UnsignedInteger> { - pub(crate) blocks: Vec<GLWECiphertext<D>>, + pub(crate) blocks: Vec<GLWE<D>>, pub(crate) _base: u8, pub(crate) _phantom: PhantomData<T>, }

@@ -38,7 +38,7 @@ fn k(&self) -> poulpy_core::layouts::TorusPrecision {

self.blocks[0].k() } - fn n(&self) -> poulpy_core::layouts::Degree { + fn n(&self) -> poulpy_core::layouts::RingDegree { self.blocks[0].n() } }

@@ -62,7 +62,7 @@ #[allow(dead_code)]

pub(crate) fn alloc_with<BE: Backend>(module: &Module<BE>, base2k: Base2K, k: TorusPrecision, rank: Rank) -> Self { Self { blocks: (0..T::WORD_SIZE) - .map(|_| GLWECiphertext::alloc_with(module.n().into(), base2k, k, rank)) + .map(|_| GLWE::alloc(module.n().into(), base2k, k, rank)) .collect(), _base: 1, _phantom: PhantomData,

@@ -83,7 +83,7 @@ source_xe: &mut Source,

scratch: &mut Scratch<BE>, ) where S: DataRef, - Module<BE>: VecZnxDftAllocBytes + Module<BE>: VecZnxDftBytesOf + VecZnxBigNormalize<BE> + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE>

@@ -96,7 +96,7 @@ + VecZnxNormalizeInplace<BE>

+ VecZnxAddNormal + VecZnxNormalize<BE> + VecZnxSub, - Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPt<BE>, + Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPlaintext<BE>, { use poulpy_core::layouts::GLWEPlaintextLayout;

@@ -136,7 +136,7 @@ + VecZnxIdftApplyConsume<BE>

+ VecZnxBigAddInplace<BE> + VecZnxBigAddSmallInplace<BE> + VecZnxBigNormalize<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPt<BE>, + Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPlaintext<BE>, { #[cfg(debug_assertions)] {

@@ -175,8 +175,8 @@ want: T,

scratch: &mut Scratch<BE>, ) -> Vec<f64> where - Module<BE>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<BE>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE> + VecZnxIdftApplyConsume<BE>

@@ -186,7 +186,7 @@ + VecZnxBigNormalize<BE>

+ VecZnxNormalizeTmpBytes + VecZnxSubInplace + VecZnxNormalizeInplace<BE>, - Scratch<BE>: TakeGLWEPt<BE> + TakeVecZnxDft<BE> + TakeVecZnxBig<BE>, + Scratch<BE>: TakeGLWEPlaintext<BE> + TakeVecZnxDft<BE> + TakeVecZnxBig<BE>, { #[cfg(debug_assertions)] {
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_prepared.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/block_prepared.rs

@@ -1,12 +1,10 @@

use std::marker::PhantomData; -use poulpy_core::layouts::{ - Base2K, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWCiphertextPrepared, -}; +use poulpy_core::layouts::{Base2K, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, prepared::GGSWPrepared}; #[cfg(test)] use poulpy_core::{ TakeGGSW, - layouts::{GGSWCiphertext, prepared::GLWESecretPrepared}, + layouts::{GGSW, prepared::GLWESecretPrepared}, }; use poulpy_hal::{ api::VmpPMatAlloc,

@@ -16,8 +14,8 @@ #[cfg(test)]

use poulpy_hal::{ api::{ ScratchAvailable, SvpApplyDftToDftInplace, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, - VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, + VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigBytesOf, + VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VmpPrepare, },

@@ -29,7 +27,7 @@ use crate::tfhe::bdd_arithmetic::{FheUintBlocks, FheUintPrepare, ToBits, UnsignedInteger};

#[cfg(test)] pub(crate) struct FheUintBlocksPrepDebug<D: Data, T: UnsignedInteger> { - pub(crate) blocks: Vec<GGSWCiphertext<D>>, + pub(crate) blocks: Vec<GGSW<D>>, pub(crate) _base: u8, pub(crate) _phantom: PhantomData<T>, }

@@ -62,7 +60,7 @@ rank: Rank,

) -> Self { Self { blocks: (0..T::WORD_SIZE) - .map(|_| GGSWCiphertext::alloc_with(module.n().into(), base2k, k, rank, dnum, dsize)) + .map(|_| GGSW::alloc(module.n().into(), base2k, k, rank, dnum, dsize)) .collect(), _base: 1, _phantom: PhantomData,

@@ -72,7 +70,7 @@ }

/// A prepared FHE ciphertext encrypting the bits of an [UnsignedInteger]. pub struct FheUintBlocksPrep<D: Data, B: Backend, T: UnsignedInteger> { - pub(crate) blocks: Vec<GGSWCiphertextPrepared<D, B>>, + pub(crate) blocks: Vec<GGSWPrepared<D, B>>, pub(crate) _base: u8, pub(crate) _phantom: PhantomData<T>, }

@@ -103,7 +101,7 @@ Module<BE>: VmpPMatAlloc<BE>,

{ Self { blocks: (0..T::WORD_SIZE) - .map(|_| GGSWCiphertextPrepared::alloc_with(module, base2k, k, dnum, dsize, rank)) + .map(|_| GGSWPrepared::alloc(module, base2k, k, dnum, dsize, rank)) .collect(), _base: 1, _phantom: PhantomData,

@@ -125,7 +123,7 @@ scratch: &mut Scratch<BE>,

) where S: DataRef, Module<BE>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<BE> + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE>

@@ -192,8 +190,8 @@ impl<D: DataRef, T: UnsignedInteger + ToBits> FheUintBlocksPrepDebug<D, T> {

#[allow(dead_code)] pub(crate) fn noise<S: DataRef, BE: Backend>(&self, module: &Module<BE>, sk: &GLWESecretPrepared<S, BE>, want: T) where - Module<BE>: VecZnxDftAllocBytes - + VecZnxBigAllocBytes + Module<BE>: VecZnxDftBytesOf + + VecZnxBigBytesOf + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE> + VecZnxIdftApplyConsume<BE>

@@ -227,7 +225,7 @@ fn k(&self) -> poulpy_core::layouts::TorusPrecision {

self.blocks[0].k() } - fn n(&self) -> poulpy_core::layouts::Degree { + fn n(&self) -> poulpy_core::layouts::RingDegree { self.blocks[0].n() } }

@@ -258,7 +256,7 @@ fn k(&self) -> poulpy_core::layouts::TorusPrecision {

self.blocks[0].k() } - fn n(&self) -> poulpy_core::layouts::Degree { + fn n(&self) -> poulpy_core::layouts::RingDegree { self.blocks[0].n() } }
M poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/word.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/ciphertexts/word.rs

@@ -1,9 +1,9 @@

use itertools::Itertools; use poulpy_core::{ - GLWEOperations, TakeGLWECtSlice, TakeGLWEPt, glwe_packing, + GLWEOperations, TakeGLWEPlaintext, TakeGLWESlice, glwe_packing, layouts::{ - GLWECiphertext, GLWEInfos, GLWEPlaintextLayout, LWEInfos, TorusPrecision, - prepared::{GGLWEAutomorphismKeyPrepared, GLWESecretPrepared}, + GLWE, GLWEInfos, GLWEPlaintextLayout, LWEInfos, TorusPrecision, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared}, }, }; use poulpy_hal::{

@@ -11,7 +11,7 @@ api::{

ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphismInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,

@@ -24,22 +24,22 @@

use crate::tfhe::bdd_arithmetic::{FromBits, ToBits, UnsignedInteger}; /// A FHE ciphertext encrypting a [UnsignedInteger]. -pub struct FheUintWord<D: Data, T: UnsignedInteger>(pub(crate) GLWECiphertext<D>, pub(crate) PhantomData<T>); +pub struct FheUintWord<D: Data, T: UnsignedInteger>(pub(crate) GLWE<D>, pub(crate) PhantomData<T>); impl<D: DataMut, T: UnsignedInteger> FheUintWord<D, T> { #[allow(dead_code)] fn post_process<ATK, BE: Backend>( &mut self, module: &Module<BE>, - mut tmp_res: Vec<GLWECiphertext<&mut [u8]>>, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<ATK, BE>>, + mut tmp_res: Vec<GLWE<&mut [u8]>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<ATK, BE>>, scratch: &mut Scratch<BE>, ) where ATK: DataRef, Module<BE>: VecZnxSub + VecZnxCopy + VecZnxNegateInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxAddInplace + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes

@@ -62,12 +62,12 @@ + VecZnxBigAddSmallInplace<BE>

+ VecZnxAutomorphismInplace<BE> + VecZnxBigSubSmallNegateInplace<BE> + VecZnxRotate, - Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWECtSlice, + Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWESlice, { // Repacks the GLWE ciphertexts bits let gap: usize = module.n() / T::WORD_SIZE; let log_gap: usize = (usize::BITS - (gap - 1).leading_zeros()) as usize; - let mut cts: HashMap<usize, &mut GLWECiphertext<&mut [u8]>> = HashMap::new(); + let mut cts: HashMap<usize, &mut GLWE<&mut [u8]>> = HashMap::new(); for (i, ct) in tmp_res.iter_mut().enumerate().take(T::WORD_SIZE) { cts.insert(i * gap, ct); }

@@ -87,7 +87,7 @@ fn k(&self) -> poulpy_core::layouts::TorusPrecision {

self.0.k() } - fn n(&self) -> poulpy_core::layouts::Degree { + fn n(&self) -> poulpy_core::layouts::RingDegree { self.0.n() } }

@@ -109,7 +109,7 @@ source_xe: &mut Source,

scratch: &mut Scratch<BE>, ) where Module<BE>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<BE> + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE>

@@ -122,7 +122,7 @@ + VecZnxNormalizeInplace<BE>

+ VecZnxAddNormal + VecZnxNormalize<BE> + VecZnxSub, - Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPt<BE>, + Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGLWEPlaintext<BE>, { #[cfg(debug_assertions)] {

@@ -167,7 +167,7 @@ + VecZnxIdftApplyConsume<BE>

+ VecZnxBigAddInplace<BE> + VecZnxBigAddSmallInplace<BE> + VecZnxBigNormalize<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPt<BE>, + Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPlaintext<BE>, { #[cfg(debug_assertions)] {
M poulpy-schemes/src/tfhe/bdd_arithmetic/eval.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/eval.rs

@@ -1,9 +1,9 @@

use itertools::Itertools; use poulpy_core::{ - GLWEExternalProductInplace, GLWEOperations, TakeGLWECtSlice, + GLWEExternalProductInplace, GLWEOperations, TakeGLWESlice, layouts::{ - GLWECiphertext, GLWECiphertextToMut, LWEInfos, - prepared::{GGSWCiphertextPrepared, GGSWCiphertextPreparedToRef}, + GLWE, GLWEToMut, LWEInfos, + prepared::{GGSWPrepared, GGSWPreparedToRef}, }, }; use poulpy_hal::{

@@ -38,8 +38,8 @@ {

fn execute<O>( &self, module: &Module<BE>, - out: &mut [GLWECiphertext<O>], - inputs: &[&dyn GGSWCiphertextPreparedToRef<BE>], + out: &mut [GLWE<O>], + inputs: &[&dyn GGSWPreparedToRef<BE>], scratch: &mut Scratch<BE>, ) where O: DataMut;

@@ -49,13 +49,13 @@ impl<C: BitCircuitInfo, const N: usize, T: UnsignedInteger, BE: Backend> CircuitExecute<BE, T> for Circuit<C, N>

where Self: GetBitCircuitInfo<T>, Module<BE>: Cmux<BE> + VecZnxCopy, - Scratch<BE>: TakeGLWECtSlice, + Scratch<BE>: TakeGLWESlice, { fn execute<O>( &self, module: &Module<BE>, - out: &mut [GLWECiphertext<O>], - inputs: &[&dyn GGSWCiphertextPreparedToRef<BE>], + out: &mut [GLWE<O>], + inputs: &[&dyn GGSWPreparedToRef<BE>], scratch: &mut Scratch<BE>, ) where O: DataMut,

@@ -159,14 +159,8 @@ }

} pub trait Cmux<BE: Backend> { - fn cmux<O, T, F, S>( - &self, - out: &mut GLWECiphertext<O>, - t: &GLWECiphertext<T>, - f: &GLWECiphertext<F>, - s: &GGSWCiphertextPrepared<S, BE>, - scratch: &mut Scratch<BE>, - ) where + fn cmux<O, T, F, S>(&self, out: &mut GLWE<O>, t: &GLWE<T>, f: &GLWE<F>, s: &GGSWPrepared<S, BE>, scratch: &mut Scratch<BE>) + where O: DataMut, T: DataRef, F: DataRef,

@@ -177,14 +171,8 @@ impl<BE: Backend> Cmux<BE> for Module<BE>

where Module<BE>: GLWEExternalProductInplace<BE> + VecZnxSub + VecZnxCopy + VecZnxNegateInplace + VecZnxAddInplace, { - fn cmux<O, T, F, S>( - &self, - out: &mut GLWECiphertext<O>, - t: &GLWECiphertext<T>, - f: &GLWECiphertext<F>, - s: &GGSWCiphertextPrepared<S, BE>, - scratch: &mut Scratch<BE>, - ) where + fn cmux<O, T, F, S>(&self, out: &mut GLWE<O>, t: &GLWE<T>, f: &GLWE<F>, s: &GGSWPrepared<S, BE>, scratch: &mut Scratch<BE>) + where O: DataMut, T: DataRef, F: DataRef,
M poulpy-schemes/src/tfhe/bdd_arithmetic/key.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/key.rs

@@ -9,18 +9,18 @@ CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute,

}, }; use poulpy_core::{ - TakeGGSW, TakeGLWECt, + TakeGGSW, TakeGLWE, layouts::{ - GLWESecret, GLWEToLWEKey, GLWEToLWEKeyLayout, LWECiphertext, LWESecret, + GLWESecret, GLWEToLWEKeyLayout, GLWEToLWESwitchingKey, LWE, LWESecret, prepared::{GLWEToLWESwitchingKeyPrepared, Prepare, PrepareAlloc}, }, }; use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, + ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPrepare, },

@@ -56,7 +56,7 @@ LWE: Data,

BRA: BlindRotationAlgo, { cbt: CircuitBootstrappingKey<CBT, BRA>, - ks: GLWEToLWEKey<LWE>, + ks: GLWEToLWESwitchingKey<LWE>, } impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, Vec<u8>, BRA> {

@@ -77,7 +77,7 @@ BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>,

Module<BE>: SvpApplyDftToDft<BE> + VecZnxIdftApplyTmpA<BE> + VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<BE> + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE>

@@ -92,13 +92,13 @@ + VecZnxNormalize<BE>

+ VecZnxSub + SvpPrepare<BE> + VecZnxSwitchRing - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<BE> + VecZnxAutomorphism + VecZnxAutomorphismInplace<BE>, Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol<BE> + TakeVecZnxBig<BE>, { - let mut ks: GLWEToLWEKey<Vec<u8>> = GLWEToLWEKey::alloc(&infos.ks_infos()); + let mut ks: GLWEToLWESwitchingKey<Vec<u8>> = GLWEToLWESwitchingKey::alloc(&infos.ks_infos()); ks.encrypt_sk(module, sk_lwe, sk_glwe, source_xa, source_xe, scratch); Self {

@@ -131,7 +131,7 @@ impl<CBT: DataMut, LWE: DataMut, BRA: BlindRotationAlgo, BE: Backend> PrepareAlloc<BE, BDDKeyPrepared<CBT, LWE, BRA, BE>>

for BDDKey<CBT, LWE, BRA> where CircuitBootstrappingKey<CBT, BRA>: PrepareAlloc<BE, CircuitBootstrappingKeyPrepared<CBT, BRA, BE>>, - GLWEToLWEKey<LWE>: PrepareAlloc<BE, GLWEToLWESwitchingKeyPrepared<LWE, BE>>, + GLWEToLWESwitchingKey<LWE>: PrepareAlloc<BE, GLWEToLWESwitchingKeyPrepared<LWE, BE>>, { fn prepare_alloc(&self, module: &Module<BE>, scratch: &mut Scratch<BE>) -> BDDKeyPrepared<CBT, LWE, BRA, BE> { BDDKeyPrepared {

@@ -157,7 +157,7 @@ BRA: BlindRotationAlgo,

BE: Backend, Module<BE>: VmpPrepare<BE> + VecZnxRotate - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<BE>

@@ -168,7 +168,7 @@ + VecZnxBigAddSmallInplace<BE>

+ VecZnxBigNormalize<BE> + VecZnxNormalize<BE> + VecZnxNormalizeTmpBytes, - Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWECt + TakeVecZnx + TakeGGSW, + Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWE + TakeVecZnx + TakeGGSW, CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>, { fn prepare(

@@ -182,7 +182,7 @@ #[cfg(debug_assertions)]

{ assert_eq!(out.blocks.len(), bits.blocks.len()); } - let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&bits.blocks[0]); //TODO: add TakeLWE + let mut lwe: LWE<Vec<u8>> = LWE::alloc(&bits.blocks[0]); //TODO: add TakeLWE let (mut tmp_ggsw, scratch_1) = scratch.take_ggsw(out); for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) { lwe.from_glwe(module, src, &self.ks, scratch_1);

@@ -206,7 +206,7 @@ BRA: BlindRotationAlgo,

BE: Backend, Module<BE>: VmpPrepare<BE> + VecZnxRotate - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<BE>

@@ -217,7 +217,7 @@ + VecZnxBigAddSmallInplace<BE>

+ VecZnxBigNormalize<BE> + VecZnxNormalize<BE> + VecZnxNormalizeTmpBytes, - Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWECt + TakeVecZnx + TakeGGSW, + Scratch<BE>: ScratchAvailable + TakeVecZnxDft<BE> + TakeGLWE + TakeVecZnx + TakeGGSW, CircuitBootstrappingKeyPrepared<CBT, BRA, BE>: CirtuitBootstrappingExecute<BE>, { fn prepare(

@@ -231,7 +231,7 @@ #[cfg(debug_assertions)]

{ assert_eq!(out.blocks.len(), bits.blocks.len()); } - let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&bits.blocks[0]); //TODO: add TakeLWE + let mut lwe: LWE<Vec<u8>> = LWE::alloc(&bits.blocks[0]); //TODO: add TakeLWE for (dst, src) in out.blocks.iter_mut().zip(bits.blocks.iter()) { lwe.from_glwe(module, src, &self.ks, scratch); self.cbt
M poulpy-schemes/src/tfhe/bdd_arithmetic/parameters.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/parameters.rs

@@ -1,7 +1,7 @@

#[cfg(test)] use poulpy_core::layouts::{ - Base2K, Degree, Dnum, Dsize, GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertextLayout, GLWECiphertextLayout, - GLWEToLWEKeyLayout, Rank, TorusPrecision, + AutomorphismKeyLayout, Base2K, Dnum, Dsize, GGSWLayout, GLWELayout, GLWEToLWEKeyLayout, Rank, RingDegree, TensorKeyLayout, + TorusPrecision, }; #[cfg(test)]

@@ -25,16 +25,16 @@ #[cfg(test)]

pub(crate) const TEST_RANK: u32 = 2; #[cfg(test)] -pub(crate) static TEST_GLWE_INFOS: GLWECiphertextLayout = GLWECiphertextLayout { - n: Degree(TEST_N_GLWE), +pub(crate) static TEST_GLWE_INFOS: GLWELayout = GLWELayout { + n: RingDegree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(TEST_K_GLWE), rank: Rank(TEST_RANK), }; #[cfg(test)] -pub(crate) static TEST_GGSW_INFOS: GGSWCiphertextLayout = GGSWCiphertextLayout { - n: Degree(TEST_N_GLWE), +pub(crate) static TEST_GGSW_INFOS: GGSWLayout = GGSWLayout { + n: RingDegree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(TEST_K_GGSW), rank: Rank(TEST_RANK),

@@ -46,23 +46,23 @@ #[cfg(test)]

pub(crate) static TEST_BDD_KEY_LAYOUT: BDDKeyLayout = BDDKeyLayout { cbt: CircuitBootstrappingKeyLayout { layout_brk: BlindRotationKeyLayout { - n_glwe: Degree(TEST_N_GLWE), - n_lwe: Degree(TEST_N_LWE), + n_glwe: RingDegree(TEST_N_GLWE), + n_lwe: RingDegree(TEST_N_LWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(52), dnum: Dnum(3), rank: Rank(TEST_RANK), }, - layout_atk: GGLWEAutomorphismKeyLayout { - n: Degree(TEST_N_GLWE), + layout_atk: AutomorphismKeyLayout { + n: RingDegree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(52), rank: Rank(TEST_RANK), dnum: Dnum(3), dsize: Dsize(1), }, - layout_tsk: GGLWETensorKeyLayout { - n: Degree(TEST_N_GLWE), + layout_tsk: TensorKeyLayout { + n: RingDegree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(52), rank: Rank(TEST_RANK),

@@ -71,7 +71,7 @@ dsize: Dsize(1),

}, }, ks: GLWEToLWEKeyLayout { - n: Degree(TEST_N_GLWE), + n: RingDegree(TEST_N_GLWE), base2k: Base2K(TEST_BASE2K), k: TorusPrecision(39), rank_in: Rank(TEST_RANK),
M poulpy-schemes/src/tfhe/bdd_arithmetic/test.rs → poulpy-schemes/src/tfhe/bdd_arithmetic/test.rs

@@ -2,20 +2,20 @@ use std::time::Instant;

use poulpy_backend::FFT64Ref; use poulpy_core::{ - TakeGGSW, TakeGLWEPt, + TakeGGSW, TakeGLWEPlaintext, layouts::{ - GGSWCiphertextLayout, GLWECiphertextLayout, GLWESecret, LWEInfos, LWESecret, + GGSWLayout, GLWELayout, GLWESecret, LWEInfos, LWESecret, prepared::{GLWESecretPrepared, PrepareAlloc}, }, }; use poulpy_hal::{ api::{ ModuleNew, ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, - SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeSlice, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, + SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, TakeScalarZnx, TakeSlice, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAutomorphismInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftAddInplace, - VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform,

@@ -51,7 +51,7 @@ where

Module<BE>: ModuleNew<BE> + SvpPPolAlloc<BE> + SvpPrepare<BE> + VmpPMatAlloc<BE>, ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>, Module<BE>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<BE> + VecZnxDftApply<BE> + SvpApplyDftToDftInplace<BE>

@@ -68,16 +68,16 @@ + VmpPrepare<BE>,

Scratch<BE>: TakeVecZnxDft<BE> + ScratchAvailable + TakeVecZnx + TakeGGSW + TakeScalarZnx + TakeSlice, Module<BE>: VecZnxCopy + VecZnxNegateInplace + VmpApplyDftToDftTmpBytes + VmpApplyDftToDft<BE> + VmpApplyDftToDftAdd<BE>, Module<BE>: VecZnxBigAddInplace<BE> + VecZnxBigAddSmallInplace<BE> + VecZnxBigNormalize<BE>, - Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPt<BE>, + Scratch<BE>: TakeVecZnxDft<BE> + TakeVecZnxBig<BE> + TakeGLWEPlaintext<BE>, Module<BE>: VecZnxAutomorphism + VecZnxSwitchRing - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxIdftApplyTmpA<BE> + SvpApplyDftToDft<BE> + VecZnxBigAlloc<BE> + VecZnxDftAlloc<BE> + VecZnxBigNormalizeTmpBytes - + SvpPPolAllocBytes + + SvpPPolBytesOf + VecZnxRotateInplace<BE> + VecZnxBigAutomorphismInplace<BE> + VecZnxRshInplace<BE>

@@ -85,7 +85,7 @@ + VecZnxDftCopy<BE>

+ VecZnxAutomorphismInplace<BE> + VecZnxBigSubSmallNegateInplace<BE> + VecZnxRotateInplaceTmpBytes - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<BE> + VecZnxRotate + ZnFillUniform

@@ -107,8 +107,8 @@ BlindRotationKey<Vec<u8>, BRA>: PrepareAlloc<BE, BlindRotationKeyPrepared<Vec<u8>, BRA, BE>>,

BlindRotationKeyPrepared<Vec<u8>, BRA, BE>: BlincRotationExecute<BE>, BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<BE>, { - let glwe_infos: GLWECiphertextLayout = TEST_GLWE_INFOS; - let ggsw_infos: GGSWCiphertextLayout = TEST_GGSW_INFOS; + let glwe_infos: GLWELayout = TEST_GLWE_INFOS; + let ggsw_infos: GGSWLayout = TEST_GGSW_INFOS; let n_glwe: usize = glwe_infos.n().into();

@@ -120,7 +120,7 @@ let mut source_xe: Source = Source::new([3u8; 32]);

let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(1 << 22); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); let sk_glwe_prep: GLWESecretPrepared<Vec<u8>, BE> = sk_glwe.prepare_alloc(&module, scratch.borrow());
M poulpy-schemes/src/tfhe/blind_rotation/cggi_algo.rs → poulpy-schemes/src/tfhe/blind_rotation/cggi_algo.rs

@@ -1,9 +1,9 @@

use itertools::izip; use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDft, SvpPPolAllocBytes, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, - TakeVecZnxSlice, VecZnxAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigNormalize, - VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftAllocBytes, VecZnxDftApply, + ScratchAvailable, SvpApplyDftToDft, SvpPPolBytesOf, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, + TakeVecZnxSlice, VecZnxAddInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, + VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftSubInplace, VecZnxDftZero, VecZnxIdftApply, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes, VecZnxMulXpMinusOneInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxSubInplace, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,

@@ -12,8 +12,8 @@ layouts::{Backend, DataMut, DataRef, Module, Scratch, SvpPPol, VecZnx, ZnxView, ZnxZero},

}; use poulpy_core::{ - Distribution, GLWEOperations, TakeGLWECt, - layouts::{GGSWInfos, GLWECiphertext, GLWECiphertextToMut, GLWEInfos, LWECiphertext, LWECiphertextToRef, LWEInfos}, + Distribution, GLWEOperations, TakeGLWE, + layouts::{GGSWInfos, GLWE, GLWEInfos, GLWEToMut, LWE, LWEInfos, LWEToRef}, }; use crate::tfhe::blind_rotation::{

@@ -21,7 +21,7 @@ BlincRotationExecute, BlindRotationKeyInfos, BlindRotationKeyPrepared, CGGI, LookUpTable, LookUpTableRotationDirection,

}; #[allow(clippy::too_many_arguments)] -pub fn cggi_blind_rotate_scratch_space<B: Backend, OUT, GGSW>( +pub fn cggi_blind_rotate_tmp_bytes<B: Backend, OUT, GGSW>( module: &Module<B>, block_size: usize, extension_factor: usize,

@@ -31,10 +31,10 @@ ) -> usize

where OUT: GLWEInfos, GGSW: GGSWInfos, - Module<B>: VecZnxDftAllocBytes + Module<B>: VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxNormalizeTmpBytes - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxIdftApplyTmpBytes + VecZnxBigNormalizeTmpBytes, {

@@ -43,14 +43,14 @@

if block_size > 1 { let cols: usize = (brk_infos.rank() + 1).into(); let dnum: usize = brk_infos.dnum().into(); - let acc_dft: usize = module.vec_znx_dft_alloc_bytes(cols, dnum) * extension_factor; - let acc_big: usize = module.vec_znx_big_alloc_bytes(1, brk_size); - let vmp_res: usize = module.vec_znx_dft_alloc_bytes(cols, brk_size) * extension_factor; - let vmp_xai: usize = module.vec_znx_dft_alloc_bytes(1, brk_size); + let acc_dft: usize = module.bytes_of_vec_znx_dft(cols, dnum) * extension_factor; + let acc_big: usize = module.bytes_of_vec_znx_big(1, brk_size); + let vmp_res: usize = module.bytes_of_vec_znx_dft(cols, brk_size) * extension_factor; + let vmp_xai: usize = module.bytes_of_vec_znx_dft(1, brk_size); let acc_dft_add: usize = vmp_res; let vmp: usize = module.vmp_apply_dft_to_dft_tmp_bytes(brk_size, dnum, dnum, 2, 2, brk_size); // GGSW product: (1 x 2) x (2 x 2) let acc: usize = if extension_factor > 1 { - VecZnx::alloc_bytes(module.n(), cols, glwe_infos.size()) * extension_factor + VecZnx::bytes_of(module.n(), cols, glwe_infos.size()) * extension_factor } else { 0 };

@@ -61,16 +61,15 @@ + vmp_res

+ vmp_xai + (vmp | (acc_big + (module.vec_znx_big_normalize_tmp_bytes() | module.vec_znx_idft_apply_tmp_bytes()))) } else { - GLWECiphertext::alloc_bytes(glwe_infos) - + GLWECiphertext::external_product_inplace_scratch_space(module, glwe_infos, brk_infos) + GLWE::bytes_of(glwe_infos) + GLWE::external_product_inplace_tmp_bytes(module, glwe_infos, brk_infos) } } impl<D: DataRef, B: Backend> BlincRotationExecute<B> for BlindRotationKeyPrepared<D, CGGI, B> where - Module<B>: VecZnxBigAllocBytes - + VecZnxDftAllocBytes - + SvpPPolAllocBytes + Module<B>: VecZnxBigBytesOf + + VecZnxDftBytesOf + + SvpPPolBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpBytes

@@ -99,8 +98,8 @@ {

fn execute<DR: DataMut, DI: DataRef>( &self, module: &Module<B>, - res: &mut GLWECiphertext<DR>, - lwe: &LWECiphertext<DI>, + res: &mut GLWE<DR>, + lwe: &LWE<DI>, lut: &LookUpTable, scratch: &mut Scratch<B>, ) {

@@ -121,8 +120,8 @@ }

fn execute_block_binary_extended<DataRes, DataIn, DataBrk, B: Backend>( module: &Module<B>, - res: &mut GLWECiphertext<DataRes>, - lwe: &LWECiphertext<DataIn>, + res: &mut GLWE<DataRes>, + lwe: &LWE<DataIn>, lut: &LookUpTable, brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>, scratch: &mut Scratch<B>,

@@ -130,9 +129,9 @@ ) where

DataRes: DataMut, DataIn: DataRef, DataBrk: DataRef, - Module<B>: VecZnxBigAllocBytes - + VecZnxDftAllocBytes - + SvpPPolAllocBytes + Module<B>: VecZnxBigBytesOf + + VecZnxDftBytesOf + + SvpPPolBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpBytes

@@ -179,7 +178,7 @@ panic!("invalid key: x_pow_a has not been initialized")

} let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).as_usize()]; // TODO: from scratch space - let lwe_ref: LWECiphertext<&[u8]> = lwe.to_ref(); + let lwe_ref: LWE<&[u8]> = lwe.to_ref(); let two_n: usize = 2 * n_glwe; let two_n_ext: usize = 2 * lut.domain_size();

@@ -288,8 +287,8 @@ }

fn execute_block_binary<DataRes, DataIn, DataBrk, B: Backend>( module: &Module<B>, - res: &mut GLWECiphertext<DataRes>, - lwe: &LWECiphertext<DataIn>, + res: &mut GLWE<DataRes>, + lwe: &LWE<DataIn>, lut: &LookUpTable, brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>, scratch: &mut Scratch<B>,

@@ -297,9 +296,9 @@ ) where

DataRes: DataMut, DataIn: DataRef, DataBrk: DataRef, - Module<B>: VecZnxBigAllocBytes - + VecZnxDftAllocBytes - + SvpPPolAllocBytes + Module<B>: VecZnxBigBytesOf + + VecZnxDftBytesOf + + SvpPPolBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpBytes

@@ -324,8 +323,8 @@ Scratch<B>: TakeVecZnxDftSlice<B> + TakeVecZnxDft<B> + TakeVecZnxBig<B> + TakeVecZnxSlice + ScratchAvailable + TakeVecZnx,

{ let n_glwe: usize = brk.n_glwe().into(); let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).into()]; // TODO: from scratch space - let mut out_mut: GLWECiphertext<&mut [u8]> = res.to_mut(); - let lwe_ref: LWECiphertext<&[u8]> = lwe.to_ref(); + let mut out_mut: GLWE<&mut [u8]> = res.to_mut(); + let lwe_ref: LWE<&[u8]> = lwe.to_ref(); let two_n: usize = n_glwe << 1; let base2k: usize = brk.base2k().into(); let dnum: usize = brk.dnum().into();

@@ -410,8 +409,8 @@ }

fn execute_standard<DataRes, DataIn, DataBrk, B: Backend>( module: &Module<B>, - res: &mut GLWECiphertext<DataRes>, - lwe: &LWECiphertext<DataIn>, + res: &mut GLWE<DataRes>, + lwe: &LWE<DataIn>, lut: &LookUpTable, brk: &BlindRotationKeyPrepared<DataBrk, CGGI, B>, scratch: &mut Scratch<B>,

@@ -419,9 +418,9 @@ ) where

DataRes: DataMut, DataIn: DataRef, DataBrk: DataRef, - Module<B>: VecZnxBigAllocBytes - + VecZnxDftAllocBytes - + SvpPPolAllocBytes + Module<B>: VecZnxBigBytesOf + + VecZnxDftBytesOf + + SvpPPolBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpBytes

@@ -480,8 +479,8 @@ );

} let mut lwe_2n: Vec<i64> = vec![0i64; (lwe.n() + 1).into()]; // TODO: from scratch space - let mut out_mut: GLWECiphertext<&mut [u8]> = res.to_mut(); - let lwe_ref: LWECiphertext<&[u8]> = lwe.to_ref(); + let mut out_mut: GLWE<&mut [u8]> = res.to_mut(); + let lwe_ref: LWE<&[u8]> = lwe.to_ref(); mod_switch_2n( 2 * lut.domain_size(),

@@ -519,7 +518,7 @@ // on top of each others, thus ~ 2^{63-base2k} additions are supported before overflow.

out_mut.normalize_inplace(module, scratch_1); } -pub fn mod_switch_2n(n: usize, res: &mut [i64], lwe: &LWECiphertext<&[u8]>, rot_dir: LookUpTableRotationDirection) { +pub fn mod_switch_2n(n: usize, res: &mut [i64], lwe: &LWE<&[u8]>, rot_dir: LookUpTableRotationDirection) { let base2k: usize = lwe.base2k().into(); let log2n: usize = usize::BITS as usize - (n - 1).leading_zeros() as usize + 1;
M poulpy-schemes/src/tfhe/blind_rotation/cggi_key.rs → poulpy-schemes/src/tfhe/blind_rotation/cggi_key.rs

@@ -1,9 +1,8 @@

use poulpy_hal::{ api::{ ScratchAvailable, SvpApplyDftToDftInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, - VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, - VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, - VmpPMatAlloc, VmpPrepare, + VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VmpPMatAlloc, VmpPrepare, }, layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut}, source::Source,

@@ -14,9 +13,9 @@

use poulpy_core::{ Distribution, layouts::{ - GGSWCiphertext, GGSWInfos, LWESecret, - compressed::GGSWCiphertextCompressed, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared}, + GGSW, GGSWInfos, LWESecret, + compressed::GGSWCompressed, + prepared::{GGSWPrepared, GLWESecretPrepared}, }, };

@@ -30,9 +29,9 @@ fn alloc<A>(infos: &A) -> Self

where A: BlindRotationKeyInfos, { - let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into()); + let mut data: Vec<GGSW<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into()); for _ in 0..infos.n_lwe().as_usize() { - data.push(GGSWCiphertext::alloc(infos)); + data.push(GGSW::alloc_from_infos(infos)); } Self {

@@ -44,19 +43,19 @@ }

} impl BlindRotationKey<Vec<u8>, CGGI> { - pub fn generate_from_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize + pub fn generate_from_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGSWInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { - GGSWCiphertext::encrypt_sk_scratch_space(module, infos) + GGSW::encrypt_sk_tmp_bytes(module, infos) } } impl<D: DataMut, B: Backend> BlindRotationKeyEncryptSk<B> for BlindRotationKey<D, CGGI> where Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -121,8 +120,8 @@ fn alloc<A>(module: &Module<B>, infos: &A) -> Self

where A: BlindRotationKeyInfos, { - let mut data: Vec<GGSWCiphertextPrepared<Vec<u8>, B>> = Vec::with_capacity(infos.n_lwe().into()); - (0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCiphertextPrepared::alloc(module, infos))); + let mut data: Vec<GGSWPrepared<Vec<u8>, B>> = Vec::with_capacity(infos.n_lwe().into()); + (0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWPrepared::alloc_from_infos(module, infos))); Self { data, dist: Distribution::NONE,

@@ -137,8 +136,8 @@ pub fn alloc<A>(infos: &A) -> Self

where A: BlindRotationKeyInfos, { - let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into()); - (0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCiphertextCompressed::alloc(infos))); + let mut data: Vec<GGSWCompressed<Vec<u8>>> = Vec::with_capacity(infos.n_lwe().into()); + (0..infos.n_lwe().as_usize()).for_each(|_| data.push(GGSWCompressed::alloc_from_infos(infos))); Self { keys: data, dist: Distribution::NONE,

@@ -146,12 +145,12 @@ _phantom: PhantomData,

} } - pub fn generate_from_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize + pub fn generate_from_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize where A: GGSWInfos, - Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes, + Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, { - GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, infos) + GGSWCompressed::encrypt_sk_tmp_bytes(module, infos) } }

@@ -169,7 +168,7 @@ ) where

DataSkGLWE: DataRef, DataSkLWE: DataRef, Module<B>: VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>
M poulpy-schemes/src/tfhe/blind_rotation/key.rs → poulpy-schemes/src/tfhe/blind_rotation/key.rs

@@ -8,7 +8,7 @@

use poulpy_core::{ Distribution, layouts::{ - Base2K, Degree, Dnum, Dsize, GGSWCiphertext, GGSWInfos, GLWEInfos, LWEInfos, LWESecret, Rank, TorusPrecision, + Base2K, Dnum, Dsize, GGSW, GGSWInfos, GLWEInfos, LWEInfos, LWESecret, Rank, RingDegree, TorusPrecision, prepared::GLWESecretPrepared, }, };

@@ -19,8 +19,8 @@ use crate::tfhe::blind_rotation::BlindRotationAlgo;

#[derive(PartialEq, Eq, Copy, Clone, Debug)] pub struct BlindRotationKeyLayout { - pub n_glwe: Degree, - pub n_lwe: Degree, + pub n_glwe: RingDegree, + pub n_lwe: RingDegree, pub base2k: Base2K, pub k: TorusPrecision, pub dnum: Dnum,

@@ -28,11 +28,11 @@ pub rank: Rank,

} impl BlindRotationKeyInfos for BlindRotationKeyLayout { - fn n_glwe(&self) -> Degree { + fn n_glwe(&self) -> RingDegree { self.n_glwe } - fn n_lwe(&self) -> Degree { + fn n_lwe(&self) -> RingDegree { self.n_lwe } }

@@ -62,7 +62,7 @@ fn k(&self) -> TorusPrecision {

self.k } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.n_glwe } }

@@ -71,8 +71,8 @@ pub trait BlindRotationKeyInfos

where Self: GGSWInfos, { - fn n_glwe(&self) -> Degree; - fn n_lwe(&self) -> Degree; + fn n_glwe(&self) -> RingDegree; + fn n_lwe(&self) -> RingDegree; } pub trait BlindRotationKeyAlloc {

@@ -98,7 +98,7 @@ }

#[derive(Clone)] pub struct BlindRotationKey<D: Data, BRT: BlindRotationAlgo> { - pub(crate) keys: Vec<GGSWCiphertext<D>>, + pub(crate) keys: Vec<GGSW<D>>, pub(crate) dist: Distribution, pub(crate) _phantom: PhantomData<BRT>, }

@@ -178,12 +178,12 @@ }

} impl<D: DataRef, BRT: BlindRotationAlgo> BlindRotationKeyInfos for BlindRotationKey<D, BRT> { - fn n_glwe(&self) -> Degree { + fn n_glwe(&self) -> RingDegree { self.n() } - fn n_lwe(&self) -> Degree { - Degree(self.keys.len() as u32) + fn n_lwe(&self) -> RingDegree { + RingDegree(self.keys.len() as u32) } }

@@ -206,7 +206,7 @@ fn k(&self) -> TorusPrecision {

self.keys[0].k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.keys[0].n() }
M poulpy-schemes/src/tfhe/blind_rotation/key_compressed.rs → poulpy-schemes/src/tfhe/blind_rotation/key_compressed.rs

@@ -8,14 +8,14 @@

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use poulpy_core::{ Distribution, - layouts::{Base2K, Degree, Dsize, GGSWInfos, GLWEInfos, LWEInfos, TorusPrecision, compressed::GGSWCiphertextCompressed}, + layouts::{Base2K, Dsize, GGSWInfos, GLWEInfos, LWEInfos, RingDegree, TorusPrecision, compressed::GGSWCompressed}, }; use crate::tfhe::blind_rotation::{BlindRotationAlgo, BlindRotationKeyInfos}; #[derive(Clone)] pub struct BlindRotationKeyCompressed<D: Data, BRT: BlindRotationAlgo> { - pub(crate) keys: Vec<GGSWCiphertextCompressed<D>>, + pub(crate) keys: Vec<GGSWCompressed<D>>, pub(crate) dist: Distribution, pub(crate) _phantom: PhantomData<BRT>, }

@@ -94,17 +94,17 @@ }

} impl<D: DataRef, BRA: BlindRotationAlgo> BlindRotationKeyInfos for BlindRotationKeyCompressed<D, BRA> { - fn n_glwe(&self) -> Degree { + fn n_glwe(&self) -> RingDegree { self.n() } - fn n_lwe(&self) -> Degree { - Degree(self.keys.len() as u32) + fn n_lwe(&self) -> RingDegree { + RingDegree(self.keys.len() as u32) } } impl<D: DataRef, BRA: BlindRotationAlgo> LWEInfos for BlindRotationKeyCompressed<D, BRA> { - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.keys[0].n() }
M poulpy-schemes/src/tfhe/blind_rotation/key_prepared.rs → poulpy-schemes/src/tfhe/blind_rotation/key_prepared.rs

@@ -8,8 +8,8 @@

use poulpy_core::{ Distribution, layouts::{ - Base2K, Degree, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, TorusPrecision, - prepared::{GGSWCiphertextPrepared, Prepare, PrepareAlloc}, + Base2K, Dnum, Dsize, GGSWInfos, GLWEInfos, LWEInfos, Rank, RingDegree, TorusPrecision, + prepared::{GGSWPrepared, Prepare, PrepareAlloc}, }, };

@@ -23,19 +23,19 @@ }

#[derive(PartialEq, Eq)] pub struct BlindRotationKeyPrepared<D: Data, BRT: BlindRotationAlgo, B: Backend> { - pub(crate) data: Vec<GGSWCiphertextPrepared<D, B>>, + pub(crate) data: Vec<GGSWPrepared<D, B>>, pub(crate) dist: Distribution, pub(crate) x_pow_a: Option<Vec<SvpPPol<Vec<u8>, B>>>, pub(crate) _phantom: PhantomData<BRT>, } impl<D: Data, BRT: BlindRotationAlgo, B: Backend> BlindRotationKeyInfos for BlindRotationKeyPrepared<D, BRT, B> { - fn n_glwe(&self) -> Degree { + fn n_glwe(&self) -> RingDegree { self.n() } - fn n_lwe(&self) -> Degree { - Degree(self.data.len() as u32) + fn n_lwe(&self) -> RingDegree { + RingDegree(self.data.len() as u32) } }

@@ -48,7 +48,7 @@ fn k(&self) -> TorusPrecision {

self.data[0].k() } - fn n(&self) -> Degree { + fn n(&self) -> RingDegree { self.data[0].n() }
M poulpy-schemes/src/tfhe/blind_rotation/mod.rs → poulpy-schemes/src/tfhe/blind_rotation/mod.rs

@@ -14,7 +14,7 @@ pub use lut::*;

pub mod tests; -use poulpy_core::layouts::{GLWECiphertext, LWECiphertext}; +use poulpy_core::layouts::{GLWE, LWE}; use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch}; pub trait BlindRotationAlgo {}

@@ -27,8 +27,8 @@ pub trait BlincRotationExecute<B: Backend> {

fn execute<DR: DataMut, DI: DataRef>( &self, module: &Module<B>, - res: &mut GLWECiphertext<DR>, - lwe: &LWECiphertext<DI>, + res: &mut GLWE<DR>, + lwe: &LWE<DI>, lut: &LookUpTable, scratch: &mut Scratch<B>, );
M poulpy-schemes/src/tfhe/blind_rotation/tests/generic_blind_rotation.rs → poulpy-schemes/src/tfhe/blind_rotation/tests/generic_blind_rotation.rs

@@ -1,9 +1,9 @@

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigAllocBytes, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftSubInplace, VecZnxDftZero, VecZnxFillUniform, VecZnxIdftApply, + VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxCopy, VecZnxDftAdd, VecZnxDftAddInplace, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftSubInplace, VecZnxDftZero, VecZnxFillUniform, VecZnxIdftApply, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpBytes, VecZnxMulXpMinusOneInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal,

@@ -19,20 +19,19 @@ };

use crate::tfhe::blind_rotation::{ BlincRotationExecute, BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyEncryptSk, BlindRotationKeyLayout, - BlindRotationKeyPrepared, CGGI, LookUpTable, cggi_blind_rotate_scratch_space, mod_switch_2n, + BlindRotationKeyPrepared, CGGI, LookUpTable, cggi_blind_rotate_tmp_bytes, mod_switch_2n, }; use poulpy_core::layouts::{ - GLWECiphertext, GLWECiphertextLayout, GLWEPlaintext, GLWESecret, LWECiphertext, LWECiphertextLayout, LWECiphertextToRef, - LWEInfos, LWEPlaintext, LWESecret, + GLWE, GLWELayout, GLWEPlaintext, GLWESecret, LWE, LWEInfos, LWELayout, LWEPlaintext, LWESecret, LWEToRef, prepared::{GLWESecretPrepared, PrepareAlloc}, }; pub fn test_blind_rotation<B>(module: &Module<B>, n_lwe: usize, block_size: usize, extension_factor: usize) where - Module<B>: VecZnxBigAllocBytes - + VecZnxDftAllocBytes - + SvpPPolAllocBytes + Module<B>: VecZnxBigBytesOf + + VecZnxDftBytesOf + + SvpPPolBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VecZnxIdftApplyTmpBytes

@@ -111,31 +110,31 @@ dnum: rows_brk.into(),

rank: rank.into(), }; - let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout { + let glwe_infos: GLWELayout = GLWELayout { n: n_glwe.into(), base2k: base2k.into(), k: k_res.into(), rank: rank.into(), }; - let lwe_infos: LWECiphertextLayout = LWECiphertextLayout { + let lwe_infos: LWELayout = LWELayout { n: n_lwe.into(), k: k_lwe.into(), base2k: base2k.into(), }; - let mut scratch: ScratchOwned<B> = ScratchOwned::<B>::alloc(BlindRotationKey::generate_from_sk_scratch_space( + let mut scratch: ScratchOwned<B> = ScratchOwned::<B>::alloc(BlindRotationKey::generate_from_sk_tmp_bytes( module, &brk_infos, )); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); let sk_glwe_dft: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe.into()); sk_lwe.fill_binary_block(block_size, &mut source_xs); - let mut scratch_br: ScratchOwned<B> = ScratchOwned::<B>::alloc(cggi_blind_rotate_scratch_space( + let mut scratch_br: ScratchOwned<B> = ScratchOwned::<B>::alloc(cggi_blind_rotate_tmp_bytes( module, block_size, extension_factor,

@@ -154,9 +153,9 @@ &mut source_xe,

scratch.borrow(), ); - let mut lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos); + let mut lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos); - let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(&lwe_infos); + let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_from_infos(&lwe_infos); let x: i64 = 15 % (message_modulus as i64);

@@ -175,13 +174,13 @@

let mut lut: LookUpTable = LookUpTable::alloc(module, base2k, k_lut, extension_factor); lut.set(module, &f_vec, log_message_modulus + 1); - let mut res: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos); + let mut res: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos); let brk_prepared: BlindRotationKeyPrepared<Vec<u8>, CGGI, B> = brk.prepare_alloc(module, scratch.borrow()); brk_prepared.execute(module, &mut res, &lwe, &lut, scratch_br.borrow()); - let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos); + let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos); res.decrypt(module, &mut pt_have, &sk_glwe_dft, scratch.borrow());
M poulpy-schemes/src/tfhe/circuit_bootstrapping/circuit.rs → poulpy-schemes/src/tfhe/circuit_bootstrapping/circuit.rs

@@ -3,9 +3,9 @@

use poulpy_hal::{ api::{ ScratchAvailable, TakeMatZnx, TakeSlice, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, TakeVecZnxSlice, - VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, + VecZnxAddInplace, VecZnxAutomorphismInplace, VecZnxBigAddSmallInplace, VecZnxBigAutomorphismInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftAddInplace, - VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, + VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes,

@@ -15,12 +15,12 @@ oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl},

}; use poulpy_core::{ - GLWEOperations, TakeGGLWE, TakeGLWECt, - layouts::{Dsize, GGLWECiphertextLayout, GGSWInfos, GLWEInfos, LWEInfos}, + GLWEOperations, TakeGGLWE, TakeGLWE, + layouts::{Dsize, GGLWELayout, GGSWInfos, GLWEInfos, LWEInfos}, }; use poulpy_core::glwe_packing; -use poulpy_core::layouts::{GGSWCiphertext, GLWECiphertext, LWECiphertext, prepared::GGLWEAutomorphismKeyPrepared}; +use poulpy_core::layouts::{GGSW, GLWE, LWE, prepared::AutomorphismKeyPrepared}; use crate::tfhe::{ blind_rotation::{

@@ -44,7 +44,7 @@ + VecZnxAddInplace

+ VecZnxNegateInplace + VecZnxCopy + VecZnxSubInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -56,7 +56,7 @@ + VecZnxBigNormalize<B>

+ VecZnxAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B> + VecZnxRotateInplaceTmpBytes - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<B> + VecZnxRotate + VecZnxNormalize<B>,

@@ -74,8 +74,8 @@ {

fn execute_to_constant<DM: DataMut, DR: DataRef>( &self, module: &Module<B>, - res: &mut GGSWCiphertext<DM>, - lwe: &LWECiphertext<DR>, + res: &mut GGSW<DM>, + lwe: &LWE<DR>, log_domain: usize, extension_factor: usize, scratch: &mut Scratch<B>,

@@ -97,8 +97,8 @@ fn execute_to_exponent<DM: DataMut, DR: DataRef>(

&self, module: &Module<B>, log_gap_out: usize, - res: &mut GGSWCiphertext<DM>, - lwe: &LWECiphertext<DR>, + res: &mut GGSW<DM>, + lwe: &LWE<DR>, log_domain: usize, extension_factor: usize, scratch: &mut Scratch<B>,

@@ -122,8 +122,8 @@ pub fn circuit_bootstrap_core<DRes, DLwe, DBrk, BRA: BlindRotationAlgo, B>(

to_exponent: bool, module: &Module<B>, log_gap_out: usize, - res: &mut GGSWCiphertext<DRes>, - lwe: &LWECiphertext<DLwe>, + res: &mut GGSW<DRes>, + lwe: &LWE<DLwe>, log_domain: usize, extension_factor: usize, key: &CircuitBootstrappingKeyPrepared<DBrk, BRA, B>,

@@ -145,7 +145,7 @@ + VecZnxAddInplace

+ VecZnxNegateInplace + VecZnxCopy + VecZnxSubInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -156,7 +156,7 @@ + VecZnxBigAddSmallInplace<B>

+ VecZnxBigNormalize<B> + VecZnxAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<B> + VecZnxRotateInplaceTmpBytes + VecZnxRotate

@@ -214,7 +214,7 @@

// TODO: separate GGSW k from output of blind rotation k let (mut res_glwe, scratch_1) = scratch.take_glwe_ct(res); - let gglwe_infos: GGLWECiphertextLayout = GGLWECiphertextLayout { + let gglwe_infos: GGLWELayout = GGLWELayout { n: n.into(), base2k: base2k.into(), k: k.into(),

@@ -233,7 +233,7 @@

let log_gap_in: usize = (usize::BITS - (gap * alpha - 1).leading_zeros()) as _; (0..dnum).for_each(|i| { - let mut tmp_glwe: GLWECiphertext<&mut [u8]> = tmp_gglwe.at_mut(i, 0); + let mut tmp_glwe: GLWE<&mut [u8]> = tmp_gglwe.at_mut(i, 0); if to_exponent { // Isolates i-th LUT and moves coefficients according to requested gap.

@@ -263,12 +263,12 @@

#[allow(clippy::too_many_arguments)] fn post_process<DataRes, DataA, B: Backend>( module: &Module<B>, - res: &mut GLWECiphertext<DataRes>, - a: &GLWECiphertext<DataA>, + res: &mut GLWE<DataRes>, + a: &GLWE<DataA>, log_gap_in: usize, log_gap_out: usize, log_domain: usize, - auto_keys: &HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, + auto_keys: &HashMap<i64, AutomorphismKeyPrepared<Vec<u8>, B>>, scratch: &mut Scratch<B>, ) where DataRes: DataMut,

@@ -286,7 +286,7 @@ + VecZnxAddInplace

+ VecZnxNegateInplace + VecZnxCopy + VecZnxSubInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VmpApplyDftToDftTmpBytes + VecZnxBigNormalizeTmpBytes + VmpApplyDftToDft<B>

@@ -303,7 +303,7 @@ Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,

{ let log_n: usize = module.log_n(); - let mut cts: HashMap<usize, &mut GLWECiphertext<Vec<u8>>> = HashMap::new(); + let mut cts: HashMap<usize, &mut GLWE<Vec<u8>>> = HashMap::new(); // First partial trace, vanishes all coefficients which are not multiples of gap_in // [1, 1, 1, 1, 0, 0, 0, ..., 0, 0, -1, -1, -1, -1] -> [1, 0, 0, 0, 0, 0, 0, ..., 0, 0, 0, 0, 0, 0]

@@ -322,7 +322,7 @@ if log_gap_in != log_gap_out {

let steps: usize = 1 << log_domain; // TODO: from Scratch - let mut cts_vec: Vec<GLWECiphertext<Vec<u8>>> = Vec::new(); + let mut cts_vec: Vec<GLWE<Vec<u8>>> = Vec::new(); for i in 0..steps { if i != 0 {

@@ -336,7 +336,7 @@ cts.insert(i * (1 << log_gap_out), ct);

} glwe_packing(module, &mut cts, log_gap_out, auto_keys, scratch); - let packed: &mut GLWECiphertext<Vec<u8>> = cts.remove(&0).unwrap(); + let packed: &mut GLWE<Vec<u8>> = cts.remove(&0).unwrap(); res.trace( module, log_n - log_gap_out,
M poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rs → poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rs

@@ -1,15 +1,15 @@

use poulpy_core::layouts::{ - GGLWEAutomorphismKey, GGLWEAutomorphismKeyLayout, GGLWEInfos, GGLWETensorKey, GGLWETensorKeyLayout, GGSWInfos, - GLWECiphertext, GLWEInfos, GLWESecret, LWEInfos, LWESecret, - prepared::{GGLWEAutomorphismKeyPrepared, GGLWETensorKeyPrepared, GLWESecretPrepared, PrepareAlloc}, + AutomorphismKey, AutomorphismKeyLayout, GGLWEInfos, GGSWInfos, GLWE, GLWEInfos, GLWESecret, LWEInfos, LWESecret, TensorKey, + TensorKeyLayout, + prepared::{AutomorphismKeyPrepared, GLWESecretPrepared, PrepareAlloc, TensorKeyPrepared}, }; use std::collections::HashMap; use poulpy_hal::{ api::{ - ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, + ScratchAvailable, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, TakeScalarZnx, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, - VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxAutomorphism, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpPMatAlloc, VmpPrepare, },

@@ -24,19 +24,19 @@ };

pub trait CircuitBootstrappingKeyInfos { fn brk_infos(&self) -> BlindRotationKeyLayout; - fn atk_infos(&self) -> GGLWEAutomorphismKeyLayout; - fn tsk_infos(&self) -> GGLWETensorKeyLayout; + fn atk_infos(&self) -> AutomorphismKeyLayout; + fn tsk_infos(&self) -> TensorKeyLayout; } #[derive(Debug, Clone, Copy)] pub struct CircuitBootstrappingKeyLayout { pub layout_brk: BlindRotationKeyLayout, - pub layout_atk: GGLWEAutomorphismKeyLayout, - pub layout_tsk: GGLWETensorKeyLayout, + pub layout_atk: AutomorphismKeyLayout, + pub layout_tsk: TensorKeyLayout, } impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout { - fn atk_infos(&self) -> GGLWEAutomorphismKeyLayout { + fn atk_infos(&self) -> AutomorphismKeyLayout { self.layout_atk }

@@ -44,7 +44,7 @@ fn brk_infos(&self) -> BlindRotationKeyLayout {

self.layout_brk } - fn tsk_infos(&self) -> GGLWETensorKeyLayout { + fn tsk_infos(&self) -> TensorKeyLayout { self.layout_tsk } }

@@ -68,8 +68,8 @@ }

pub struct CircuitBootstrappingKey<D: Data, BRA: BlindRotationAlgo> { pub(crate) brk: BlindRotationKey<D, BRA>, - pub(crate) tsk: GGLWETensorKey<Vec<u8>>, - pub(crate) atk: HashMap<i64, GGLWEAutomorphismKey<Vec<u8>>>, + pub(crate) tsk: TensorKey<Vec<u8>>, + pub(crate) atk: HashMap<i64, AutomorphismKey<Vec<u8>>>, } impl<BRA: BlindRotationAlgo, B: Backend> CircuitBootstrappingKeyEncryptSk<B> for CircuitBootstrappingKey<Vec<u8>, BRA>

@@ -78,7 +78,7 @@ BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyAlloc + BlindRotationKeyEncryptSk<B>,

Module<B>: SvpApplyDftToDft<B> + VecZnxIdftApplyTmpA<B> + VecZnxAddScalarInplace - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -93,7 +93,7 @@ + VecZnxNormalize<B>

+ VecZnxSub + SvpPrepare<B> + VecZnxSwitchRing - + SvpPPolAllocBytes + + SvpPPolBytesOf + SvpPPolAlloc<B> + VecZnxAutomorphism, Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeSvpPPol<B> + TakeVecZnxBig<B>,

@@ -117,14 +117,14 @@ assert_eq!(sk_glwe.n(), cbt_infos.brk_infos().n_glwe());

assert_eq!(sk_glwe.n(), cbt_infos.atk_infos().n()); assert_eq!(sk_glwe.n(), cbt_infos.tsk_infos().n()); - let atk_infos: GGLWEAutomorphismKeyLayout = cbt_infos.atk_infos(); + let atk_infos: AutomorphismKeyLayout = cbt_infos.atk_infos(); let brk_infos: BlindRotationKeyLayout = cbt_infos.brk_infos(); - let trk_infos: GGLWETensorKeyLayout = cbt_infos.tsk_infos(); + let trk_infos: TensorKeyLayout = cbt_infos.tsk_infos(); - let mut auto_keys: HashMap<i64, GGLWEAutomorphismKey<Vec<u8>>> = HashMap::new(); - let gal_els: Vec<i64> = GLWECiphertext::trace_galois_elements(module); + let mut auto_keys: HashMap<i64, AutomorphismKey<Vec<u8>>> = HashMap::new(); + let gal_els: Vec<i64> = GLWE::trace_galois_elements(module); gal_els.iter().for_each(|gal_el| { - let mut key: GGLWEAutomorphismKey<Vec<u8>> = GGLWEAutomorphismKey::alloc(&atk_infos); + let mut key: AutomorphismKey<Vec<u8>> = AutomorphismKey::alloc_from_infos(&atk_infos); key.encrypt_sk(module, *gal_el, sk_glwe, source_xa, source_xe, scratch); auto_keys.insert(*gal_el, key); });

@@ -141,7 +141,7 @@ source_xe,

scratch, ); - let mut tsk: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(&trk_infos); + let mut tsk: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(&trk_infos); tsk.encrypt_sk(module, sk_glwe, source_xa, source_xe, scratch); Self {

@@ -154,14 +154,14 @@ }

pub struct CircuitBootstrappingKeyPrepared<D: Data, BRA: BlindRotationAlgo, B: Backend> { pub(crate) brk: BlindRotationKeyPrepared<D, BRA, B>, - pub(crate) tsk: GGLWETensorKeyPrepared<Vec<u8>, B>, - pub(crate) atk: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, + pub(crate) tsk: TensorKeyPrepared<Vec<u8>, B>, + pub(crate) atk: HashMap<i64, AutomorphismKeyPrepared<Vec<u8>, B>>, } impl<D: DataRef, BRA: BlindRotationAlgo, B: Backend> CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyPrepared<D, BRA, B> { - fn atk_infos(&self) -> GGLWEAutomorphismKeyLayout { + fn atk_infos(&self) -> AutomorphismKeyLayout { let (_, atk) = self.atk.iter().next().expect("atk is empty"); - GGLWEAutomorphismKeyLayout { + AutomorphismKeyLayout { n: atk.n(), base2k: atk.base2k(), k: atk.k(),

@@ -182,8 +182,8 @@ rank: self.brk.rank(),

} } - fn tsk_infos(&self) -> GGLWETensorKeyLayout { - GGLWETensorKeyLayout { + fn tsk_infos(&self) -> TensorKeyLayout { + TensorKeyLayout { n: self.tsk.n(), base2k: self.tsk.base2k(), k: self.tsk.k(),

@@ -199,13 +199,13 @@ for CircuitBootstrappingKey<D, BRA>

where Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>, BlindRotationKey<D, BRA>: PrepareAlloc<B, BlindRotationKeyPrepared<Vec<u8>, BRA, B>>, - GGLWETensorKey<D>: PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>>, - GGLWEAutomorphismKey<D>: PrepareAlloc<B, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>>, + TensorKey<D>: PrepareAlloc<B, TensorKeyPrepared<Vec<u8>, B>>, + AutomorphismKey<D>: PrepareAlloc<B, AutomorphismKeyPrepared<Vec<u8>, B>>, { fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> { let brk: BlindRotationKeyPrepared<Vec<u8>, BRA, B> = self.brk.prepare_alloc(module, scratch); - let tsk: GGLWETensorKeyPrepared<Vec<u8>, B> = self.tsk.prepare_alloc(module, scratch); - let mut atk: HashMap<i64, GGLWEAutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); + let tsk: TensorKeyPrepared<Vec<u8>, B> = self.tsk.prepare_alloc(module, scratch); + let mut atk: HashMap<i64, AutomorphismKeyPrepared<Vec<u8>, B>> = HashMap::new(); for (key, value) in &self.atk { atk.insert(*key, value.prepare_alloc(module, scratch)); }
M poulpy-schemes/src/tfhe/circuit_bootstrapping/mod.rs → poulpy-schemes/src/tfhe/circuit_bootstrapping/mod.rs

@@ -5,7 +5,7 @@

pub use circuit::*; pub use key::*; -use poulpy_core::layouts::{GGSWCiphertext, LWECiphertext}; +use poulpy_core::layouts::{GGSW, LWE}; use poulpy_hal::layouts::{Backend, DataMut, DataRef, Module, Scratch};

@@ -13,8 +13,8 @@ pub trait CirtuitBootstrappingExecute<B: Backend> {

fn execute_to_constant<DM: DataMut, DR: DataRef>( &self, module: &Module<B>, - res: &mut GGSWCiphertext<DM>, - lwe: &LWECiphertext<DR>, + res: &mut GGSW<DM>, + lwe: &LWE<DR>, log_domain: usize, extension_factor: usize, scratch: &mut Scratch<B>,

@@ -25,8 +25,8 @@ fn execute_to_exponent<DM: DataMut, DR: DataRef>(

&self, module: &Module<B>, log_gap_out: usize, - res: &mut GGSWCiphertext<DM>, - lwe: &LWECiphertext<DR>, + res: &mut GGSW<DM>, + lwe: &LWE<DR>, log_domain: usize, extension_factor: usize, scratch: &mut Scratch<B>,
M poulpy-schemes/src/tfhe/circuit_bootstrapping/tests/circuit_bootstrapping.rs → poulpy-schemes/src/tfhe/circuit_bootstrapping/tests/circuit_bootstrapping.rs

@@ -2,11 +2,11 @@ use std::time::Instant;

use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolAllocBytes, + ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism, VecZnxAutomorphismInplace, - VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigAutomorphismInplace, + VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigAutomorphismInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxBigSubSmallNegateInplace, VecZnxCopy, VecZnxDftAddInplace, - VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftApply, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, + VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxDftCopy, VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNegateInplace, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRotateInplaceTmpBytes, VecZnxRshInplace, VecZnxSub, VecZnxSubInplace, VecZnxSwitchRing, VmpApplyDftToDft, VmpApplyDftToDftAdd, VmpApplyDftToDftTmpBytes, VmpPMatAlloc, VmpPrepare, ZnAddNormal, ZnFillUniform,

@@ -31,13 +31,11 @@ CircuitBootstrappingKeyPrepared, CirtuitBootstrappingExecute,

}, }; -use poulpy_core::layouts::{ - Dsize, GGLWEAutomorphismKeyLayout, GGLWETensorKeyLayout, GGSWCiphertextLayout, LWECiphertextLayout, prepared::PrepareAlloc, -}; +use poulpy_core::layouts::{AutomorphismKeyLayout, Dsize, GGSWLayout, LWELayout, TensorKeyLayout, prepared::PrepareAlloc}; use poulpy_core::layouts::{ - GGSWCiphertext, GLWECiphertext, GLWEPlaintext, GLWESecret, LWECiphertext, LWEPlaintext, LWESecret, - prepared::{GGSWCiphertextPrepared, GLWESecretPrepared}, + GGSW, GLWE, GLWEPlaintext, GLWESecret, LWE, LWEPlaintext, LWESecret, + prepared::{GGSWPrepared, GLWESecretPrepared}, }; pub fn test_circuit_bootstrapping_to_exponent<B, BRA: BlindRotationAlgo>(module: &Module<B>)

@@ -45,7 +43,7 @@ where

Module<B>: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -58,7 +56,7 @@ + VecZnxSub

+ VecZnxAddScalarInplace + VecZnxAutomorphism + VecZnxSwitchRing - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxIdftApplyTmpA<B> + SvpApplyDftToDft<B> + VecZnxBigAddInplace<B>

@@ -73,7 +71,7 @@ + SvpPPolAlloc<B>

+ VmpApplyDftToDftTmpBytes + VmpApplyDftToDft<B> + VmpApplyDftToDftAdd<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + VecZnxRotateInplace<B> + VecZnxBigAutomorphismInplace<B> + VecZnxRshInplace<B>

@@ -83,7 +81,7 @@ + VecZnxCopy

+ VecZnxAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B> + VecZnxRotateInplaceTmpBytes - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<B> + VecZnxRotate + ZnFillUniform

@@ -128,7 +126,7 @@

let k_ggsw_res: usize = 4 * base2k; let rows_ggsw_res: usize = 2; - let lwe_infos: LWECiphertextLayout = LWECiphertextLayout { + let lwe_infos: LWELayout = LWELayout { n: n_lwe.into(), k: k_lwe_ct.into(), base2k: base2k.into(),

@@ -143,7 +141,7 @@ k: k_brk.into(),

dnum: rows_brk.into(), rank: rank.into(), }, - layout_atk: GGLWEAutomorphismKeyLayout { + layout_atk: AutomorphismKeyLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_atk.into(),

@@ -151,7 +149,7 @@ dnum: rows_atk.into(),

rank: rank.into(), dsize: Dsize(1), }, - layout_tsk: GGLWETensorKeyLayout { + layout_tsk: TensorKeyLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -161,7 +159,7 @@ rank: rank.into(),

}, }; - let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout { + let ggsw_infos: GGSWLayout = GGSWLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_ggsw_res.into(),

@@ -179,19 +177,19 @@

let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe.into()); sk_lwe.fill_binary_block(block_size, &mut source_xs); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n_glwe.into(), rank.into()); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe.into(), rank.into()); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let data: i64 = 1; - let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_with(base2k.into(), k_lwe_pt.into()); + let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into()); pt_lwe.encode_i64(data, (k_lwe_pt + 1).into()); println!("pt_lwe: {pt_lwe}"); - let mut ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos); + let mut ct_lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos); ct_lwe.encrypt_sk(module, &pt_lwe, &sk_lwe, &mut source_xa, &mut source_xe); let now: Instant = Instant::now();

@@ -206,7 +204,7 @@ scratch.borrow(),

); println!("CBT-KGEN: {} ms", now.elapsed().as_millis()); - let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut res: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); let log_gap_out = 1;

@@ -236,8 +234,8 @@ );

res.print_noise(module, &sk_glwe_prepared, &pt_ggsw); - let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&ggsw_infos); - let mut pt_glwe: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&ggsw_infos); + let mut ct_glwe: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ggsw_infos); + let mut pt_glwe: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ggsw_infos); pt_glwe.data.at_mut(0, 0)[0] = 1 << (base2k - 2); ct_glwe.encrypt_sk(

@@ -249,11 +247,11 @@ &mut source_xe,

scratch.borrow(), ); - let res_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = res.prepare_alloc(module, scratch.borrow()); + let res_prepared: GGSWPrepared<Vec<u8>, B> = res.prepare_alloc(module, scratch.borrow()); ct_glwe.external_product_inplace(module, &res_prepared, scratch.borrow()); - let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&ggsw_infos); + let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ggsw_infos); ct_glwe.decrypt(module, &mut pt_res, &sk_glwe_prepared, scratch.borrow()); // Parameters are set such that the first limb should be noiseless.

@@ -267,7 +265,7 @@ where

Module<B>: VecZnxFillUniform + VecZnxAddNormal + VecZnxNormalizeInplace<B> - + VecZnxDftAllocBytes + + VecZnxDftBytesOf + VecZnxBigNormalize<B> + VecZnxDftApply<B> + SvpApplyDftToDftInplace<B>

@@ -280,7 +278,7 @@ + VecZnxSub

+ VecZnxAddScalarInplace + VecZnxAutomorphism + VecZnxSwitchRing - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxIdftApplyTmpA<B> + SvpApplyDftToDft<B> + VecZnxBigAddInplace<B>

@@ -295,7 +293,7 @@ + SvpPPolAlloc<B>

+ VmpApplyDftToDftTmpBytes + VmpApplyDftToDft<B> + VmpApplyDftToDftAdd<B> - + SvpPPolAllocBytes + + SvpPPolBytesOf + VecZnxRotateInplace<B> + VecZnxBigAutomorphismInplace<B> + VecZnxRotateInplaceTmpBytes

@@ -305,7 +303,7 @@ + VecZnxNegateInplace

+ VecZnxCopy + VecZnxAutomorphismInplace<B> + VecZnxBigSubSmallNegateInplace<B> - + VecZnxBigAllocBytes + + VecZnxBigBytesOf + VecZnxDftAddInplace<B> + VecZnxRotate + ZnFillUniform

@@ -350,7 +348,7 @@

let k_ggsw_res: usize = 4 * base2k; let rows_ggsw_res: usize = 3; - let lwe_infos: LWECiphertextLayout = LWECiphertextLayout { + let lwe_infos: LWELayout = LWELayout { n: n_lwe.into(), k: k_lwe_ct.into(), base2k: base2k.into(),

@@ -365,7 +363,7 @@ k: k_brk.into(),

dnum: rows_brk.into(), rank: rank.into(), }, - layout_atk: GGLWEAutomorphismKeyLayout { + layout_atk: AutomorphismKeyLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_atk.into(),

@@ -373,7 +371,7 @@ dnum: rows_atk.into(),

rank: rank.into(), dsize: Dsize(1), }, - layout_tsk: GGLWETensorKeyLayout { + layout_tsk: TensorKeyLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_tsk.into(),

@@ -383,7 +381,7 @@ rank: rank.into(),

}, }; - let ggsw_infos: GGSWCiphertextLayout = GGSWCiphertextLayout { + let ggsw_infos: GGSWLayout = GGSWLayout { n: n_glwe.into(), base2k: base2k.into(), k: k_ggsw_res.into(),

@@ -401,19 +399,19 @@

let mut sk_lwe: LWESecret<Vec<u8>> = LWESecret::alloc(n_lwe.into()); sk_lwe.fill_binary_block(block_size, &mut source_xs); - let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc_with(n_glwe.into(), rank.into()); + let mut sk_glwe: GLWESecret<Vec<u8>> = GLWESecret::alloc(n_glwe.into(), rank.into()); sk_glwe.fill_ternary_prob(0.5, &mut source_xs); let sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, B> = sk_glwe.prepare_alloc(module, scratch.borrow()); let data: i64 = 1; - let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc_with(base2k.into(), k_lwe_pt.into()); + let mut pt_lwe: LWEPlaintext<Vec<u8>> = LWEPlaintext::alloc(base2k.into(), k_lwe_pt.into()); pt_lwe.encode_i64(data, (k_lwe_pt + 1).into()); println!("pt_lwe: {pt_lwe}"); - let mut ct_lwe: LWECiphertext<Vec<u8>> = LWECiphertext::alloc(&lwe_infos); + let mut ct_lwe: LWE<Vec<u8>> = LWE::alloc_from_infos(&lwe_infos); ct_lwe.encrypt_sk(module, &pt_lwe, &sk_lwe, &mut source_xa, &mut source_xe); let now: Instant = Instant::now();

@@ -428,7 +426,7 @@ scratch.borrow(),

); println!("CBT-KGEN: {} ms", now.elapsed().as_millis()); - let mut res: GGSWCiphertext<Vec<u8>> = GGSWCiphertext::alloc(&ggsw_infos); + let mut res: GGSW<Vec<u8>> = GGSW::alloc_from_infos(&ggsw_infos); let cbt_prepared: CircuitBootstrappingKeyPrepared<Vec<u8>, BRA, B> = cbt_key.prepare_alloc(module, scratch.borrow());

@@ -449,8 +447,8 @@ pt_ggsw.at_mut(0, 0)[0] = data;

res.print_noise(module, &sk_glwe_prepared, &pt_ggsw); - let mut ct_glwe: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&ggsw_infos); - let mut pt_glwe: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&ggsw_infos); + let mut ct_glwe: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&ggsw_infos); + let mut pt_glwe: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ggsw_infos); pt_glwe.data.at_mut(0, 0)[0] = 1 << (base2k - k_lwe_pt - 1); ct_glwe.encrypt_sk(

@@ -462,11 +460,11 @@ &mut source_xe,

scratch.borrow(), ); - let res_prepared: GGSWCiphertextPrepared<Vec<u8>, B> = res.prepare_alloc(module, scratch.borrow()); + let res_prepared: GGSWPrepared<Vec<u8>, B> = res.prepare_alloc(module, scratch.borrow()); ct_glwe.external_product_inplace(module, &res_prepared, scratch.borrow()); - let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&ggsw_infos); + let mut pt_res: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&ggsw_infos); ct_glwe.decrypt(module, &mut pt_res, &sk_glwe_prepared, scratch.borrow()); // Parameters are set such that the first limb should be noiseless.