Crates io (#76)

* crates re-organisation

* fixed typo in layout & added test for vmp_apply

* updated dependencies
This commit is contained in:
Jean-Philippe Bossuat
2025-08-18 11:16:27 +02:00
committed by GitHub
parent dce4d82706
commit a1de248567
415 changed files with 32933 additions and 1889 deletions

17
poulpy-hal/src/api/mod.rs Normal file
View File

@@ -0,0 +1,17 @@
mod module;
mod scratch;
mod svp_ppol;
mod vec_znx;
mod vec_znx_big;
mod vec_znx_dft;
mod vmp_pmat;
mod znx_base;
pub use module::*;
pub use scratch::*;
pub use svp_ppol::*;
pub use vec_znx::*;
pub use vec_znx_big::*;
pub use vec_znx_dft::*;
pub use vmp_pmat::*;
pub use znx_base::*;

View File

@@ -0,0 +1,6 @@
use crate::layouts::Backend;
/// Instantiate a new [crate::layouts::Module].
pub trait ModuleNew<B: Backend> {
fn new(n: u64) -> Self;
}

View File

@@ -0,0 +1,107 @@
use crate::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> {
fn alloc(size: usize) -> Self;
}
/// Borrows a slice of bytes into a [Scratch].
pub trait ScratchOwnedBorrow<B: Backend> {
fn borrow(&mut self) -> &mut Scratch<B>;
}
/// Wrap an array of mutable borrowed bytes into a [Scratch].
pub trait ScratchFromBytes<B: Backend> {
fn from_bytes(data: &mut [u8]) -> &mut Scratch<B>;
}
/// Returns how many bytes left can be taken from the scratch.
pub trait ScratchAvailable {
fn available(&self) -> usize;
}
/// Takes a slice of bytes from a [Scratch] and return a new [Scratch] minus the taken array of bytes.
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);
}
/// 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);
}
/// 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);
}
/// 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);
}
/// 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);
}
/// 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);
}
/// 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(
&mut self,
len: usize,
n: usize,
cols: usize,
size: usize,
) -> (Vec<VecZnxDft<&mut [u8], B>>, &mut Self);
}
/// 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(
&mut self,
n: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
size: usize,
) -> (VmpPMat<&mut [u8], B>, &mut Self);
}
/// 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(
&mut self,
n: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
size: usize,
) -> (MatZnx<&mut [u8]>, &mut Self);
}
/// Take a slice of bytes from a [Scratch], wraps it into the template's type and returns it
/// as well as a new [Scratch] minus the taken array of bytes.
pub trait TakeLike<'a, B: Backend, T> {
type Output;
fn take_like(&'a mut self, template: &T) -> (Self::Output, &'a mut Self);
}

View File

@@ -0,0 +1,42 @@
use crate::layouts::{Backend, ScalarZnxToRef, SvpPPolOwned, SvpPPolToMut, SvpPPolToRef, VecZnxDftToMut, VecZnxDftToRef};
/// Allocates as [crate::layouts::SvpPPol].
pub trait SvpPPolAlloc<B: Backend> {
fn svp_ppol_alloc(&self, n: usize, cols: usize) -> SvpPPolOwned<B>;
}
/// Returns the size in bytes to allocate a [crate::layouts::SvpPPol].
pub trait SvpPPolAllocBytes {
fn svp_ppol_alloc_bytes(&self, n: usize, cols: usize) -> usize;
}
/// Consume a vector of bytes into a [crate::layouts::MatZnx].
/// User must ensure that bytes is memory aligned and that it length is equal to [SvpPPolAllocBytes].
pub trait SvpPPolFromBytes<B: Backend> {
fn svp_ppol_from_bytes(&self, n: usize, cols: usize, bytes: Vec<u8>) -> SvpPPolOwned<B>;
}
/// Prepare a [crate::layouts::ScalarZnx] into an [crate::layouts::SvpPPol].
pub trait SvpPrepare<B: Backend> {
fn svp_prepare<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: SvpPPolToMut<B>,
A: ScalarZnxToRef;
}
/// Apply a scalar-vector product between `a[a_col]` and `b[b_col]` and stores the result on `res[res_col]`.
pub trait SvpApply<B: Backend> {
fn svp_apply<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: SvpPPolToRef<B>,
C: VecZnxDftToRef<B>;
}
/// Apply a scalar-vector product between `res[res_col]` and `a[a_col]` and stores the result on `res[res_col]`.
pub trait SvpApplyInplace<B: Backend> {
fn svp_apply_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: SvpPPolToRef<B>;
}

View File

@@ -0,0 +1,269 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef},
source::Source,
};
pub trait VecZnxNormalizeTmpBytes {
/// Returns the minimum number of bytes necessary for normalization.
fn vec_znx_normalize_tmp_bytes(&self, n: usize) -> usize;
}
pub trait VecZnxNormalize<B: Backend> {
/// Normalizes the selected column of `a` and stores the result into the selected column of `res`.
fn vec_znx_normalize<R, A>(&self, basek: usize, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxNormalizeInplace<B: Backend> {
/// Normalizes the selected column of `a`.
fn vec_znx_normalize_inplace<A>(&self, basek: usize, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxToMut;
}
pub trait VecZnxAdd {
/// Adds the selected column of `a` to the selected column of `b` and writes the result on the selected column of `res`.
fn vec_znx_add<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
B: VecZnxToRef;
}
pub trait VecZnxAddInplace {
/// Adds the selected column of `a` to the selected column of `res` and writes the result on the selected column of `res`.
fn vec_znx_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxAddScalarInplace {
/// Adds the selected column of `a` on the selected column and limb of `res`.
fn vec_znx_add_scalar_inplace<R, A>(&self, res: &mut R, res_col: usize, res_limb: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: ScalarZnxToRef;
}
pub trait VecZnxSub {
/// Subtracts the selected column of `b` from the selected column of `a` and writes the result on the selected column of `res`.
fn vec_znx_sub<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
B: VecZnxToRef;
}
pub trait VecZnxSubABInplace {
/// Subtracts the selected column of `a` from the selected column of `res` inplace.
///
/// res\[res_col\] -= a\[a_col\]
fn vec_znx_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxSubBAInplace {
/// Subtracts the selected column of `res` from the selected column of `a` and inplace mutates `res`
///
/// res\[res_col\] = a\[a_col\] - res\[res_col\]
fn vec_znx_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxSubScalarInplace {
/// Subtracts the selected column of `a` on the selected column and limb of `res`.
fn vec_znx_sub_scalar_inplace<R, A>(&self, res: &mut R, res_col: usize, res_limb: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: ScalarZnxToRef;
}
pub trait VecZnxNegate {
// Negates the selected column of `a` and stores the result in `res_col` of `res`.
fn vec_znx_negate<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxNegateInplace {
/// Negates the selected column of `a`.
fn vec_znx_negate_inplace<A>(&self, a: &mut A, a_col: usize)
where
A: VecZnxToMut;
}
pub trait VecZnxLshInplace {
/// Left shift by k bits all columns of `a`.
fn vec_znx_lsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A)
where
A: VecZnxToMut;
}
pub trait VecZnxRshInplace {
/// Right shift by k bits all columns of `a`.
fn vec_znx_rsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A)
where
A: VecZnxToMut;
}
pub trait VecZnxRotate {
/// Multiplies the selected column of `a` by X^k and stores the result in `res_col` of `res`.
fn vec_znx_rotate<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxRotateInplace {
/// Multiplies the selected column of `a` by X^k.
fn vec_znx_rotate_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxToMut;
}
pub trait VecZnxAutomorphism {
/// Applies the automorphism X^i -> X^ik on the selected column of `a` and stores the result in `res_col` column of `res`.
fn vec_znx_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxAutomorphismInplace {
/// Applies the automorphism X^i -> X^ik on the selected column of `a`.
fn vec_znx_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxToMut;
}
pub trait VecZnxMulXpMinusOne {
fn vec_znx_mul_xp_minus_one<R, A>(&self, p: i64, r: &mut R, r_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxMulXpMinusOneInplace {
fn vec_znx_mul_xp_minus_one_inplace<R>(&self, p: i64, r: &mut R, r_col: usize)
where
R: VecZnxToMut;
}
pub trait VecZnxSplit<B: Backend> {
/// Splits the selected columns of `b` into subrings and copies them them into the selected column of `res`.
///
/// # Panics
///
/// This method requires that all [crate::layouts::VecZnx] of b have the same ring degree
/// and that b.n() * b.len() <= a.n()
fn vec_znx_split<R, A>(&self, res: &mut [R], res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxMerge {
/// Merges the subrings of the selected column of `a` into the selected column of `res`.
///
/// # Panics
///
/// This method requires that all [crate::layouts::VecZnx] of a have the same ring degree
/// and that a.n() * a.len() <= b.n()
fn vec_znx_merge<R, A>(&self, res: &mut R, res_col: usize, a: &[A], a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxSwithcDegree {
fn vec_znx_switch_degree<R, A>(&self, res: &mut R, res_col: usize, a: &A, col_a: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxCopy {
fn vec_znx_copy<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxFillUniform {
/// Fills the first `size` size with uniform values in \[-2^{basek-1}, 2^{basek-1}\]
fn vec_znx_fill_uniform<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, source: &mut Source)
where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxFillDistF64 {
fn vec_znx_fill_dist_f64<R, D: Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxAddDistF64 {
/// Adds vector sampled according to the provided distribution, scaled by 2^{-k} and bounded to \[-bound, bound\].
fn vec_znx_add_dist_f64<R, D: Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxFillNormal {
fn vec_znx_fill_normal<R>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxAddNormal {
/// Adds a discrete normal vector scaled by 2^{-k} with the provided standard deviation and bounded to \[-bound, bound\].
fn vec_znx_add_normal<R>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) where
R: VecZnxToMut;
}

View File

@@ -0,0 +1,220 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, Scratch, VecZnxBigOwned, VecZnxBigToMut, VecZnxBigToRef, VecZnxToMut, VecZnxToRef},
source::Source,
};
/// Allocates as [crate::layouts::VecZnxBig].
pub trait VecZnxBigAlloc<B: Backend> {
fn vec_znx_big_alloc(&self, n: usize, 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, n: usize, cols: usize, size: usize) -> usize;
}
/// Consume a vector of bytes into a [crate::layouts::VecZnxBig].
/// User must ensure that bytes is memory aligned and that it length is equal to [VecZnxBigAllocBytes].
pub trait VecZnxBigFromBytes<B: Backend> {
fn vec_znx_big_from_bytes(&self, n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<B>;
}
#[allow(clippy::too_many_arguments)]
/// Add a discrete normal distribution on res.
///
/// # Arguments
/// * `basek`: base two logarithm of the bivariate representation
/// * `res`: receiver.
/// * `res_col`: column of the receiver on which the operation is performed/stored.
/// * `k`:
/// * `source`: random coin source.
/// * `sigma`: standard deviation of the discrete normal distribution.
/// * `bound`: rejection sampling bound.
pub trait VecZnxBigAddNormal<B: Backend> {
fn vec_znx_big_add_normal<R: VecZnxBigToMut<B>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
);
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxBigFillNormal<B: Backend> {
fn vec_znx_big_fill_normal<R: VecZnxBigToMut<B>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
);
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxBigFillDistF64<B: Backend> {
fn vec_znx_big_fill_dist_f64<R: VecZnxBigToMut<B>, D: Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
);
}
#[allow(clippy::too_many_arguments)]
pub trait VecZnxBigAddDistF64<B: Backend> {
fn vec_znx_big_add_dist_f64<R: VecZnxBigToMut<B>, D: Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
);
}
pub trait VecZnxBigAdd<B: Backend> {
/// Adds `a` to `b` and stores the result on `c`.
fn vec_znx_big_add<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxBigToRef<B>;
}
pub trait VecZnxBigAddInplace<B: Backend> {
/// Adds `a` to `b` and stores the result on `b`.
fn vec_znx_big_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigAddSmall<B: Backend> {
/// Adds `a` to `b` and stores the result on `c`.
fn vec_znx_big_add_small<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxToRef;
}
pub trait VecZnxBigAddSmallInplace<B: Backend> {
/// Adds `a` to `b` and stores the result on `b`.
fn vec_znx_big_add_small_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
pub trait VecZnxBigSub<B: Backend> {
/// Subtracts `a` to `b` and stores the result on `c`.
fn vec_znx_big_sub<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxBigToRef<B>;
}
pub trait VecZnxBigSubABInplace<B: Backend> {
/// Subtracts `a` from `b` and stores the result on `b`.
fn vec_znx_big_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigSubBAInplace<B: Backend> {
/// Subtracts `b` from `a` and stores the result on `b`.
fn vec_znx_big_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigSubSmallA<B: Backend> {
/// Subtracts `b` from `a` and stores the result on `c`.
fn vec_znx_big_sub_small_a<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef,
C: VecZnxBigToRef<B>;
}
pub trait VecZnxBigSubSmallAInplace<B: Backend> {
/// Subtracts `a` from `res` and stores the result on `res`.
fn vec_znx_big_sub_small_a_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
pub trait VecZnxBigSubSmallB<B: Backend> {
/// Subtracts `b` from `a` and stores the result on `c`.
fn vec_znx_big_sub_small_b<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxToRef;
}
pub trait VecZnxBigSubSmallBInplace<B: Backend> {
/// Subtracts `res` from `a` and stores the result on `res`.
fn vec_znx_big_sub_small_b_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
pub trait VecZnxBigNegateInplace<B: Backend> {
fn vec_znx_big_negate_inplace<A>(&self, a: &mut A, a_col: usize)
where
A: VecZnxBigToMut<B>;
}
pub trait VecZnxBigNormalizeTmpBytes {
fn vec_znx_big_normalize_tmp_bytes(&self, n: usize) -> usize;
}
pub trait VecZnxBigNormalize<B: Backend> {
fn vec_znx_big_normalize<R, A>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
scratch: &mut Scratch<B>,
) where
R: VecZnxToMut,
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigAutomorphism<B: Backend> {
/// Applies the automorphism X^i -> X^ik on `a` and stores the result on `b`.
fn vec_znx_big_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigAutomorphismInplace<B: Backend> {
/// Applies the automorphism X^i -> X^ik on `a` and stores the result on `a`.
fn vec_znx_big_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxBigToMut<B>;
}

View File

@@ -0,0 +1,96 @@
use crate::layouts::{
Backend, Data, Scratch, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftOwned, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef,
};
pub trait VecZnxDftAlloc<B: Backend> {
fn vec_znx_dft_alloc(&self, n: usize, cols: usize, size: usize) -> VecZnxDftOwned<B>;
}
pub trait VecZnxDftFromBytes<B: Backend> {
fn vec_znx_dft_from_bytes(&self, n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B>;
}
pub trait VecZnxDftAllocBytes {
fn vec_znx_dft_alloc_bytes(&self, n: usize, cols: usize, size: usize) -> usize;
}
pub trait VecZnxDftToVecZnxBigTmpBytes {
fn vec_znx_dft_to_vec_znx_big_tmp_bytes(&self, n: usize) -> usize;
}
pub trait VecZnxDftToVecZnxBig<B: Backend> {
fn vec_znx_dft_to_vec_znx_big<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxBigToMut<B>,
A: VecZnxDftToRef<B>;
}
pub trait VecZnxDftToVecZnxBigTmpA<B: Backend> {
fn vec_znx_dft_to_vec_znx_big_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxDftToMut<B>;
}
pub trait VecZnxDftToVecZnxBigConsume<B: Backend> {
fn vec_znx_dft_to_vec_znx_big_consume<D: Data>(&self, a: VecZnxDft<D, B>) -> VecZnxBig<D, B>
where
VecZnxDft<D, B>: VecZnxDftToMut<B>;
}
pub trait VecZnxDftAdd<B: Backend> {
fn vec_znx_dft_add<R, A, D>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
D: VecZnxDftToRef<B>;
}
pub trait VecZnxDftAddInplace<B: Backend> {
fn vec_znx_dft_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
pub trait VecZnxDftSub<B: Backend> {
fn vec_znx_dft_sub<R, A, D>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
D: VecZnxDftToRef<B>;
}
pub trait VecZnxDftSubABInplace<B: Backend> {
fn vec_znx_dft_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
pub trait VecZnxDftSubBAInplace<B: Backend> {
fn vec_znx_dft_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
pub trait VecZnxDftCopy<B: Backend> {
fn vec_znx_dft_copy<R, A>(&self, step: usize, offset: usize, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
pub trait VecZnxDftFromVecZnx<B: Backend> {
fn vec_znx_dft_from_vec_znx<R, A>(&self, step: usize, offset: usize, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxToRef;
}
pub trait VecZnxDftZero<B: Backend> {
fn vec_znx_dft_zero<R>(&self, res: &mut R)
where
R: VecZnxDftToMut<B>;
}

View File

@@ -0,0 +1,100 @@
use crate::layouts::{Backend, MatZnxToRef, Scratch, VecZnxDftToMut, VecZnxDftToRef, VmpPMatOwned, VmpPMatToMut, VmpPMatToRef};
pub trait VmpPMatAlloc<B: Backend> {
fn vmp_pmat_alloc(&self, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> VmpPMatOwned<B>;
}
pub trait VmpPMatAllocBytes {
fn vmp_pmat_alloc_bytes(&self, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize;
}
pub trait VmpPMatFromBytes<B: Backend> {
fn vmp_pmat_from_bytes(
&self,
n: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
size: usize,
bytes: Vec<u8>,
) -> VmpPMatOwned<B>;
}
pub trait VmpPrepareTmpBytes {
fn vmp_prepare_tmp_bytes(&self, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize;
}
pub trait VmpPrepare<B: Backend> {
fn vmp_prepare<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<B>)
where
R: VmpPMatToMut<B>,
A: MatZnxToRef;
}
#[allow(clippy::too_many_arguments)]
pub trait VmpApplyTmpBytes {
fn vmp_apply_tmp_bytes(
&self,
n: usize,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize;
}
pub trait VmpApply<B: Backend> {
/// Applies the vector matrix product [crate::layouts::VecZnxDft] x [crate::layouts::VmpPMat].
///
/// A vector matrix product numerically equivalent to a sum of [crate::api::SvpApply],
/// where each [crate::layouts::SvpPPol] is a limb of the input [crate::layouts::VecZnx] in DFT,
/// and each vector a [crate::layouts::VecZnxDft] (row) of the [crate::layouts::VmpPMat].
///
/// As such, given an input [crate::layouts::VecZnx] of `i` size and a [crate::layouts::VmpPMat] of `i` rows and
/// `j` size, the output is a [crate::layouts::VecZnx] of `j` size.
///
/// If there is a mismatch between the dimensions the largest valid ones are used.
///
/// ```text
/// |a b c d| x |e f g| = (a * |e f g| + b * |h i j| + c * |k l m|) = |n o p|
/// |h i j|
/// |k l m|
/// ```
/// where each element is a [crate::layouts::VecZnxDft].
///
/// # Arguments
///
/// * `c`: the output of the vector matrix product, as a [crate::layouts::VecZnxDft].
/// * `a`: the left operand [crate::layouts::VecZnxDft] of the vector matrix product.
/// * `b`: the right operand [crate::layouts::VmpPMat] of the vector matrix product.
/// * `buf`: scratch space, the size can be obtained with [VmpApplyTmpBytes::vmp_apply_tmp_bytes].
fn vmp_apply<R, A, C>(&self, res: &mut R, a: &A, b: &C, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
C: VmpPMatToRef<B>;
}
#[allow(clippy::too_many_arguments)]
pub trait VmpApplyAddTmpBytes {
fn vmp_apply_add_tmp_bytes(
&self,
n: usize,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize;
}
pub trait VmpApplyAdd<B: Backend> {
fn vmp_apply_add<R, A, C>(&self, res: &mut R, a: &A, b: &C, scale: usize, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
C: VmpPMatToRef<B>;
}

View File

@@ -0,0 +1,125 @@
use crate::{
layouts::{Backend, Data, DataMut, DataRef},
source::Source,
};
use rand_distr::num_traits::Zero;
pub trait ZnxInfos {
/// Returns the ring degree of the polynomials.
fn n(&self) -> usize;
/// Returns the base two logarithm of the ring dimension of the polynomials.
fn log_n(&self) -> usize {
(usize::BITS - (self.n() - 1).leading_zeros()) as _
}
/// Returns the number of rows.
fn rows(&self) -> usize;
/// Returns the number of polynomials in each row.
fn cols(&self) -> usize;
/// Returns the number of size per polynomial.
fn size(&self) -> usize;
/// Returns the total number of small polynomials.
fn poly_count(&self) -> usize {
self.rows() * self.cols() * self.size()
}
}
pub trait ZnxSliceSizeImpl<B: Backend> {
fn slice_size(&self) -> usize;
}
pub trait ZnxSliceSize {
/// Returns the slice size, which is the offset between
/// two size of the same column.
fn sl(&self) -> usize;
}
pub trait DataView {
type D: Data;
fn data(&self) -> &Self::D;
}
pub trait DataViewMut: DataView {
fn data_mut(&mut self) -> &mut Self::D;
}
pub trait ZnxView: ZnxInfos + DataView<D: DataRef> {
type Scalar: Copy + Zero;
/// Returns a non-mutable pointer to the underlying coefficients array.
fn as_ptr(&self) -> *const Self::Scalar {
self.data().as_ref().as_ptr() as *const Self::Scalar
}
/// Returns a non-mutable reference to the entire underlying coefficient array.
fn raw(&self) -> &[Self::Scalar] {
unsafe { std::slice::from_raw_parts(self.as_ptr(), self.n() * self.poly_count()) }
}
/// Returns a non-mutable pointer starting at the j-th small polynomial of the i-th column.
fn at_ptr(&self, i: usize, j: usize) -> *const Self::Scalar {
#[cfg(debug_assertions)]
{
assert!(i < self.cols(), "cols: {} >= {}", i, self.cols());
assert!(j < self.size(), "size: {} >= {}", j, self.size());
}
let offset: usize = self.n() * (j * self.cols() + i);
unsafe { self.as_ptr().add(offset) }
}
/// Returns non-mutable reference to the (i, j)-th small polynomial.
fn at(&self, i: usize, j: usize) -> &[Self::Scalar] {
unsafe { std::slice::from_raw_parts(self.at_ptr(i, j), self.n()) }
}
}
pub trait ZnxViewMut: ZnxView + DataViewMut<D: DataMut> {
/// Returns a mutable pointer to the underlying coefficients array.
fn as_mut_ptr(&mut self) -> *mut Self::Scalar {
self.data_mut().as_mut().as_mut_ptr() as *mut Self::Scalar
}
/// Returns a mutable reference to the entire underlying coefficient array.
fn raw_mut(&mut self) -> &mut [Self::Scalar] {
unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), self.n() * self.poly_count()) }
}
/// Returns a mutable pointer starting at the j-th small polynomial of the i-th column.
fn at_mut_ptr(&mut self, i: usize, j: usize) -> *mut Self::Scalar {
#[cfg(debug_assertions)]
{
assert!(i < self.cols(), "cols: {} >= {}", i, self.cols());
assert!(j < self.size(), "size: {} >= {}", j, self.size());
}
let offset: usize = self.n() * (j * self.cols() + i);
unsafe { self.as_mut_ptr().add(offset) }
}
/// Returns mutable reference to the (i, j)-th small polynomial.
fn at_mut(&mut self, i: usize, j: usize) -> &mut [Self::Scalar] {
unsafe { std::slice::from_raw_parts_mut(self.at_mut_ptr(i, j), self.n()) }
}
}
//(Jay)Note: Can't provide blanket impl. of ZnxView because Scalar is not known
impl<T> ZnxViewMut for T where T: ZnxView + DataViewMut<D: DataMut> {}
pub trait ZnxZero
where
Self: Sized,
{
fn zero(&mut self);
fn zero_at(&mut self, i: usize, j: usize);
}
pub trait FillUniform {
fn fill_uniform(&mut self, source: &mut Source);
}
pub trait Reset {
fn reset(&mut self);
}

View File

@@ -0,0 +1,7 @@
mod module;
mod scratch;
mod svp_ppol;
mod vec_znx;
mod vec_znx_big;
mod vec_znx_dft;
mod vmp_pmat;

View File

@@ -0,0 +1,14 @@
use crate::{
api::ModuleNew,
layouts::{Backend, Module},
oep::ModuleNewImpl,
};
impl<B> ModuleNew<B> for Module<B>
where
B: Backend + ModuleNewImpl<B>,
{
fn new(n: u64) -> Self {
B::new_impl(n)
}
}

View File

@@ -0,0 +1,235 @@
use crate::{
api::{
ScratchAvailable, ScratchFromBytes, ScratchOwnedAlloc, ScratchOwnedBorrow, TakeLike, TakeMatZnx, TakeScalarZnx,
TakeSlice, TakeSvpPPol, TakeVecZnx, TakeVecZnxBig, TakeVecZnxDft, TakeVecZnxDftSlice, TakeVecZnxSlice, TakeVmpPMat,
},
layouts::{Backend, DataRef, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat},
oep::{
ScratchAvailableImpl, ScratchFromBytesImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeLikeImpl, TakeMatZnxImpl,
TakeScalarZnxImpl, TakeSliceImpl, TakeSvpPPolImpl, TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxDftSliceImpl,
TakeVecZnxImpl, TakeVecZnxSliceImpl, TakeVmpPMatImpl,
},
};
impl<B> ScratchOwnedAlloc<B> for ScratchOwned<B>
where
B: Backend + ScratchOwnedAllocImpl<B>,
{
fn alloc(size: usize) -> Self {
B::scratch_owned_alloc_impl(size)
}
}
impl<B> ScratchOwnedBorrow<B> for ScratchOwned<B>
where
B: Backend + ScratchOwnedBorrowImpl<B>,
{
fn borrow(&mut self) -> &mut Scratch<B> {
B::scratch_owned_borrow_impl(self)
}
}
impl<B> ScratchFromBytes<B> for Scratch<B>
where
B: Backend + ScratchFromBytesImpl<B>,
{
fn from_bytes(data: &mut [u8]) -> &mut Scratch<B> {
B::scratch_from_bytes_impl(data)
}
}
impl<B> ScratchAvailable for Scratch<B>
where
B: Backend + ScratchAvailableImpl<B>,
{
fn available(&self) -> usize {
B::scratch_available_impl(self)
}
}
impl<B> TakeSlice for Scratch<B>
where
B: Backend + TakeSliceImpl<B>,
{
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)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, ScalarZnx<D>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, ScalarZnx<D>, Output = ScalarZnx<&'a mut [u8]>>,
D: DataRef,
{
type Output = ScalarZnx<&'a mut [u8]>;
fn take_like(&'a mut self, template: &ScalarZnx<D>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, SvpPPol<D, B>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, SvpPPol<D, B>, Output = SvpPPol<&'a mut [u8], B>>,
D: DataRef,
{
type Output = SvpPPol<&'a mut [u8], B>;
fn take_like(&'a mut self, template: &SvpPPol<D, B>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, VecZnx<D>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, VecZnx<D>, Output = VecZnx<&'a mut [u8]>>,
D: DataRef,
{
type Output = VecZnx<&'a mut [u8]>;
fn take_like(&'a mut self, template: &VecZnx<D>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, VecZnxBig<D, B>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, VecZnxBig<D, B>, Output = VecZnxBig<&'a mut [u8], B>>,
D: DataRef,
{
type Output = VecZnxBig<&'a mut [u8], B>;
fn take_like(&'a mut self, template: &VecZnxBig<D, B>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, VecZnxDft<D, B>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, VecZnxDft<D, B>, Output = VecZnxDft<&'a mut [u8], B>>,
D: DataRef,
{
type Output = VecZnxDft<&'a mut [u8], B>;
fn take_like(&'a mut self, template: &VecZnxDft<D, B>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, MatZnx<D>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, MatZnx<D>, Output = MatZnx<&'a mut [u8]>>,
D: DataRef,
{
type Output = MatZnx<&'a mut [u8]>;
fn take_like(&'a mut self, template: &MatZnx<D>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}
impl<'a, B: Backend, D> TakeLike<'a, B, VmpPMat<D, B>> for Scratch<B>
where
B: TakeLikeImpl<'a, B, VmpPMat<D, B>, Output = VmpPMat<&'a mut [u8], B>>,
D: DataRef,
{
type Output = VmpPMat<&'a mut [u8], B>;
fn take_like(&'a mut self, template: &VmpPMat<D, B>) -> (Self::Output, &'a mut Self) {
B::take_like_impl(self, template)
}
}

View File

@@ -0,0 +1,72 @@
use crate::{
api::{SvpApply, SvpApplyInplace, SvpPPolAlloc, SvpPPolAllocBytes, SvpPPolFromBytes, SvpPrepare},
layouts::{Backend, Module, ScalarZnxToRef, SvpPPolOwned, SvpPPolToMut, SvpPPolToRef, VecZnxDftToMut, VecZnxDftToRef},
oep::{SvpApplyImpl, SvpApplyInplaceImpl, SvpPPolAllocBytesImpl, SvpPPolAllocImpl, SvpPPolFromBytesImpl, SvpPrepareImpl},
};
impl<B> SvpPPolFromBytes<B> for Module<B>
where
B: Backend + SvpPPolFromBytesImpl<B>,
{
fn svp_ppol_from_bytes(&self, n: usize, cols: usize, bytes: Vec<u8>) -> SvpPPolOwned<B> {
B::svp_ppol_from_bytes_impl(n, cols, bytes)
}
}
impl<B> SvpPPolAlloc<B> for Module<B>
where
B: Backend + SvpPPolAllocImpl<B>,
{
fn svp_ppol_alloc(&self, n: usize, cols: usize) -> SvpPPolOwned<B> {
B::svp_ppol_alloc_impl(n, cols)
}
}
impl<B> SvpPPolAllocBytes for Module<B>
where
B: Backend + SvpPPolAllocBytesImpl<B>,
{
fn svp_ppol_alloc_bytes(&self, n: usize, cols: usize) -> usize {
B::svp_ppol_alloc_bytes_impl(n, cols)
}
}
impl<B> SvpPrepare<B> for Module<B>
where
B: Backend + SvpPrepareImpl<B>,
{
fn svp_prepare<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: SvpPPolToMut<B>,
A: ScalarZnxToRef,
{
B::svp_prepare_impl(self, res, res_col, a, a_col);
}
}
impl<B> SvpApply<B> for Module<B>
where
B: Backend + SvpApplyImpl<B>,
{
fn svp_apply<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: SvpPPolToRef<B>,
C: VecZnxDftToRef<B>,
{
B::svp_apply_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> SvpApplyInplace<B> for Module<B>
where
B: Backend + SvpApplyInplaceImpl,
{
fn svp_apply_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: SvpPPolToRef<B>,
{
B::svp_apply_inplace_impl(self, res, res_col, a, a_col);
}
}

View File

@@ -0,0 +1,414 @@
use crate::{
api::{
VecZnxAdd, VecZnxAddDistF64, VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxAutomorphism,
VecZnxAutomorphismInplace, VecZnxCopy, VecZnxFillDistF64, VecZnxFillNormal, VecZnxFillUniform, VecZnxLshInplace,
VecZnxMerge, VecZnxMulXpMinusOne, VecZnxMulXpMinusOneInplace, VecZnxNegate, VecZnxNegateInplace, VecZnxNormalize,
VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxRotate, VecZnxRotateInplace, VecZnxRshInplace, VecZnxSplit,
VecZnxSub, VecZnxSubABInplace, VecZnxSubBAInplace, VecZnxSubScalarInplace, VecZnxSwithcDegree,
},
layouts::{Backend, Module, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef},
oep::{
VecZnxAddDistF64Impl, VecZnxAddImpl, VecZnxAddInplaceImpl, VecZnxAddNormalImpl, VecZnxAddScalarInplaceImpl,
VecZnxAutomorphismImpl, VecZnxAutomorphismInplaceImpl, VecZnxCopyImpl, VecZnxFillDistF64Impl, VecZnxFillNormalImpl,
VecZnxFillUniformImpl, VecZnxLshInplaceImpl, VecZnxMergeImpl, VecZnxMulXpMinusOneImpl, VecZnxMulXpMinusOneInplaceImpl,
VecZnxNegateImpl, VecZnxNegateInplaceImpl, VecZnxNormalizeImpl, VecZnxNormalizeInplaceImpl, VecZnxNormalizeTmpBytesImpl,
VecZnxRotateImpl, VecZnxRotateInplaceImpl, VecZnxRshInplaceImpl, VecZnxSplitImpl, VecZnxSubABInplaceImpl,
VecZnxSubBAInplaceImpl, VecZnxSubImpl, VecZnxSubScalarInplaceImpl, VecZnxSwithcDegreeImpl,
},
source::Source,
};
impl<B> VecZnxNormalizeTmpBytes for Module<B>
where
B: Backend + VecZnxNormalizeTmpBytesImpl<B>,
{
fn vec_znx_normalize_tmp_bytes(&self, n: usize) -> usize {
B::vec_znx_normalize_tmp_bytes_impl(self, n)
}
}
impl<B> VecZnxNormalize<B> for Module<B>
where
B: Backend + VecZnxNormalizeImpl<B>,
{
fn vec_znx_normalize<R, A>(&self, basek: usize, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_normalize_impl(self, basek, res, res_col, a, a_col, scratch)
}
}
impl<B> VecZnxNormalizeInplace<B> for Module<B>
where
B: Backend + VecZnxNormalizeInplaceImpl<B>,
{
fn vec_znx_normalize_inplace<A>(&self, basek: usize, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxToMut,
{
B::vec_znx_normalize_inplace_impl(self, basek, a, a_col, scratch)
}
}
impl<B> VecZnxAdd for Module<B>
where
B: Backend + VecZnxAddImpl<B>,
{
fn vec_znx_add<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
C: VecZnxToRef,
{
B::vec_znx_add_impl(self, res, res_col, a, a_col, b, b_col)
}
}
impl<B> VecZnxAddInplace for Module<B>
where
B: Backend + VecZnxAddInplaceImpl<B>,
{
fn vec_znx_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_add_inplace_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxAddScalarInplace for Module<B>
where
B: Backend + VecZnxAddScalarInplaceImpl<B>,
{
fn vec_znx_add_scalar_inplace<R, A>(&self, res: &mut R, res_col: usize, res_limb: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: ScalarZnxToRef,
{
B::vec_znx_add_scalar_inplace_impl(self, res, res_col, res_limb, a, a_col)
}
}
impl<B> VecZnxSub for Module<B>
where
B: Backend + VecZnxSubImpl<B>,
{
fn vec_znx_sub<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
C: VecZnxToRef,
{
B::vec_znx_sub_impl(self, res, res_col, a, a_col, b, b_col)
}
}
impl<B> VecZnxSubABInplace for Module<B>
where
B: Backend + VecZnxSubABInplaceImpl<B>,
{
fn vec_znx_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_sub_ab_inplace_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxSubBAInplace for Module<B>
where
B: Backend + VecZnxSubBAInplaceImpl<B>,
{
fn vec_znx_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_sub_ba_inplace_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxSubScalarInplace for Module<B>
where
B: Backend + VecZnxSubScalarInplaceImpl<B>,
{
fn vec_znx_sub_scalar_inplace<R, A>(&self, res: &mut R, res_col: usize, res_limb: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: ScalarZnxToRef,
{
B::vec_znx_sub_scalar_inplace_impl(self, res, res_col, res_limb, a, a_col)
}
}
impl<B> VecZnxNegate for Module<B>
where
B: Backend + VecZnxNegateImpl<B>,
{
fn vec_znx_negate<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_negate_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxNegateInplace for Module<B>
where
B: Backend + VecZnxNegateInplaceImpl<B>,
{
fn vec_znx_negate_inplace<A>(&self, a: &mut A, a_col: usize)
where
A: VecZnxToMut,
{
B::vec_znx_negate_inplace_impl(self, a, a_col)
}
}
impl<B> VecZnxLshInplace for Module<B>
where
B: Backend + VecZnxLshInplaceImpl<B>,
{
fn vec_znx_lsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A)
where
A: VecZnxToMut,
{
B::vec_znx_lsh_inplace_impl(self, basek, k, a)
}
}
impl<B> VecZnxRshInplace for Module<B>
where
B: Backend + VecZnxRshInplaceImpl<B>,
{
fn vec_znx_rsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A)
where
A: VecZnxToMut,
{
B::vec_znx_rsh_inplace_impl(self, basek, k, a)
}
}
impl<B> VecZnxRotate for Module<B>
where
B: Backend + VecZnxRotateImpl<B>,
{
fn vec_znx_rotate<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_rotate_impl(self, k, res, res_col, a, a_col)
}
}
impl<B> VecZnxRotateInplace for Module<B>
where
B: Backend + VecZnxRotateInplaceImpl<B>,
{
fn vec_znx_rotate_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxToMut,
{
B::vec_znx_rotate_inplace_impl(self, k, a, a_col)
}
}
impl<B> VecZnxAutomorphism for Module<B>
where
B: Backend + VecZnxAutomorphismImpl<B>,
{
fn vec_znx_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_automorphism_impl(self, k, res, res_col, a, a_col)
}
}
impl<B> VecZnxAutomorphismInplace for Module<B>
where
B: Backend + VecZnxAutomorphismInplaceImpl<B>,
{
fn vec_znx_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxToMut,
{
B::vec_znx_automorphism_inplace_impl(self, k, a, a_col)
}
}
impl<B> VecZnxMulXpMinusOne for Module<B>
where
B: Backend + VecZnxMulXpMinusOneImpl<B>,
{
fn vec_znx_mul_xp_minus_one<R, A>(&self, p: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_mul_xp_minus_one_impl(self, p, res, res_col, a, a_col);
}
}
impl<B> VecZnxMulXpMinusOneInplace for Module<B>
where
B: Backend + VecZnxMulXpMinusOneInplaceImpl<B>,
{
fn vec_znx_mul_xp_minus_one_inplace<R>(&self, p: i64, res: &mut R, res_col: usize)
where
R: VecZnxToMut,
{
B::vec_znx_mul_xp_minus_one_inplace_impl(self, p, res, res_col);
}
}
impl<B> VecZnxSplit<B> for Module<B>
where
B: Backend + VecZnxSplitImpl<B>,
{
fn vec_znx_split<R, A>(&self, res: &mut [R], res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_split_impl(self, res, res_col, a, a_col, scratch)
}
}
impl<B> VecZnxMerge for Module<B>
where
B: Backend + VecZnxMergeImpl<B>,
{
fn vec_znx_merge<R, A>(&self, res: &mut R, res_col: usize, a: &[A], a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_merge_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxSwithcDegree for Module<B>
where
B: Backend + VecZnxSwithcDegreeImpl<B>,
{
fn vec_znx_switch_degree<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_switch_degree_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxCopy for Module<B>
where
B: Backend + VecZnxCopyImpl<B>,
{
fn vec_znx_copy<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
{
B::vec_znx_copy_impl(self, res, res_col, a, a_col)
}
}
impl<B> VecZnxFillUniform for Module<B>
where
B: Backend + VecZnxFillUniformImpl<B>,
{
fn vec_znx_fill_uniform<R>(&self, basek: usize, res: &mut R, res_col: usize, k: usize, source: &mut Source)
where
R: VecZnxToMut,
{
B::vec_znx_fill_uniform_impl(self, basek, res, res_col, k, source);
}
}
impl<B> VecZnxFillDistF64 for Module<B>
where
B: Backend + VecZnxFillDistF64Impl<B>,
{
fn vec_znx_fill_dist_f64<R, D: rand::prelude::Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: VecZnxToMut,
{
B::vec_znx_fill_dist_f64_impl(self, basek, res, res_col, k, source, dist, bound);
}
}
impl<B> VecZnxAddDistF64 for Module<B>
where
B: Backend + VecZnxAddDistF64Impl<B>,
{
fn vec_znx_add_dist_f64<R, D: rand::prelude::Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: VecZnxToMut,
{
B::vec_znx_add_dist_f64_impl(self, basek, res, res_col, k, source, dist, bound);
}
}
impl<B> VecZnxFillNormal for Module<B>
where
B: Backend + VecZnxFillNormalImpl<B>,
{
fn vec_znx_fill_normal<R>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) where
R: VecZnxToMut,
{
B::vec_znx_fill_normal_impl(self, basek, res, res_col, k, source, sigma, bound);
}
}
impl<B> VecZnxAddNormal for Module<B>
where
B: Backend + VecZnxAddNormalImpl<B>,
{
fn vec_znx_add_normal<R>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) where
R: VecZnxToMut,
{
B::vec_znx_add_normal_impl(self, basek, res, res_col, k, source, sigma, bound);
}
}

View File

@@ -0,0 +1,334 @@
use rand_distr::Distribution;
use crate::{
api::{
VecZnxBigAdd, VecZnxBigAddDistF64, VecZnxBigAddInplace, VecZnxBigAddNormal, VecZnxBigAddSmall, VecZnxBigAddSmallInplace,
VecZnxBigAlloc, VecZnxBigAllocBytes, VecZnxBigAutomorphism, VecZnxBigAutomorphismInplace, VecZnxBigFillDistF64,
VecZnxBigFillNormal, VecZnxBigFromBytes, VecZnxBigNegateInplace, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
VecZnxBigSub, VecZnxBigSubABInplace, VecZnxBigSubBAInplace, VecZnxBigSubSmallA, VecZnxBigSubSmallAInplace,
VecZnxBigSubSmallB, VecZnxBigSubSmallBInplace,
},
layouts::{Backend, Module, Scratch, VecZnxBigOwned, VecZnxBigToMut, VecZnxBigToRef, VecZnxToMut, VecZnxToRef},
oep::{
VecZnxBigAddDistF64Impl, VecZnxBigAddImpl, VecZnxBigAddInplaceImpl, VecZnxBigAddNormalImpl, VecZnxBigAddSmallImpl,
VecZnxBigAddSmallInplaceImpl, VecZnxBigAllocBytesImpl, VecZnxBigAllocImpl, VecZnxBigAutomorphismImpl,
VecZnxBigAutomorphismInplaceImpl, VecZnxBigFillDistF64Impl, VecZnxBigFillNormalImpl, VecZnxBigFromBytesImpl,
VecZnxBigNegateInplaceImpl, VecZnxBigNormalizeImpl, VecZnxBigNormalizeTmpBytesImpl, VecZnxBigSubABInplaceImpl,
VecZnxBigSubBAInplaceImpl, VecZnxBigSubImpl, VecZnxBigSubSmallAImpl, VecZnxBigSubSmallAInplaceImpl,
VecZnxBigSubSmallBImpl, VecZnxBigSubSmallBInplaceImpl,
},
source::Source,
};
impl<B> VecZnxBigAlloc<B> for Module<B>
where
B: Backend + VecZnxBigAllocImpl<B>,
{
fn vec_znx_big_alloc(&self, n: usize, cols: usize, size: usize) -> VecZnxBigOwned<B> {
B::vec_znx_big_alloc_impl(n, cols, size)
}
}
impl<B> VecZnxBigFromBytes<B> for Module<B>
where
B: Backend + VecZnxBigFromBytesImpl<B>,
{
fn vec_znx_big_from_bytes(&self, n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<B> {
B::vec_znx_big_from_bytes_impl(n, cols, size, bytes)
}
}
impl<B> VecZnxBigAllocBytes for Module<B>
where
B: Backend + VecZnxBigAllocBytesImpl<B>,
{
fn vec_znx_big_alloc_bytes(&self, n: usize, cols: usize, size: usize) -> usize {
B::vec_znx_big_alloc_bytes_impl(n, cols, size)
}
}
impl<B> VecZnxBigAddDistF64<B> for Module<B>
where
B: Backend + VecZnxBigAddDistF64Impl<B>,
{
fn vec_znx_big_add_dist_f64<R: VecZnxBigToMut<B>, D: Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) {
B::add_dist_f64_impl(self, basek, res, res_col, k, source, dist, bound);
}
}
impl<B> VecZnxBigAddNormal<B> for Module<B>
where
B: Backend + VecZnxBigAddNormalImpl<B>,
{
fn vec_znx_big_add_normal<R: VecZnxBigToMut<B>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) {
B::add_normal_impl(self, basek, res, res_col, k, source, sigma, bound);
}
}
impl<B> VecZnxBigFillDistF64<B> for Module<B>
where
B: Backend + VecZnxBigFillDistF64Impl<B>,
{
fn vec_znx_big_fill_dist_f64<R: VecZnxBigToMut<B>, D: Distribution<f64>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) {
B::fill_dist_f64_impl(self, basek, res, res_col, k, source, dist, bound);
}
}
impl<B> VecZnxBigFillNormal<B> for Module<B>
where
B: Backend + VecZnxBigFillNormalImpl<B>,
{
fn vec_znx_big_fill_normal<R: VecZnxBigToMut<B>>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) {
B::fill_normal_impl(self, basek, res, res_col, k, source, sigma, bound);
}
}
impl<B> VecZnxBigAdd<B> for Module<B>
where
B: Backend + VecZnxBigAddImpl<B>,
{
fn vec_znx_big_add<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxBigToRef<B>,
{
B::vec_znx_big_add_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxBigAddInplace<B> for Module<B>
where
B: Backend + VecZnxBigAddInplaceImpl<B>,
{
fn vec_znx_big_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
{
B::vec_znx_big_add_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigAddSmall<B> for Module<B>
where
B: Backend + VecZnxBigAddSmallImpl<B>,
{
fn vec_znx_big_add_small<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxToRef,
{
B::vec_znx_big_add_small_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxBigAddSmallInplace<B> for Module<B>
where
B: Backend + VecZnxBigAddSmallInplaceImpl<B>,
{
fn vec_znx_big_add_small_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef,
{
B::vec_znx_big_add_small_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigSub<B> for Module<B>
where
B: Backend + VecZnxBigSubImpl<B>,
{
fn vec_znx_big_sub<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxBigToRef<B>,
{
B::vec_znx_big_sub_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxBigSubABInplace<B> for Module<B>
where
B: Backend + VecZnxBigSubABInplaceImpl<B>,
{
fn vec_znx_big_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
{
B::vec_znx_big_sub_ab_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigSubBAInplace<B> for Module<B>
where
B: Backend + VecZnxBigSubBAInplaceImpl<B>,
{
fn vec_znx_big_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
{
B::vec_znx_big_sub_ba_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigSubSmallA<B> for Module<B>
where
B: Backend + VecZnxBigSubSmallAImpl<B>,
{
fn vec_znx_big_sub_small_a<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef,
C: VecZnxBigToRef<B>,
{
B::vec_znx_big_sub_small_a_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxBigSubSmallAInplace<B> for Module<B>
where
B: Backend + VecZnxBigSubSmallAInplaceImpl<B>,
{
fn vec_znx_big_sub_small_a_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef,
{
B::vec_znx_big_sub_small_a_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigSubSmallB<B> for Module<B>
where
B: Backend + VecZnxBigSubSmallBImpl<B>,
{
fn vec_znx_big_sub_small_b<R, A, C>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxToRef,
{
B::vec_znx_big_sub_small_b_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxBigSubSmallBInplace<B> for Module<B>
where
B: Backend + VecZnxBigSubSmallBInplaceImpl<B>,
{
fn vec_znx_big_sub_small_b_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef,
{
B::vec_znx_big_sub_small_b_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigNegateInplace<B> for Module<B>
where
B: Backend + VecZnxBigNegateInplaceImpl<B>,
{
fn vec_znx_big_negate_inplace<A>(&self, a: &mut A, a_col: usize)
where
A: VecZnxBigToMut<B>,
{
B::vec_znx_big_negate_inplace_impl(self, a, a_col);
}
}
impl<B> VecZnxBigNormalizeTmpBytes for Module<B>
where
B: Backend + VecZnxBigNormalizeTmpBytesImpl<B>,
{
fn vec_znx_big_normalize_tmp_bytes(&self, n: usize) -> usize {
B::vec_znx_big_normalize_tmp_bytes_impl(self, n)
}
}
impl<B> VecZnxBigNormalize<B> for Module<B>
where
B: Backend + VecZnxBigNormalizeImpl<B>,
{
fn vec_znx_big_normalize<R, A>(
&self,
basek: usize,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
scratch: &mut Scratch<B>,
) where
R: VecZnxToMut,
A: VecZnxBigToRef<B>,
{
B::vec_znx_big_normalize_impl(self, basek, res, res_col, a, a_col, scratch);
}
}
impl<B> VecZnxBigAutomorphism<B> for Module<B>
where
B: Backend + VecZnxBigAutomorphismImpl<B>,
{
fn vec_znx_big_automorphism<R, A>(&self, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
{
B::vec_znx_big_automorphism_impl(self, k, res, res_col, a, a_col);
}
}
impl<B> VecZnxBigAutomorphismInplace<B> for Module<B>
where
B: Backend + VecZnxBigAutomorphismInplaceImpl<B>,
{
fn vec_znx_big_automorphism_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxBigToMut<B>,
{
B::vec_znx_big_automorphism_inplace_impl(self, k, a, a_col);
}
}

View File

@@ -0,0 +1,196 @@
use crate::{
api::{
VecZnxDftAdd, VecZnxDftAddInplace, VecZnxDftAlloc, VecZnxDftAllocBytes, VecZnxDftCopy, VecZnxDftFromBytes,
VecZnxDftFromVecZnx, VecZnxDftSub, VecZnxDftSubABInplace, VecZnxDftSubBAInplace, VecZnxDftToVecZnxBig,
VecZnxDftToVecZnxBigConsume, VecZnxDftToVecZnxBigTmpA, VecZnxDftToVecZnxBigTmpBytes, VecZnxDftZero,
},
layouts::{
Backend, Data, Module, Scratch, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftOwned, VecZnxDftToMut, VecZnxDftToRef,
VecZnxToRef,
},
oep::{
VecZnxDftAddImpl, VecZnxDftAddInplaceImpl, VecZnxDftAllocBytesImpl, VecZnxDftAllocImpl, VecZnxDftCopyImpl,
VecZnxDftFromBytesImpl, VecZnxDftFromVecZnxImpl, VecZnxDftSubABInplaceImpl, VecZnxDftSubBAInplaceImpl, VecZnxDftSubImpl,
VecZnxDftToVecZnxBigConsumeImpl, VecZnxDftToVecZnxBigImpl, VecZnxDftToVecZnxBigTmpAImpl,
VecZnxDftToVecZnxBigTmpBytesImpl, VecZnxDftZeroImpl,
},
};
impl<B> VecZnxDftFromBytes<B> for Module<B>
where
B: Backend + VecZnxDftFromBytesImpl<B>,
{
fn vec_znx_dft_from_bytes(&self, n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B> {
B::vec_znx_dft_from_bytes_impl(n, cols, size, bytes)
}
}
impl<B> VecZnxDftAllocBytes for Module<B>
where
B: Backend + VecZnxDftAllocBytesImpl<B>,
{
fn vec_znx_dft_alloc_bytes(&self, n: usize, cols: usize, size: usize) -> usize {
B::vec_znx_dft_alloc_bytes_impl(n, cols, size)
}
}
impl<B> VecZnxDftAlloc<B> for Module<B>
where
B: Backend + VecZnxDftAllocImpl<B>,
{
fn vec_znx_dft_alloc(&self, n: usize, cols: usize, size: usize) -> VecZnxDftOwned<B> {
B::vec_znx_dft_alloc_impl(n, cols, size)
}
}
impl<B> VecZnxDftToVecZnxBigTmpBytes for Module<B>
where
B: Backend + VecZnxDftToVecZnxBigTmpBytesImpl<B>,
{
fn vec_znx_dft_to_vec_znx_big_tmp_bytes(&self, n: usize) -> usize {
B::vec_znx_dft_to_vec_znx_big_tmp_bytes_impl(self, n)
}
}
impl<B> VecZnxDftToVecZnxBig<B> for Module<B>
where
B: Backend + VecZnxDftToVecZnxBigImpl<B>,
{
fn vec_znx_dft_to_vec_znx_big<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxBigToMut<B>,
A: VecZnxDftToRef<B>,
{
B::vec_znx_dft_to_vec_znx_big_impl(self, res, res_col, a, a_col, scratch);
}
}
impl<B> VecZnxDftToVecZnxBigTmpA<B> for Module<B>
where
B: Backend + VecZnxDftToVecZnxBigTmpAImpl<B>,
{
fn vec_znx_dft_to_vec_znx_big_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxDftToMut<B>,
{
B::vec_znx_dft_to_vec_znx_big_tmp_a_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxDftToVecZnxBigConsume<B> for Module<B>
where
B: Backend + VecZnxDftToVecZnxBigConsumeImpl<B>,
{
fn vec_znx_dft_to_vec_znx_big_consume<D: Data>(&self, a: VecZnxDft<D, B>) -> VecZnxBig<D, B>
where
VecZnxDft<D, B>: VecZnxDftToMut<B>,
{
B::vec_znx_dft_to_vec_znx_big_consume_impl(self, a)
}
}
impl<B> VecZnxDftFromVecZnx<B> for Module<B>
where
B: Backend + VecZnxDftFromVecZnxImpl<B>,
{
fn vec_znx_dft_from_vec_znx<R, A>(&self, step: usize, offset: usize, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxToRef,
{
B::vec_znx_dft_from_vec_znx_impl(self, step, offset, res, res_col, a, a_col);
}
}
impl<B> VecZnxDftAdd<B> for Module<B>
where
B: Backend + VecZnxDftAddImpl<B>,
{
fn vec_znx_dft_add<R, A, D>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
D: VecZnxDftToRef<B>,
{
B::vec_znx_dft_add_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxDftAddInplace<B> for Module<B>
where
B: Backend + VecZnxDftAddInplaceImpl<B>,
{
fn vec_znx_dft_add_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
{
B::vec_znx_dft_add_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxDftSub<B> for Module<B>
where
B: Backend + VecZnxDftSubImpl<B>,
{
fn vec_znx_dft_sub<R, A, D>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
D: VecZnxDftToRef<B>,
{
B::vec_znx_dft_sub_impl(self, res, res_col, a, a_col, b, b_col);
}
}
impl<B> VecZnxDftSubABInplace<B> for Module<B>
where
B: Backend + VecZnxDftSubABInplaceImpl<B>,
{
fn vec_znx_dft_sub_ab_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
{
B::vec_znx_dft_sub_ab_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxDftSubBAInplace<B> for Module<B>
where
B: Backend + VecZnxDftSubBAInplaceImpl<B>,
{
fn vec_znx_dft_sub_ba_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
{
B::vec_znx_dft_sub_ba_inplace_impl(self, res, res_col, a, a_col);
}
}
impl<B> VecZnxDftCopy<B> for Module<B>
where
B: Backend + VecZnxDftCopyImpl<B>,
{
fn vec_znx_dft_copy<R, A>(&self, step: usize, offset: usize, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
{
B::vec_znx_dft_copy_impl(self, step, offset, res, res_col, a, a_col);
}
}
impl<B> VecZnxDftZero<B> for Module<B>
where
B: Backend + VecZnxDftZeroImpl<B>,
{
fn vec_znx_dft_zero<R>(&self, res: &mut R)
where
R: VecZnxDftToMut<B>,
{
B::vec_znx_dft_zero_impl(self, res);
}
}

View File

@@ -0,0 +1,136 @@
use crate::{
api::{
VmpApply, VmpApplyAdd, VmpApplyAddTmpBytes, VmpApplyTmpBytes, VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatFromBytes,
VmpPrepare, VmpPrepareTmpBytes,
},
layouts::{Backend, MatZnxToRef, Module, Scratch, VecZnxDftToMut, VecZnxDftToRef, VmpPMatOwned, VmpPMatToMut, VmpPMatToRef},
oep::{
VmpApplyAddImpl, VmpApplyAddTmpBytesImpl, VmpApplyImpl, VmpApplyTmpBytesImpl, VmpPMatAllocBytesImpl, VmpPMatAllocImpl,
VmpPMatFromBytesImpl, VmpPMatPrepareImpl, VmpPrepareTmpBytesImpl,
},
};
impl<B> VmpPMatAlloc<B> for Module<B>
where
B: Backend + VmpPMatAllocImpl<B>,
{
fn vmp_pmat_alloc(&self, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> VmpPMatOwned<B> {
B::vmp_pmat_alloc_impl(n, rows, cols_in, cols_out, size)
}
}
impl<B> VmpPMatAllocBytes for Module<B>
where
B: Backend + VmpPMatAllocBytesImpl<B>,
{
fn vmp_pmat_alloc_bytes(&self, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize {
B::vmp_pmat_alloc_bytes_impl(n, rows, cols_in, cols_out, size)
}
}
impl<B> VmpPMatFromBytes<B> for Module<B>
where
B: Backend + VmpPMatFromBytesImpl<B>,
{
fn vmp_pmat_from_bytes(
&self,
n: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
size: usize,
bytes: Vec<u8>,
) -> VmpPMatOwned<B> {
B::vmp_pmat_from_bytes_impl(n, rows, cols_in, cols_out, size, bytes)
}
}
impl<B> VmpPrepareTmpBytes for Module<B>
where
B: Backend + VmpPrepareTmpBytesImpl<B>,
{
fn vmp_prepare_tmp_bytes(&self, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> usize {
B::vmp_prepare_tmp_bytes_impl(self, n, rows, cols_in, cols_out, size)
}
}
impl<B> VmpPrepare<B> for Module<B>
where
B: Backend + VmpPMatPrepareImpl<B>,
{
fn vmp_prepare<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<B>)
where
R: VmpPMatToMut<B>,
A: MatZnxToRef,
{
B::vmp_prepare_impl(self, res, a, scratch)
}
}
impl<B> VmpApplyTmpBytes for Module<B>
where
B: Backend + VmpApplyTmpBytesImpl<B>,
{
fn vmp_apply_tmp_bytes(
&self,
n: usize,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize {
B::vmp_apply_tmp_bytes_impl(
self, n, res_size, a_size, b_rows, b_cols_in, b_cols_out, b_size,
)
}
}
impl<B> VmpApply<B> for Module<B>
where
B: Backend + VmpApplyImpl<B>,
{
fn vmp_apply<R, A, C>(&self, res: &mut R, a: &A, b: &C, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
C: VmpPMatToRef<B>,
{
B::vmp_apply_impl(self, res, a, b, scratch);
}
}
impl<B> VmpApplyAddTmpBytes for Module<B>
where
B: Backend + VmpApplyAddTmpBytesImpl<B>,
{
fn vmp_apply_add_tmp_bytes(
&self,
n: usize,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize {
B::vmp_apply_add_tmp_bytes_impl(
self, n, res_size, a_size, b_rows, b_cols_in, b_cols_out, b_size,
)
}
}
impl<B> VmpApplyAdd<B> for Module<B>
where
B: Backend + VmpApplyAddImpl<B>,
{
fn vmp_apply_add<R, A, C>(&self, res: &mut R, a: &A, b: &C, scale: usize, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
C: VmpPMatToRef<B>,
{
B::vmp_apply_add_impl(self, res, a, b, scale, scratch);
}
}

View File

@@ -0,0 +1,204 @@
use itertools::izip;
use rug::{Assign, Float};
use crate::{
api::{ZnxInfos, ZnxView, ZnxViewMut, ZnxZero},
layouts::{DataMut, DataRef, VecZnx, VecZnxToMut, VecZnxToRef},
};
impl<D: DataMut> VecZnx<D> {
pub fn encode_vec_i64(&mut self, basek: usize, col: usize, k: usize, data: &[i64], log_max: usize) {
let size: usize = k.div_ceil(basek);
#[cfg(debug_assertions)]
{
let a: VecZnx<&mut [u8]> = self.to_mut();
assert!(
size <= a.size(),
"invalid argument k.div_ceil(basek)={} > a.size()={}",
size,
a.size()
);
assert!(col < a.cols());
assert!(data.len() <= a.n())
}
let data_len: usize = data.len();
let mut a: VecZnx<&mut [u8]> = self.to_mut();
let k_rem: usize = basek - (k % basek);
// Zeroes coefficients of the i-th column
(0..a.size()).for_each(|i| {
a.zero_at(col, i);
});
// If 2^{basek} * 2^{k_rem} < 2^{63}-1, then we can simply copy
// values on the last limb.
// Else we decompose values base2k.
if log_max + k_rem < 63 || k_rem == basek {
a.at_mut(col, size - 1)[..data_len].copy_from_slice(&data[..data_len]);
} else {
let mask: i64 = (1 << basek) - 1;
let steps: usize = size.min(log_max.div_ceil(basek));
(size - steps..size)
.rev()
.enumerate()
.for_each(|(i, i_rev)| {
let shift: usize = i * basek;
izip!(a.at_mut(col, i_rev).iter_mut(), data.iter()).for_each(|(y, x)| *y = (x >> shift) & mask);
})
}
// Case where self.prec % self.k != 0.
if k_rem != basek {
let steps: usize = size.min(log_max.div_ceil(basek));
(size - steps..size).rev().for_each(|i| {
a.at_mut(col, i)[..data_len]
.iter_mut()
.for_each(|x| *x <<= k_rem);
})
}
}
pub fn encode_coeff_i64(&mut self, basek: usize, col: usize, k: usize, idx: usize, data: i64, log_max: usize) {
let size: usize = k.div_ceil(basek);
#[cfg(debug_assertions)]
{
let a: VecZnx<&mut [u8]> = self.to_mut();
assert!(idx < a.n());
assert!(
size <= a.size(),
"invalid argument k.div_ceil(basek)={} > a.size()={}",
size,
a.size()
);
assert!(col < a.cols());
}
let k_rem: usize = basek - (k % basek);
let mut a: VecZnx<&mut [u8]> = self.to_mut();
(0..a.size()).for_each(|j| a.at_mut(col, j)[idx] = 0);
// If 2^{basek} * 2^{k_rem} < 2^{63}-1, then we can simply copy
// values on the last limb.
// Else we decompose values base2k.
if log_max + k_rem < 63 || k_rem == basek {
a.at_mut(col, size - 1)[idx] = data;
} else {
let mask: i64 = (1 << basek) - 1;
let steps: usize = size.min(log_max.div_ceil(basek));
(size - steps..size)
.rev()
.enumerate()
.for_each(|(j, j_rev)| {
a.at_mut(col, j_rev)[idx] = (data >> (j * basek)) & mask;
})
}
// Case where prec % k != 0.
if k_rem != basek {
let steps: usize = size.min(log_max.div_ceil(basek));
(size - steps..size).rev().for_each(|j| {
a.at_mut(col, j)[idx] <<= k_rem;
})
}
}
}
impl<D: DataRef> VecZnx<D> {
pub fn decode_vec_i64(&self, basek: usize, col: usize, k: usize, data: &mut [i64]) {
let size: usize = k.div_ceil(basek);
#[cfg(debug_assertions)]
{
let a: VecZnx<&[u8]> = self.to_ref();
assert!(
data.len() >= a.n(),
"invalid data: data.len()={} < a.n()={}",
data.len(),
a.n()
);
assert!(col < a.cols());
}
let a: VecZnx<&[u8]> = self.to_ref();
data.copy_from_slice(a.at(col, 0));
let rem: usize = basek - (k % basek);
if k < basek {
data.iter_mut().for_each(|x| *x >>= rem);
} else {
(1..size).for_each(|i| {
if i == size - 1 && rem != basek {
let k_rem: usize = basek - rem;
izip!(a.at(col, i).iter(), data.iter_mut()).for_each(|(x, y)| {
*y = (*y << k_rem) + (x >> rem);
});
} else {
izip!(a.at(col, i).iter(), data.iter_mut()).for_each(|(x, y)| {
*y = (*y << basek) + x;
});
}
})
}
}
pub fn decode_coeff_i64(&self, basek: usize, col: usize, k: usize, idx: usize) -> i64 {
#[cfg(debug_assertions)]
{
let a: VecZnx<&[u8]> = self.to_ref();
assert!(idx < a.n());
assert!(col < a.cols())
}
let a: VecZnx<&[u8]> = self.to_ref();
let size: usize = k.div_ceil(basek);
let mut res: i64 = 0;
let rem: usize = basek - (k % basek);
(0..size).for_each(|j| {
let x: i64 = a.at(col, j)[idx];
if j == size - 1 && rem != basek {
let k_rem: usize = basek - rem;
res = (res << k_rem) + (x >> rem);
} else {
res = (res << basek) + x;
}
});
res
}
pub fn decode_vec_float(&self, basek: usize, col: usize, data: &mut [Float]) {
#[cfg(debug_assertions)]
{
let a: VecZnx<&[u8]> = self.to_ref();
assert!(
data.len() >= a.n(),
"invalid data: data.len()={} < a.n()={}",
data.len(),
a.n()
);
assert!(col < a.cols());
}
let a: VecZnx<&[u8]> = self.to_ref();
let size: usize = a.size();
let prec: u32 = (basek * size) as u32;
// 2^{basek}
let base = Float::with_val(prec, (1 << basek) as f64);
// y[i] = sum x[j][i] * 2^{-basek*j}
(0..size).for_each(|i| {
if i == 0 {
izip!(a.at(col, size - i - 1).iter(), data.iter_mut()).for_each(|(x, y)| {
y.assign(*x);
*y /= &base;
});
} else {
izip!(a.at(col, size - i - 1).iter(), data.iter_mut()).for_each(|(x, y)| {
*y += Float::with_val(prec, *x);
*y /= &base;
});
}
});
}
}

View File

@@ -0,0 +1,304 @@
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, FillUniform, Reset, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
layouts::{Data, DataMut, DataRef, ReaderFrom, ToOwnedDeep, VecZnx, WriterTo},
source::Source,
};
use std::fmt;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use rand::RngCore;
#[derive(PartialEq, Eq, Clone)]
pub struct MatZnx<D: Data> {
data: D,
n: usize,
size: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
}
impl<D: DataRef> ToOwnedDeep for MatZnx<D> {
type Owned = MatZnx<Vec<u8>>;
fn to_owned_deep(&self) -> Self::Owned {
MatZnx {
data: self.data.as_ref().to_vec(),
n: self.n,
size: self.size,
rows: self.rows,
cols_in: self.cols_in,
cols_out: self.cols_out,
}
}
}
impl<D: DataRef> fmt::Debug for MatZnx<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: Data> ZnxInfos for MatZnx<D> {
fn cols(&self) -> usize {
self.cols_in
}
fn rows(&self) -> usize {
self.rows
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
self.size
}
}
impl<D: Data> ZnxSliceSize for MatZnx<D> {
fn sl(&self) -> usize {
self.n() * self.cols_out()
}
}
impl<D: Data> DataView for MatZnx<D> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data> DataViewMut for MatZnx<D> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: DataRef> ZnxView for MatZnx<D> {
type Scalar = i64;
}
impl<D: Data> MatZnx<D> {
pub fn cols_in(&self) -> usize {
self.cols_in
}
pub fn cols_out(&self) -> usize {
self.cols_out
}
}
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 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));
Self {
data,
n,
size,
rows,
cols_in,
cols_out,
}
}
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));
Self {
data,
n,
size,
rows,
cols_in,
cols_out,
}
}
}
impl<D: DataRef> MatZnx<D> {
pub fn at(&self, row: usize, col: usize) -> VecZnx<&[u8]> {
#[cfg(debug_assertions)]
{
assert!(row < self.rows(), "rows: {} >= {}", row, self.rows());
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 start: usize = nb_bytes * self.cols() * row + col * nb_bytes;
let end: usize = start + nb_bytes;
VecZnx {
data: &self_ref.data[start..end],
n: self.n,
cols: self.cols_out,
size: self.size,
max_size: self.size,
}
}
}
impl<D: DataMut> MatZnx<D> {
pub fn at_mut(&mut self, row: usize, col: usize) -> VecZnx<&mut [u8]> {
#[cfg(debug_assertions)]
{
assert!(row < self.rows(), "rows: {} >= {}", row, self.rows());
assert!(col < self.cols_in(), "cols: {} >= {}", col, self.cols_in());
}
let n: usize = self.n();
let cols_out: usize = self.cols_out();
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 start: usize = nb_bytes * cols_in * row + col * nb_bytes;
let end: usize = start + nb_bytes;
VecZnx {
data: &mut self_ref.data[start..end],
n,
cols: cols_out,
size,
max_size: size,
}
}
}
impl<D: DataMut> FillUniform for MatZnx<D> {
fn fill_uniform(&mut self, source: &mut Source) {
source.fill_bytes(self.data.as_mut());
}
}
impl<D: DataMut> Reset for MatZnx<D> {
fn reset(&mut self) {
self.zero();
self.n = 0;
self.size = 0;
self.rows = 0;
self.cols_in = 0;
self.cols_out = 0;
}
}
pub type MatZnxOwned = MatZnx<Vec<u8>>;
pub type MatZnxMut<'a> = MatZnx<&'a mut [u8]>;
pub type MatZnxRef<'a> = MatZnx<&'a [u8]>;
pub trait MatZnxToRef {
fn to_ref(&self) -> MatZnx<&[u8]>;
}
impl<D: DataRef> MatZnxToRef for MatZnx<D> {
fn to_ref(&self) -> MatZnx<&[u8]> {
MatZnx {
data: self.data.as_ref(),
n: self.n,
rows: self.rows,
cols_in: self.cols_in,
cols_out: self.cols_out,
size: self.size,
}
}
}
pub trait MatZnxToMut {
fn to_mut(&mut self) -> MatZnx<&mut [u8]>;
}
impl<D: DataMut> MatZnxToMut for MatZnx<D> {
fn to_mut(&mut self) -> MatZnx<&mut [u8]> {
MatZnx {
data: self.data.as_mut(),
n: self.n,
rows: self.rows,
cols_in: self.cols_in,
cols_out: self.cols_out,
size: self.size,
}
}
}
impl<D: Data> MatZnx<D> {
pub fn from_data(data: D, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
Self {
data,
n,
rows,
cols_in,
cols_out,
size,
}
}
}
impl<D: DataMut> ReaderFrom for MatZnx<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.n = reader.read_u64::<LittleEndian>()? as usize;
self.size = reader.read_u64::<LittleEndian>()? as usize;
self.rows = reader.read_u64::<LittleEndian>()? as usize;
self.cols_in = reader.read_u64::<LittleEndian>()? as usize;
self.cols_out = reader.read_u64::<LittleEndian>()? as usize;
let len: usize = reader.read_u64::<LittleEndian>()? as usize;
let buf: &mut [u8] = self.data.as_mut();
if buf.len() != len {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!("self.data.len()={} != read len={}", buf.len(), len),
));
}
reader.read_exact(&mut buf[..len])?;
Ok(())
}
}
impl<D: DataRef> WriterTo for MatZnx<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u64::<LittleEndian>(self.n as u64)?;
writer.write_u64::<LittleEndian>(self.size as u64)?;
writer.write_u64::<LittleEndian>(self.rows as u64)?;
writer.write_u64::<LittleEndian>(self.cols_in as u64)?;
writer.write_u64::<LittleEndian>(self.cols_out as u64)?;
let buf: &[u8] = self.data.as_ref();
writer.write_u64::<LittleEndian>(buf.len() as u64)?;
writer.write_all(buf)?;
Ok(())
}
}
impl<D: DataRef> fmt::Display for MatZnx<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"MatZnx(n={}, rows={}, cols_in={}, cols_out={}, size={})",
self.n, self.rows, self.cols_in, self.cols_out, self.size
)?;
for row_i in 0..self.rows {
writeln!(f, "Row {}:", row_i)?;
for col_i in 0..self.cols_in {
writeln!(f, "cols_in {}:", col_i)?;
writeln!(f, "{}:", self.at(row_i, col_i))?;
}
}
Ok(())
}
}
impl<D: DataMut> ZnxZero for MatZnx<D> {
fn zero(&mut self) {
self.raw_mut().fill(0)
}
fn zero_at(&mut self, i: usize, j: usize) {
self.at_mut(i, j).zero();
}
}

View File

@@ -0,0 +1,32 @@
mod encoding;
mod mat_znx;
mod module;
mod scalar_znx;
mod scratch;
mod serialization;
mod stats;
mod svp_ppol;
mod vec_znx;
mod vec_znx_big;
mod vec_znx_dft;
mod vmp_pmat;
pub use mat_znx::*;
pub use module::*;
pub use scalar_znx::*;
pub use scratch::*;
pub use serialization::*;
pub use svp_ppol::*;
pub use vec_znx::*;
pub use vec_znx_big::*;
pub use vec_znx_dft::*;
pub use vmp_pmat::*;
pub trait Data = PartialEq + Eq + Sized;
pub trait DataRef = Data + AsRef<[u8]>;
pub trait DataMut = DataRef + AsMut<[u8]>;
pub trait ToOwnedDeep {
type Owned;
fn to_owned_deep(&self) -> Self::Owned;
}

View File

@@ -0,0 +1,103 @@
use std::{fmt::Display, marker::PhantomData, ptr::NonNull};
use rand_distr::num_traits::Zero;
use crate::GALOISGENERATOR;
#[allow(clippy::missing_safety_doc)]
pub trait Backend: Sized {
type ScalarBig: Copy + Zero + Display;
type ScalarPrep: Copy + Zero + Display;
type Handle: 'static;
fn layout_prep_word_count() -> usize;
fn layout_big_word_count() -> usize;
unsafe fn destroy(handle: NonNull<Self::Handle>);
}
pub struct Module<B: Backend> {
ptr: NonNull<B::Handle>,
n: u64,
_marker: PhantomData<B>,
}
impl<B: Backend> Module<B> {
/// Construct from a raw pointer managed elsewhere.
/// SAFETY: `ptr` must be non-null and remain valid for the lifetime of this Module.
#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn from_raw_parts(ptr: *mut B::Handle, n: u64) -> Self {
Self {
ptr: NonNull::new(ptr).expect("null module ptr"),
n,
_marker: PhantomData,
}
}
#[allow(clippy::missing_safety_doc)]
#[inline]
pub unsafe fn ptr(&self) -> *mut <B as Backend>::Handle {
self.ptr.as_ptr()
}
#[inline]
pub fn n(&self) -> usize {
self.n as usize
}
#[inline]
pub fn as_mut_ptr(&self) -> *mut B::Handle {
self.ptr.as_ptr()
}
#[inline]
pub fn log_n(&self) -> usize {
(usize::BITS - (self.n() - 1).leading_zeros()) as _
}
#[inline]
pub fn cyclotomic_order(&self) -> u64 {
(self.n() << 1) as _
}
// Returns GALOISGENERATOR^|generator| * sign(generator)
#[inline]
pub fn galois_element(&self, generator: i64) -> i64 {
if generator == 0 {
return 1;
}
((mod_exp_u64(GALOISGENERATOR, generator.unsigned_abs() as usize) & (self.cyclotomic_order() - 1)) as i64)
* generator.signum()
}
// Returns gen^-1
#[inline]
pub fn galois_element_inv(&self, gal_el: i64) -> i64 {
if gal_el == 0 {
panic!("cannot invert 0")
}
((mod_exp_u64(
gal_el.unsigned_abs(),
(self.cyclotomic_order() - 1) as usize,
) & (self.cyclotomic_order() - 1)) as i64)
* gal_el.signum()
}
}
impl<B: Backend> Drop for Module<B> {
fn drop(&mut self) {
unsafe { B::destroy(self.ptr) }
}
}
pub fn mod_exp_u64(x: u64, e: usize) -> u64 {
let mut y: u64 = 1;
let mut x_pow: u64 = x;
let mut exp = e;
while exp > 0 {
if exp & 1 == 1 {
y = y.wrapping_mul(x_pow);
}
x_pow = x_pow.wrapping_mul(x_pow);
exp >>= 1;
}
y
}

View File

@@ -0,0 +1,247 @@
use rand::seq::SliceRandom;
use rand_core::RngCore;
use rand_distr::{Distribution, weighted::WeightedIndex};
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, FillUniform, Reset, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
layouts::{Data, DataMut, DataRef, ReaderFrom, ToOwnedDeep, VecZnx, WriterTo},
source::Source,
};
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ScalarZnx<D: Data> {
pub data: D,
pub n: usize,
pub cols: usize,
}
impl<D: DataRef> ToOwnedDeep for ScalarZnx<D> {
type Owned = ScalarZnx<Vec<u8>>;
fn to_owned_deep(&self) -> Self::Owned {
ScalarZnx {
data: self.data.as_ref().to_vec(),
n: self.n,
cols: self.cols,
}
}
}
impl<D: Data> ZnxInfos for ScalarZnx<D> {
fn cols(&self) -> usize {
self.cols
}
fn rows(&self) -> usize {
1
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
1
}
}
impl<D: Data> ZnxSliceSize for ScalarZnx<D> {
fn sl(&self) -> usize {
self.n()
}
}
impl<D: Data> DataView for ScalarZnx<D> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data> DataViewMut for ScalarZnx<D> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: DataRef> ZnxView for ScalarZnx<D> {
type Scalar = i64;
}
impl<D: DataMut> ScalarZnx<D> {
pub fn fill_ternary_prob(&mut self, col: usize, prob: f64, source: &mut Source) {
let choices: [i64; 3] = [-1, 0, 1];
let weights: [f64; 3] = [prob / 2.0, 1.0 - prob, prob / 2.0];
let dist: WeightedIndex<f64> = WeightedIndex::new(weights).unwrap();
self.at_mut(col, 0)
.iter_mut()
.for_each(|x: &mut i64| *x = choices[dist.sample(source)]);
}
pub fn fill_ternary_hw(&mut self, col: usize, hw: usize, source: &mut Source) {
assert!(hw <= self.n());
self.at_mut(col, 0)[..hw]
.iter_mut()
.for_each(|x: &mut i64| *x = (((source.next_u32() & 1) as i64) << 1) - 1);
self.at_mut(col, 0).shuffle(source);
}
pub fn fill_binary_prob(&mut self, col: usize, prob: f64, source: &mut Source) {
let choices: [i64; 2] = [0, 1];
let weights: [f64; 2] = [1.0 - prob, prob];
let dist: WeightedIndex<f64> = WeightedIndex::new(weights).unwrap();
self.at_mut(col, 0)
.iter_mut()
.for_each(|x: &mut i64| *x = choices[dist.sample(source)]);
}
pub fn fill_binary_hw(&mut self, col: usize, hw: usize, source: &mut Source) {
assert!(hw <= self.n());
self.at_mut(col, 0)[..hw]
.iter_mut()
.for_each(|x: &mut i64| *x = (source.next_u32() & 1) as i64);
self.at_mut(col, 0).shuffle(source);
}
pub fn fill_binary_block(&mut self, col: usize, block_size: usize, source: &mut Source) {
assert!(self.n().is_multiple_of(block_size));
let max_idx: u64 = (block_size + 1) as u64;
let mask_idx: u64 = (1 << ((u64::BITS - max_idx.leading_zeros()) as u64)) - 1;
for block in self.at_mut(col, 0).chunks_mut(block_size) {
let idx: usize = source.next_u64n(max_idx, mask_idx) as usize;
if idx != block_size {
block[idx] = 1;
}
}
}
}
impl ScalarZnx<Vec<u8>> {
pub fn alloc_bytes(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));
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));
Self { data, n, cols }
}
}
impl<D: DataMut> ZnxZero for ScalarZnx<D> {
fn zero(&mut self) {
self.raw_mut().fill(0)
}
fn zero_at(&mut self, i: usize, j: usize) {
self.at_mut(i, j).fill(0);
}
}
impl<D: DataMut> FillUniform for ScalarZnx<D> {
fn fill_uniform(&mut self, source: &mut Source) {
source.fill_bytes(self.data.as_mut());
}
}
impl<D: DataMut> Reset for ScalarZnx<D> {
fn reset(&mut self) {
self.zero();
self.n = 0;
self.cols = 0;
}
}
pub type ScalarZnxOwned = ScalarZnx<Vec<u8>>;
impl<D: Data> ScalarZnx<D> {
pub fn from_data(data: D, n: usize, cols: usize) -> Self {
Self { data, n, cols }
}
}
pub trait ScalarZnxToRef {
fn to_ref(&self) -> ScalarZnx<&[u8]>;
}
impl<D: DataRef> ScalarZnxToRef for ScalarZnx<D> {
fn to_ref(&self) -> ScalarZnx<&[u8]> {
ScalarZnx {
data: self.data.as_ref(),
n: self.n,
cols: self.cols,
}
}
}
pub trait ScalarZnxToMut {
fn to_mut(&mut self) -> ScalarZnx<&mut [u8]>;
}
impl<D: DataMut> ScalarZnxToMut for ScalarZnx<D> {
fn to_mut(&mut self) -> ScalarZnx<&mut [u8]> {
ScalarZnx {
data: self.data.as_mut(),
n: self.n,
cols: self.cols,
}
}
}
impl<D: DataRef> ScalarZnx<D> {
pub fn as_vec_znx(&self) -> VecZnx<&[u8]> {
VecZnx {
data: self.data.as_ref(),
n: self.n,
cols: self.cols,
size: 1,
max_size: 1,
}
}
}
impl<D: DataMut> ScalarZnx<D> {
pub fn as_vec_znx_mut(&mut self) -> VecZnx<&mut [u8]> {
VecZnx {
data: self.data.as_mut(),
n: self.n,
cols: self.cols,
size: 1,
max_size: 1,
}
}
}
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
impl<D: DataMut> ReaderFrom for ScalarZnx<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.n = reader.read_u64::<LittleEndian>()? as usize;
self.cols = reader.read_u64::<LittleEndian>()? as usize;
let len: usize = reader.read_u64::<LittleEndian>()? as usize;
let buf: &mut [u8] = self.data.as_mut();
if buf.len() != len {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!("self.data.len()={} != read len={}", buf.len(), len),
));
}
reader.read_exact(&mut buf[..len])?;
Ok(())
}
}
impl<D: DataRef> WriterTo for ScalarZnx<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u64::<LittleEndian>(self.n as u64)?;
writer.write_u64::<LittleEndian>(self.cols as u64)?;
let buf: &[u8] = self.data.as_ref();
writer.write_u64::<LittleEndian>(buf.len() as u64)?;
writer.write_all(buf)?;
Ok(())
}
}

View File

@@ -0,0 +1,13 @@
use std::marker::PhantomData;
use crate::layouts::Backend;
pub struct ScratchOwned<B: Backend> {
pub data: Vec<u8>,
pub _phantom: PhantomData<B>,
}
pub struct Scratch<B: Backend> {
pub _phantom: PhantomData<B>,
pub data: [u8],
}

View File

@@ -0,0 +1,9 @@
use std::io::{Read, Result, Write};
pub trait WriterTo {
fn write_to<W: Write>(&self, writer: &mut W) -> Result<()>;
}
pub trait ReaderFrom {
fn read_from<R: Read>(&mut self, reader: &mut R) -> Result<()>;
}

View File

@@ -0,0 +1,32 @@
use rug::{
Float,
float::Round,
ops::{AddAssignRound, DivAssignRound, SubAssignRound},
};
use crate::{
api::ZnxInfos,
layouts::{DataRef, VecZnx},
};
impl<D: DataRef> VecZnx<D> {
pub fn std(&self, basek: usize, col: usize) -> f64 {
let prec: u32 = (self.size() * basek) as u32;
let mut data: Vec<Float> = (0..self.n()).map(|_| Float::with_val(prec, 0)).collect();
self.decode_vec_float(basek, col, &mut data);
// std = sqrt(sum((xi - avg)^2) / n)
let mut avg: Float = Float::with_val(prec, 0);
data.iter().for_each(|x| {
avg.add_assign_round(x, Round::Nearest);
});
avg.div_assign_round(Float::with_val(prec, data.len()), Round::Nearest);
data.iter_mut().for_each(|x| {
x.sub_assign_round(&avg, Round::Nearest);
});
let mut std: Float = Float::with_val(prec, 0);
data.iter().for_each(|x| std += x * x);
std.div_assign_round(Float::with_val(prec, data.len()), Round::Nearest);
std = std.sqrt();
std.to_f64()
}
}

View File

@@ -0,0 +1,156 @@
use std::marker::PhantomData;
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, ZnxInfos, ZnxSliceSize, ZnxView},
layouts::{Backend, Data, DataMut, DataRef, ReaderFrom, WriterTo},
oep::SvpPPolAllocBytesImpl,
};
#[derive(PartialEq, Eq)]
pub struct SvpPPol<D: Data, B: Backend> {
pub data: D,
pub n: usize,
pub cols: usize,
pub _phantom: PhantomData<B>,
}
impl<D: Data, B: Backend> ZnxSliceSize for SvpPPol<D, B> {
fn sl(&self) -> usize {
B::layout_prep_word_count() * self.n()
}
}
impl<D: DataRef, B: Backend> ZnxView for SvpPPol<D, B> {
type Scalar = B::ScalarPrep;
}
impl<D: Data, B: Backend> ZnxInfos for SvpPPol<D, B> {
fn cols(&self) -> usize {
self.cols
}
fn rows(&self) -> usize {
1
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
1
}
}
impl<D: Data, B: Backend> DataView for SvpPPol<D, B> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data, B: Backend> DataViewMut for SvpPPol<D, B> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: Data + From<Vec<u8>>, B: Backend> SvpPPol<D, B>
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));
Self {
data: data.into(),
n,
cols,
_phantom: PhantomData,
}
}
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));
Self {
data: data.into(),
n,
cols,
_phantom: PhantomData,
}
}
}
pub type SvpPPolOwned<B> = SvpPPol<Vec<u8>, B>;
pub trait SvpPPolToRef<B: Backend> {
fn to_ref(&self) -> SvpPPol<&[u8], B>;
}
impl<D: DataRef, B: Backend> SvpPPolToRef<B> for SvpPPol<D, B> {
fn to_ref(&self) -> SvpPPol<&[u8], B> {
SvpPPol {
data: self.data.as_ref(),
n: self.n,
cols: self.cols,
_phantom: PhantomData,
}
}
}
pub trait SvpPPolToMut<B: Backend> {
fn to_mut(&mut self) -> SvpPPol<&mut [u8], B>;
}
impl<D: DataMut, B: Backend> SvpPPolToMut<B> for SvpPPol<D, B> {
fn to_mut(&mut self) -> SvpPPol<&mut [u8], B> {
SvpPPol {
data: self.data.as_mut(),
n: self.n,
cols: self.cols,
_phantom: PhantomData,
}
}
}
impl<D: Data, B: Backend> SvpPPol<D, B> {
pub fn from_data(data: D, n: usize, cols: usize) -> Self {
Self {
data,
n,
cols,
_phantom: PhantomData,
}
}
}
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
impl<D: DataMut, B: Backend> ReaderFrom for SvpPPol<D, B> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.n = reader.read_u64::<LittleEndian>()? as usize;
self.cols = reader.read_u64::<LittleEndian>()? as usize;
let len: usize = reader.read_u64::<LittleEndian>()? as usize;
let buf: &mut [u8] = self.data.as_mut();
if buf.len() != len {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!("self.data.len()={} != read len={}", buf.len(), len),
));
}
reader.read_exact(&mut buf[..len])?;
Ok(())
}
}
impl<D: DataRef, B: Backend> WriterTo for SvpPPol<D, B> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u64::<LittleEndian>(self.n as u64)?;
writer.write_u64::<LittleEndian>(self.cols as u64)?;
let buf: &[u8] = self.data.as_ref();
writer.write_u64::<LittleEndian>(buf.len() as u64)?;
writer.write_all(buf)?;
Ok(())
}
}

View File

@@ -0,0 +1,255 @@
use std::fmt;
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, FillUniform, Reset, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
layouts::{Data, DataMut, DataRef, ReaderFrom, ToOwnedDeep, WriterTo},
source::Source,
};
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use rand::RngCore;
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct VecZnx<D: Data> {
pub data: D,
pub n: usize,
pub cols: usize,
pub size: usize,
pub max_size: usize,
}
impl<D: DataRef> ToOwnedDeep for VecZnx<D> {
type Owned = VecZnx<Vec<u8>>;
fn to_owned_deep(&self) -> Self::Owned {
VecZnx {
data: self.data.as_ref().to_vec(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
}
}
}
impl<D: DataRef> fmt::Debug for VecZnx<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl<D: Data> ZnxInfos for VecZnx<D> {
fn cols(&self) -> usize {
self.cols
}
fn rows(&self) -> usize {
1
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
self.size
}
}
impl<D: Data> ZnxSliceSize for VecZnx<D> {
fn sl(&self) -> usize {
self.n() * self.cols()
}
}
impl<D: Data> DataView for VecZnx<D> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data> DataViewMut for VecZnx<D> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: DataRef> ZnxView for VecZnx<D> {
type Scalar = i64;
}
impl VecZnx<Vec<u8>> {
pub fn rsh_scratch_space(n: usize) -> usize {
n * std::mem::size_of::<i64>()
}
}
impl<D: DataMut> ZnxZero for VecZnx<D> {
fn zero(&mut self) {
self.raw_mut().fill(0)
}
fn zero_at(&mut self, i: usize, j: usize) {
self.at_mut(i, j).fill(0);
}
}
impl VecZnx<Vec<u8>> {
pub fn alloc_bytes(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));
Self {
data,
n,
cols,
size,
max_size: size,
}
}
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));
Self {
data,
n,
cols,
size,
max_size: size,
}
}
}
impl<D: Data> VecZnx<D> {
pub fn from_data(data: D, n: usize, cols: usize, size: usize) -> Self {
Self {
data,
n,
cols,
size,
max_size: size,
}
}
}
impl<D: DataRef> fmt::Display for VecZnx<D> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"VecZnx(n={}, cols={}, size={})",
self.n, self.cols, self.size
)?;
for col in 0..self.cols {
writeln!(f, "Column {}:", col)?;
for size in 0..self.size {
let coeffs = self.at(col, size);
write!(f, " Size {}: [", size)?;
let max_show = 100;
let show_count = coeffs.len().min(max_show);
for (i, &coeff) in coeffs.iter().take(show_count).enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", coeff)?;
}
if coeffs.len() > max_show {
write!(f, ", ... ({} more)", coeffs.len() - max_show)?;
}
writeln!(f, "]")?;
}
}
Ok(())
}
}
impl<D: DataMut> FillUniform for VecZnx<D> {
fn fill_uniform(&mut self, source: &mut Source) {
source.fill_bytes(self.data.as_mut());
}
}
impl<D: DataMut> Reset for VecZnx<D> {
fn reset(&mut self) {
self.zero();
self.n = 0;
self.cols = 0;
self.size = 0;
self.max_size = 0;
}
}
pub type VecZnxOwned = VecZnx<Vec<u8>>;
pub type VecZnxMut<'a> = VecZnx<&'a mut [u8]>;
pub type VecZnxRef<'a> = VecZnx<&'a [u8]>;
pub trait VecZnxToRef {
fn to_ref(&self) -> VecZnx<&[u8]>;
}
impl<D: DataRef> VecZnxToRef for VecZnx<D> {
fn to_ref(&self) -> VecZnx<&[u8]> {
VecZnx {
data: self.data.as_ref(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
}
}
}
pub trait VecZnxToMut {
fn to_mut(&mut self) -> VecZnx<&mut [u8]>;
}
impl<D: DataMut> VecZnxToMut for VecZnx<D> {
fn to_mut(&mut self) -> VecZnx<&mut [u8]> {
VecZnx {
data: self.data.as_mut(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
}
}
}
impl<D: DataMut> ReaderFrom for VecZnx<D> {
fn read_from<R: std::io::Read>(&mut self, reader: &mut R) -> std::io::Result<()> {
self.n = reader.read_u64::<LittleEndian>()? as usize;
self.cols = reader.read_u64::<LittleEndian>()? as usize;
self.size = reader.read_u64::<LittleEndian>()? as usize;
self.max_size = reader.read_u64::<LittleEndian>()? as usize;
let len: usize = reader.read_u64::<LittleEndian>()? as usize;
let buf: &mut [u8] = self.data.as_mut();
if buf.len() != len {
return Err(std::io::Error::new(
std::io::ErrorKind::UnexpectedEof,
format!("self.data.len()={} != read len={}", buf.len(), len),
));
}
reader.read_exact(&mut buf[..len])?;
Ok(())
}
}
impl<D: DataRef> WriterTo for VecZnx<D> {
fn write_to<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
writer.write_u64::<LittleEndian>(self.n as u64)?;
writer.write_u64::<LittleEndian>(self.cols as u64)?;
writer.write_u64::<LittleEndian>(self.size as u64)?;
writer.write_u64::<LittleEndian>(self.max_size as u64)?;
let buf: &[u8] = self.data.as_ref();
writer.write_u64::<LittleEndian>(buf.len() as u64)?;
writer.write_all(buf)?;
Ok(())
}
}

View File

@@ -0,0 +1,189 @@
use std::marker::PhantomData;
use rand_distr::num_traits::Zero;
use std::fmt;
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
layouts::{Backend, Data, DataMut, DataRef},
oep::VecZnxBigAllocBytesImpl,
};
#[derive(PartialEq, Eq)]
pub struct VecZnxBig<D: Data, B: Backend> {
pub data: D,
pub n: usize,
pub cols: usize,
pub size: usize,
pub max_size: usize,
pub _phantom: PhantomData<B>,
}
impl<D: Data, B: Backend> ZnxSliceSize for VecZnxBig<D, B> {
fn sl(&self) -> usize {
B::layout_big_word_count() * self.n() * self.cols()
}
}
impl<D: DataRef, B: Backend> ZnxView for VecZnxBig<D, B> {
type Scalar = B::ScalarBig;
}
impl<D: Data, B: Backend> ZnxInfos for VecZnxBig<D, B> {
fn cols(&self) -> usize {
self.cols
}
fn rows(&self) -> usize {
1
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
self.size
}
}
impl<D: Data, B: Backend> DataView for VecZnxBig<D, B> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data, B: Backend> DataViewMut for VecZnxBig<D, B> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: DataMut, B: Backend> ZnxZero for VecZnxBig<D, B>
where
Self: ZnxViewMut,
<Self as ZnxView>::Scalar: Zero + Copy,
{
fn zero(&mut self) {
self.raw_mut().fill(<Self as ZnxView>::Scalar::zero())
}
fn zero_at(&mut self, i: usize, j: usize) {
self.at_mut(i, j).fill(<Self as ZnxView>::Scalar::zero());
}
}
impl<D: DataRef + From<Vec<u8>>, B: Backend> VecZnxBig<D, B>
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));
Self {
data: data.into(),
n,
cols,
size,
max_size: size,
_phantom: PhantomData,
}
}
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));
Self {
data: data.into(),
n,
cols,
size,
max_size: size,
_phantom: PhantomData,
}
}
}
impl<D: Data, B: Backend> VecZnxBig<D, B> {
pub fn from_data(data: D, n: usize, cols: usize, size: usize) -> Self {
Self {
data,
n,
cols,
size,
max_size: size,
_phantom: PhantomData,
}
}
}
pub type VecZnxBigOwned<B> = VecZnxBig<Vec<u8>, B>;
pub trait VecZnxBigToRef<B: Backend> {
fn to_ref(&self) -> VecZnxBig<&[u8], B>;
}
impl<D: DataRef, B: Backend> VecZnxBigToRef<B> for VecZnxBig<D, B> {
fn to_ref(&self) -> VecZnxBig<&[u8], B> {
VecZnxBig {
data: self.data.as_ref(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
_phantom: std::marker::PhantomData,
}
}
}
pub trait VecZnxBigToMut<B: Backend> {
fn to_mut(&mut self) -> VecZnxBig<&mut [u8], B>;
}
impl<D: DataMut, B: Backend> VecZnxBigToMut<B> for VecZnxBig<D, B> {
fn to_mut(&mut self) -> VecZnxBig<&mut [u8], B> {
VecZnxBig {
data: self.data.as_mut(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
_phantom: std::marker::PhantomData,
}
}
}
impl<D: DataRef, B: Backend> fmt::Display for VecZnxBig<D, B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"VecZnxBig(n={}, cols={}, size={})",
self.n, self.cols, self.size
)?;
for col in 0..self.cols {
writeln!(f, "Column {}:", col)?;
for size in 0..self.size {
let coeffs = self.at(col, size);
write!(f, " Size {}: [", size)?;
let max_show = 100;
let show_count = coeffs.len().min(max_show);
for (i, &coeff) in coeffs.iter().take(show_count).enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", coeff)?;
}
if coeffs.len() > max_show {
write!(f, ", ... ({} more)", coeffs.len() - max_show)?;
}
writeln!(f, "]")?;
}
}
Ok(())
}
}

View File

@@ -0,0 +1,206 @@
use std::{fmt, marker::PhantomData};
use rand_distr::num_traits::Zero;
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, ZnxInfos, ZnxSliceSize, ZnxView, ZnxViewMut, ZnxZero},
layouts::{Backend, Data, DataMut, DataRef, VecZnxBig},
oep::VecZnxBigAllocBytesImpl,
};
#[derive(PartialEq, Eq)]
pub struct VecZnxDft<D: Data, B: Backend> {
pub data: D,
pub n: usize,
pub cols: usize,
pub size: usize,
pub max_size: usize,
pub _phantom: PhantomData<B>,
}
impl<D: Data, B: Backend> ZnxSliceSize for VecZnxDft<D, B> {
fn sl(&self) -> usize {
B::layout_prep_word_count() * self.n() * self.cols()
}
}
impl<D: DataRef, B: Backend> ZnxView for VecZnxDft<D, B> {
type Scalar = B::ScalarPrep;
}
impl<D: Data, B: Backend> VecZnxDft<D, B> {
pub fn into_big(self) -> VecZnxBig<D, B> {
VecZnxBig::<D, B>::from_data(self.data, self.n, self.cols, self.size)
}
}
impl<D: Data, B: Backend> ZnxInfos for VecZnxDft<D, B> {
fn cols(&self) -> usize {
self.cols
}
fn rows(&self) -> usize {
1
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
self.size
}
}
impl<D: Data, B: Backend> DataView for VecZnxDft<D, B> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data, B: Backend> DataViewMut for VecZnxDft<D, B> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: DataRef, B: Backend> VecZnxDft<D, B> {
pub fn max_size(&self) -> usize {
self.max_size
}
}
impl<D: DataMut, B: Backend> VecZnxDft<D, B> {
pub fn set_size(&mut self, size: usize) {
assert!(size <= self.max_size);
self.size = size
}
}
impl<D: DataMut, B: Backend> ZnxZero for VecZnxDft<D, B>
where
Self: ZnxViewMut,
<Self as ZnxView>::Scalar: Zero + Copy,
{
fn zero(&mut self) {
self.raw_mut().fill(<Self as ZnxView>::Scalar::zero())
}
fn zero_at(&mut self, i: usize, j: usize) {
self.at_mut(i, j).fill(<Self as ZnxView>::Scalar::zero());
}
}
impl<D: DataRef + From<Vec<u8>>, B: Backend> VecZnxDft<D, B>
where
B: VecZnxBigAllocBytesImpl<B>,
{
pub fn alloc(n: usize, cols: usize, size: usize) -> Self {
let data: Vec<u8> = alloc_aligned::<u8>(B::vec_znx_big_alloc_bytes_impl(n, cols, size));
Self {
data: data.into(),
n,
cols,
size,
max_size: size,
_phantom: PhantomData,
}
}
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));
Self {
data: data.into(),
n,
cols,
size,
max_size: size,
_phantom: PhantomData,
}
}
}
pub type VecZnxDftOwned<B> = VecZnxDft<Vec<u8>, B>;
impl<D: Data, B: Backend> VecZnxDft<D, B> {
pub fn from_data(data: D, n: usize, cols: usize, size: usize) -> Self {
Self {
data,
n,
cols,
size,
max_size: size,
_phantom: PhantomData,
}
}
}
pub trait VecZnxDftToRef<B: Backend> {
fn to_ref(&self) -> VecZnxDft<&[u8], B>;
}
impl<D: DataRef, B: Backend> VecZnxDftToRef<B> for VecZnxDft<D, B> {
fn to_ref(&self) -> VecZnxDft<&[u8], B> {
VecZnxDft {
data: self.data.as_ref(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
_phantom: std::marker::PhantomData,
}
}
}
pub trait VecZnxDftToMut<B: Backend> {
fn to_mut(&mut self) -> VecZnxDft<&mut [u8], B>;
}
impl<D: DataMut, B: Backend> VecZnxDftToMut<B> for VecZnxDft<D, B> {
fn to_mut(&mut self) -> VecZnxDft<&mut [u8], B> {
VecZnxDft {
data: self.data.as_mut(),
n: self.n,
cols: self.cols,
size: self.size,
max_size: self.max_size,
_phantom: std::marker::PhantomData,
}
}
}
impl<D: DataRef, B: Backend> fmt::Display for VecZnxDft<D, B> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"VecZnxDft(n={}, cols={}, size={})",
self.n, self.cols, self.size
)?;
for col in 0..self.cols {
writeln!(f, "Column {}:", col)?;
for size in 0..self.size {
let coeffs = self.at(col, size);
write!(f, " Size {}: [", size)?;
let max_show = 100;
let show_count = coeffs.len().min(max_show);
for (i, &coeff) in coeffs.iter().take(show_count).enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", coeff)?;
}
if coeffs.len() > max_show {
write!(f, ", ... ({} more)", coeffs.len() - max_show)?;
}
writeln!(f, "]")?;
}
}
Ok(())
}
}

View File

@@ -0,0 +1,151 @@
use std::marker::PhantomData;
use crate::{
alloc_aligned,
api::{DataView, DataViewMut, ZnxInfos, ZnxView},
layouts::{Backend, Data, DataMut, DataRef},
oep::VmpPMatAllocBytesImpl,
};
#[derive(PartialEq, Eq)]
pub struct VmpPMat<D: Data, B: Backend> {
data: D,
n: usize,
size: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
_phantom: PhantomData<B>,
}
impl<D: DataRef, B: Backend> ZnxView for VmpPMat<D, B> {
type Scalar = B::ScalarPrep;
}
impl<D: Data, B: Backend> ZnxInfos for VmpPMat<D, B> {
fn cols(&self) -> usize {
self.cols_in
}
fn rows(&self) -> usize {
self.rows
}
fn n(&self) -> usize {
self.n
}
fn size(&self) -> usize {
self.size
}
}
impl<D: Data, B: Backend> DataView for VmpPMat<D, B> {
type D = D;
fn data(&self) -> &Self::D {
&self.data
}
}
impl<D: Data, B: Backend> DataViewMut for VmpPMat<D, B> {
fn data_mut(&mut self) -> &mut Self::D {
&mut self.data
}
}
impl<D: Data, B: Backend> VmpPMat<D, B> {
pub fn cols_in(&self) -> usize {
self.cols_in
}
pub fn cols_out(&self) -> usize {
self.cols_out
}
}
impl<D: DataRef + From<Vec<u8>>, B: Backend> VmpPMat<D, B>
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,
));
Self {
data: data.into(),
n,
size,
rows,
cols_in,
cols_out,
_phantom: PhantomData,
}
}
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));
Self {
data: data.into(),
n,
size,
rows,
cols_in,
cols_out,
_phantom: PhantomData,
}
}
}
pub type VmpPMatOwned<B> = VmpPMat<Vec<u8>, B>;
pub type VmpPMatRef<'a, B> = VmpPMat<&'a [u8], B>;
pub trait VmpPMatToRef<B: Backend> {
fn to_ref(&self) -> VmpPMat<&[u8], B>;
}
impl<D: DataRef, B: Backend> VmpPMatToRef<B> for VmpPMat<D, B> {
fn to_ref(&self) -> VmpPMat<&[u8], B> {
VmpPMat {
data: self.data.as_ref(),
n: self.n,
rows: self.rows,
cols_in: self.cols_in,
cols_out: self.cols_out,
size: self.size,
_phantom: std::marker::PhantomData,
}
}
}
pub trait VmpPMatToMut<B: Backend> {
fn to_mut(&mut self) -> VmpPMat<&mut [u8], B>;
}
impl<D: DataMut, B: Backend> VmpPMatToMut<B> for VmpPMat<D, B> {
fn to_mut(&mut self) -> VmpPMat<&mut [u8], B> {
VmpPMat {
data: self.data.as_mut(),
n: self.n,
rows: self.rows,
cols_in: self.cols_in,
cols_out: self.cols_out,
size: self.size,
_phantom: std::marker::PhantomData,
}
}
}
impl<D: Data, B: Backend> VmpPMat<D, B> {
pub fn from_data(data: D, n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> Self {
Self {
data,
n,
rows,
cols_in,
cols_out,
size,
_phantom: PhantomData,
}
}
}

110
poulpy-hal/src/lib.rs Normal file
View File

@@ -0,0 +1,110 @@
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals, dead_code, improper_ctypes)]
#![deny(rustdoc::broken_intra_doc_links)]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![feature(trait_alias)]
pub mod api;
pub mod delegates;
pub mod layouts;
pub mod oep;
pub mod source;
pub mod tests;
pub mod doc {
#[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/docs/backend_safety_contract.md"))]
pub mod backend_safety {
pub const _PLACEHOLDER: () = ();
}
}
pub const GALOISGENERATOR: u64 = 5;
pub const DEFAULTALIGN: usize = 64;
fn is_aligned_custom<T>(ptr: *const T, align: usize) -> bool {
(ptr as usize).is_multiple_of(align)
}
pub fn is_aligned<T>(ptr: *const T) -> bool {
is_aligned_custom(ptr, DEFAULTALIGN)
}
pub fn assert_alignement<T>(ptr: *const T) {
assert!(
is_aligned(ptr),
"invalid alignement: ensure passed bytes have been allocated with [alloc_aligned_u8] or [alloc_aligned]"
)
}
pub fn cast<T, V>(data: &[T]) -> &[V] {
let ptr: *const V = data.as_ptr() as *const V;
let len: usize = data.len() / size_of::<V>();
unsafe { std::slice::from_raw_parts(ptr, len) }
}
#[allow(clippy::mut_from_ref)]
pub fn cast_mut<T, V>(data: &[T]) -> &mut [V] {
let ptr: *mut V = data.as_ptr() as *mut V;
let len: usize = data.len() / size_of::<V>();
unsafe { std::slice::from_raw_parts_mut(ptr, len) }
}
/// Allocates a block of bytes with a custom alignement.
/// Alignement must be a power of two and size a multiple of the alignement.
/// Allocated memory is initialized to zero.
fn alloc_aligned_custom_u8(size: usize, align: usize) -> Vec<u8> {
assert!(
align.is_power_of_two(),
"Alignment must be a power of two but is {}",
align
);
assert_eq!(
(size * size_of::<u8>()) % align,
0,
"size={} must be a multiple of align={}",
size,
align
);
unsafe {
let layout: std::alloc::Layout = std::alloc::Layout::from_size_align(size, align).expect("Invalid alignment");
let ptr: *mut u8 = std::alloc::alloc(layout);
if ptr.is_null() {
panic!("Memory allocation failed");
}
assert!(
is_aligned_custom(ptr, align),
"Memory allocation at {:p} is not aligned to {} bytes",
ptr,
align
);
// Init allocated memory to zero
std::ptr::write_bytes(ptr, 0, size);
Vec::from_raw_parts(ptr, size, size)
}
}
/// Allocates a block of T aligned with [DEFAULTALIGN].
/// Size of T * size msut be a multiple of [DEFAULTALIGN].
pub fn alloc_aligned_custom<T>(size: usize, align: usize) -> Vec<T> {
assert_eq!(
(size * size_of::<T>()) % (align / size_of::<T>()),
0,
"size={} must be a multiple of align={}",
size,
align
);
let mut vec_u8: Vec<u8> = alloc_aligned_custom_u8(size_of::<T>() * size, align);
let ptr: *mut T = vec_u8.as_mut_ptr() as *mut T;
let len: usize = vec_u8.len() / size_of::<T>();
let cap: usize = vec_u8.capacity() / size_of::<T>();
std::mem::forget(vec_u8);
unsafe { Vec::from_raw_parts(ptr, len, cap) }
}
/// Allocates an aligned vector of size equal to the smallest multiple
/// of [DEFAULTALIGN]/`size_of::<T>`() that is equal or greater to `size`.
pub fn alloc_aligned<T>(size: usize) -> Vec<T> {
alloc_aligned_custom::<T>(
size + (DEFAULTALIGN - (size % (DEFAULTALIGN / size_of::<T>()))) % DEFAULTALIGN,
DEFAULTALIGN,
)
}

15
poulpy-hal/src/oep/mod.rs Normal file
View File

@@ -0,0 +1,15 @@
mod module;
mod scratch;
mod svp_ppol;
mod vec_znx;
mod vec_znx_big;
mod vec_znx_dft;
mod vmp_pmat;
pub use module::*;
pub use scratch::*;
pub use svp_ppol::*;
pub use vec_znx::*;
pub use vec_znx_big::*;
pub use vec_znx_dft::*;
pub use vmp_pmat::*;

View File

@@ -0,0 +1,9 @@
use crate::layouts::{Backend, Module};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait ModuleNewImpl<B: Backend> {
fn new_impl(n: u64) -> Module<B>;
}

View File

@@ -0,0 +1,259 @@
use crate::{
api::ZnxInfos,
layouts::{Backend, DataRef, MatZnx, ScalarZnx, Scratch, ScratchOwned, SvpPPol, VecZnx, VecZnxBig, VecZnxDft, VmpPMat},
};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait ScratchOwnedAllocImpl<B: Backend> {
fn scratch_owned_alloc_impl(size: usize) -> ScratchOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait ScratchOwnedBorrowImpl<B: Backend> {
fn scratch_owned_borrow_impl(scratch: &mut ScratchOwned<B>) -> &mut Scratch<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait ScratchFromBytesImpl<B: Backend> {
fn scratch_from_bytes_impl(data: &mut [u8]) -> &mut Scratch<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait ScratchAvailableImpl<B: Backend> {
fn scratch_available_impl(scratch: &Scratch<B>) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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 TODO for reference code.
/// * See TODO 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>);
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub trait TakeLikeImpl<'a, B: Backend, T> {
type Output;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &T) -> (Self::Output, &'a mut Scratch<B>);
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, VmpPMat<D, B>> for B
where
B: TakeVmpPMatImpl<B>,
D: DataRef,
{
type Output = VmpPMat<&'a mut [u8], B>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &VmpPMat<D, B>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_vmp_pmat_impl(
scratch,
template.n(),
template.rows(),
template.cols_in(),
template.cols_out(),
template.size(),
)
}
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, MatZnx<D>> for B
where
B: TakeMatZnxImpl<B>,
D: DataRef,
{
type Output = MatZnx<&'a mut [u8]>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &MatZnx<D>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_mat_znx_impl(
scratch,
template.n(),
template.rows(),
template.cols_in(),
template.cols_out(),
template.size(),
)
}
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, VecZnxDft<D, B>> for B
where
B: TakeVecZnxDftImpl<B>,
D: DataRef,
{
type Output = VecZnxDft<&'a mut [u8], B>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &VecZnxDft<D, B>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_vec_znx_dft_impl(scratch, template.n(), template.cols(), template.size())
}
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, VecZnxBig<D, B>> for B
where
B: TakeVecZnxBigImpl<B>,
D: DataRef,
{
type Output = VecZnxBig<&'a mut [u8], B>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &VecZnxBig<D, B>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_vec_znx_big_impl(scratch, template.n(), template.cols(), template.size())
}
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, SvpPPol<D, B>> for B
where
B: TakeSvpPPolImpl<B>,
D: DataRef,
{
type Output = SvpPPol<&'a mut [u8], B>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &SvpPPol<D, B>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_svp_ppol_impl(scratch, template.n(), template.cols())
}
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, VecZnx<D>> for B
where
B: TakeVecZnxImpl<B>,
D: DataRef,
{
type Output = VecZnx<&'a mut [u8]>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &VecZnx<D>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_vec_znx_impl(scratch, template.n(), template.cols(), template.size())
}
}
impl<'a, B: Backend, D> TakeLikeImpl<'a, B, ScalarZnx<D>> for B
where
B: TakeScalarZnxImpl<B>,
D: DataRef,
{
type Output = ScalarZnx<&'a mut [u8]>;
fn take_like_impl(scratch: &'a mut Scratch<B>, template: &ScalarZnx<D>) -> (Self::Output, &'a mut Scratch<B>) {
B::take_scalar_znx_impl(scratch, template.n(), template.cols())
}
}

View File

@@ -0,0 +1,59 @@
use crate::layouts::{Backend, Module, ScalarZnxToRef, SvpPPolOwned, SvpPPolToMut, SvpPPolToRef, VecZnxDftToMut, VecZnxDftToRef};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait SvpPPolFromBytesImpl<B: Backend> {
fn svp_ppol_from_bytes_impl(n: usize, cols: usize, bytes: Vec<u8>) -> SvpPPolOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait SvpPPolAllocImpl<B: Backend> {
fn svp_ppol_alloc_impl(n: usize, cols: usize) -> SvpPPolOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO 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;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait SvpPrepareImpl<B: Backend> {
fn svp_prepare_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: SvpPPolToMut<B>,
A: ScalarZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait SvpApplyImpl<B: Backend> {
fn svp_apply_impl<R, A, C>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: SvpPPolToRef<B>,
C: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait SvpApplyInplaceImpl: Backend {
fn svp_apply_inplace_impl<R, A>(module: &Module<Self>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<Self>,
A: SvpPPolToRef<Self>;
}

View File

@@ -0,0 +1,365 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, Module, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef},
source::Source,
};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_normalize_base2k_tmp_bytes_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L245C17-L245C55) for reference code.
/// * See [crate::api::VecZnxNormalizeTmpBytes] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxNormalizeTmpBytesImpl<B: Backend> {
fn vec_znx_normalize_tmp_bytes_impl(module: &Module<B>, n: usize) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_normalize_base2k_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L212) for reference code.
/// * See [crate::api::VecZnxNormalize] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxNormalizeImpl<B: Backend> {
fn vec_znx_normalize_impl<R, A>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
scratch: &mut Scratch<B>,
) where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_normalize_base2k_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L212) for reference code.
/// * See [crate::api::VecZnxNormalizeInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxNormalizeInplaceImpl<B: Backend> {
fn vec_znx_normalize_inplace_impl<A>(module: &Module<B>, basek: usize, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_add_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L86) for reference code.
/// * See [crate::api::VecZnxAdd] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAddImpl<B: Backend> {
fn vec_znx_add_impl<R, A, C>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
C: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_add_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L86) for reference code.
/// * See [crate::api::VecZnxAddInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAddInplaceImpl<B: Backend> {
fn vec_znx_add_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_add_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L86) for reference code.
/// * See [crate::api::VecZnxAddScalarInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAddScalarInplaceImpl<B: Backend> {
fn vec_znx_add_scalar_inplace_impl<R, A>(
module: &Module<B>,
res: &mut R,
res_col: usize,
res_limb: usize,
a: &A,
a_col: usize,
) where
R: VecZnxToMut,
A: ScalarZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_sub_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L125) for reference code.
/// * See [crate::api::VecZnxSub] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxSubImpl<B: Backend> {
fn vec_znx_sub_impl<R, A, C>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef,
C: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_sub_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L125) for reference code.
/// * See [crate::api::VecZnxSubABInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxSubABInplaceImpl<B: Backend> {
fn vec_znx_sub_ab_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_sub_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L125) for reference code.
/// * See [crate::api::VecZnxSubBAInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxSubBAInplaceImpl<B: Backend> {
fn vec_znx_sub_ba_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_sub_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L125) for reference code.
/// * See [crate::api::VecZnxSubScalarInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxSubScalarInplaceImpl<B: Backend> {
fn vec_znx_sub_scalar_inplace_impl<R, A>(
module: &Module<B>,
res: &mut R,
res_col: usize,
res_limb: usize,
a: &A,
a_col: usize,
) where
R: VecZnxToMut,
A: ScalarZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_negate_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L322C13-L322C31) for reference code.
/// * See [crate::api::VecZnxNegate] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxNegateImpl<B: Backend> {
fn vec_znx_negate_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_negate_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L322C13-L322C31) for reference code.
/// * See [crate::api::VecZnxNegateInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxNegateInplaceImpl<B: Backend> {
fn vec_znx_negate_inplace_impl<A>(module: &Module<B>, a: &mut A, a_col: usize)
where
A: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::cpu_spqlios::vec_znx::vec_znx_rsh_inplace_ref] for reference code.
/// * See [crate::api::VecZnxRshInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxRshInplaceImpl<B: Backend> {
fn vec_znx_rsh_inplace_impl<A>(module: &Module<B>, basek: usize, k: usize, a: &mut A)
where
A: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::cpu_spqlios::vec_znx::vec_znx_lsh_inplace_ref] for reference code.
/// * See [crate::api::VecZnxLshInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxLshInplaceImpl<B: Backend> {
fn vec_znx_lsh_inplace_impl<A>(module: &Module<B>, basek: usize, k: usize, a: &mut A)
where
A: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_rotate_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L164) for reference code.
/// * See [crate::api::VecZnxRotate] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxRotateImpl<B: Backend> {
fn vec_znx_rotate_impl<R, A>(module: &Module<B>, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_rotate_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L164) for reference code.
/// * See [crate::api::VecZnxRotateInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxRotateInplaceImpl<B: Backend> {
fn vec_znx_rotate_inplace_impl<A>(module: &Module<B>, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_automorphism_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L188) for reference code.
/// * See [crate::api::VecZnxAutomorphism] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAutomorphismImpl<B: Backend> {
fn vec_znx_automorphism_impl<R, A>(module: &Module<B>, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_automorphism_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/32a3f5fcce9863b58e949f2dfd5abc1bfbaa09b4/spqlios/arithmetic/vec_znx.c#L188) for reference code.
/// * See [crate::api::VecZnxAutomorphismInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAutomorphismInplaceImpl<B: Backend> {
fn vec_znx_automorphism_inplace_impl<A>(module: &Module<B>, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_mul_xp_minus_one_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/7160f588da49712a042931ea247b4259b95cefcc/spqlios/arithmetic/vec_znx.c#L200C13-L200C41) for reference code.
/// * See [crate::api::VecZnxMulXpMinusOne] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxMulXpMinusOneImpl<B: Backend> {
fn vec_znx_mul_xp_minus_one_impl<R, A>(module: &Module<B>, p: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [vec_znx_mul_xp_minus_one_ref](https://github.com/phantomzone-org/spqlios-arithmetic/blob/7160f588da49712a042931ea247b4259b95cefcc/spqlios/arithmetic/vec_znx.c#L200C13-L200C41) for reference code.
/// * See [crate::api::VecZnxMulXpMinusOneInplace] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxMulXpMinusOneInplaceImpl<B: Backend> {
fn vec_znx_mul_xp_minus_one_inplace_impl<R>(module: &Module<B>, p: i64, res: &mut R, res_col: usize)
where
R: VecZnxToMut;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::cpu_spqlios::vec_znx::vec_znx_split_ref] for reference code.
/// * See [crate::api::VecZnxSplit] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxSplitImpl<B: Backend> {
fn vec_znx_split_impl<R, A>(module: &Module<B>, res: &mut [R], res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::cpu_spqlios::vec_znx::vec_znx_merge_ref] for reference code.
/// * See [crate::api::VecZnxMerge] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxMergeImpl<B: Backend> {
fn vec_znx_merge_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &[A], a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::cpu_spqlios::vec_znx::vec_znx_switch_degree_ref] for reference code.
/// * See [crate::api::VecZnxSwithcDegree] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxSwithcDegreeImpl<B: Backend> {
fn vec_znx_switch_degree_impl<R: VecZnxToMut, A: VecZnxToRef>(
module: &Module<B>,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
);
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::cpu_spqlios::vec_znx::vec_znx_copy_ref] for reference code.
/// * See [crate::api::VecZnxCopy] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxCopyImpl<B: Backend> {
fn vec_znx_copy_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::api::VecZnxFillUniform] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxFillUniformImpl<B: Backend> {
fn vec_znx_fill_uniform_impl<R>(module: &Module<B>, basek: usize, res: &mut R, res_col: usize, k: usize, source: &mut Source)
where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::api::VecZnxFillDistF64] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxFillDistF64Impl<B: Backend> {
fn vec_znx_fill_dist_f64_impl<R, D: Distribution<f64>>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::api::VecZnxAddDistF64] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAddDistF64Impl<B: Backend> {
fn vec_znx_add_dist_f64_impl<R, D: Distribution<f64>>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::api::VecZnxFillNormal] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxFillNormalImpl<B: Backend> {
fn vec_znx_fill_normal_impl<R>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) where
R: VecZnxToMut;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See [crate::api::VecZnxAddNormal] for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxAddNormalImpl<B: Backend> {
fn vec_znx_add_normal_impl<R>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
) where
R: VecZnxToMut;
}

View File

@@ -0,0 +1,306 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, Module, Scratch, VecZnxBigOwned, VecZnxBigToMut, VecZnxBigToRef, VecZnxToMut, VecZnxToRef},
source::Source,
};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAllocImpl<B: Backend> {
fn vec_znx_big_alloc_impl(n: usize, cols: usize, size: usize) -> VecZnxBigOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigFromBytesImpl<B: Backend> {
fn vec_znx_big_from_bytes_impl(n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxBigOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO 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;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAddNormalImpl<B: Backend> {
fn add_normal_impl<R: VecZnxBigToMut<B>>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
);
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigFillNormalImpl<B: Backend> {
fn fill_normal_impl<R: VecZnxBigToMut<B>>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
sigma: f64,
bound: f64,
);
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigFillDistF64Impl<B: Backend> {
fn fill_dist_f64_impl<R: VecZnxBigToMut<B>, D: Distribution<f64>>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
);
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAddDistF64Impl<B: Backend> {
fn add_dist_f64_impl<R: VecZnxBigToMut<B>, D: Distribution<f64>>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
);
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAddImpl<B: Backend> {
fn vec_znx_big_add_impl<R, A, C>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAddInplaceImpl<B: Backend> {
fn vec_znx_big_add_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAddSmallImpl<B: Backend> {
fn vec_znx_big_add_small_impl<R, A, C>(
module: &Module<B>,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
b: &C,
b_col: usize,
) where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAddSmallInplaceImpl<B: Backend> {
fn vec_znx_big_add_small_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubImpl<B: Backend> {
fn vec_znx_big_sub_impl<R, A, C>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &C, b_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubABInplaceImpl<B: Backend> {
fn vec_znx_big_sub_ab_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubBAInplaceImpl<B: Backend> {
fn vec_znx_big_sub_ba_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubSmallAImpl<B: Backend> {
fn vec_znx_big_sub_small_a_impl<R, A, C>(
module: &Module<B>,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
b: &C,
b_col: usize,
) where
R: VecZnxBigToMut<B>,
A: VecZnxToRef,
C: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubSmallAInplaceImpl<B: Backend> {
fn vec_znx_big_sub_small_a_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubSmallBImpl<B: Backend> {
fn vec_znx_big_sub_small_b_impl<R, A, C>(
module: &Module<B>,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
b: &C,
b_col: usize,
) where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>,
C: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigSubSmallBInplaceImpl<B: Backend> {
fn vec_znx_big_sub_small_b_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigNegateInplaceImpl<B: Backend> {
fn vec_znx_big_negate_inplace_impl<A>(module: &Module<B>, a: &mut A, a_col: usize)
where
A: VecZnxBigToMut<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigNormalizeTmpBytesImpl<B: Backend> {
fn vec_znx_big_normalize_tmp_bytes_impl(module: &Module<B>, n: usize) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigNormalizeImpl<B: Backend> {
fn vec_znx_big_normalize_impl<R, A>(
module: &Module<B>,
basek: usize,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
scratch: &mut Scratch<B>,
) where
R: VecZnxToMut,
A: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAutomorphismImpl<B: Backend> {
fn vec_znx_big_automorphism_impl<R, A>(module: &Module<B>, k: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxBigAutomorphismInplaceImpl<B: Backend> {
fn vec_znx_big_automorphism_inplace_impl<A>(module: &Module<B>, k: i64, a: &mut A, a_col: usize)
where
A: VecZnxBigToMut<B>;
}

View File

@@ -0,0 +1,177 @@
use crate::layouts::{
Backend, Data, Module, Scratch, VecZnxBig, VecZnxBigToMut, VecZnxDft, VecZnxDftOwned, VecZnxDftToMut, VecZnxDftToRef,
VecZnxToRef,
};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftAllocImpl<B: Backend> {
fn vec_znx_dft_alloc_impl(n: usize, cols: usize, size: usize) -> VecZnxDftOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftFromBytesImpl<B: Backend> {
fn vec_znx_dft_from_bytes_impl(n: usize, cols: usize, size: usize, bytes: Vec<u8>) -> VecZnxDftOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO 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;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftToVecZnxBigTmpBytesImpl<B: Backend> {
fn vec_znx_dft_to_vec_znx_big_tmp_bytes_impl(module: &Module<B>, n: usize) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftToVecZnxBigImpl<B: Backend> {
fn vec_znx_dft_to_vec_znx_big_impl<R, A>(
module: &Module<B>,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
scratch: &mut Scratch<B>,
) where
R: VecZnxBigToMut<B>,
A: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftToVecZnxBigTmpAImpl<B: Backend> {
fn vec_znx_dft_to_vec_znx_big_tmp_a_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxDftToMut<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftToVecZnxBigConsumeImpl<B: Backend> {
fn vec_znx_dft_to_vec_znx_big_consume_impl<D: Data>(module: &Module<B>, a: VecZnxDft<D, B>) -> VecZnxBig<D, B>
where
VecZnxDft<D, B>: VecZnxDftToMut<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftAddImpl<B: Backend> {
fn vec_znx_dft_add_impl<R, A, D>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
D: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftAddInplaceImpl<B: Backend> {
fn vec_znx_dft_add_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftSubImpl<B: Backend> {
fn vec_znx_dft_sub_impl<R, A, D>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &D, b_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
D: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftSubABInplaceImpl<B: Backend> {
fn vec_znx_dft_sub_ab_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftSubBAInplaceImpl<B: Backend> {
fn vec_znx_dft_sub_ba_inplace_impl<R, A>(module: &Module<B>, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftCopyImpl<B: Backend> {
fn vec_znx_dft_copy_impl<R, A>(
module: &Module<B>,
step: usize,
offset: usize,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
) where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftFromVecZnxImpl<B: Backend> {
fn vec_znx_dft_from_vec_znx_impl<R, A>(
module: &Module<B>,
step: usize,
offset: usize,
res: &mut R,
res_col: usize,
a: &A,
a_col: usize,
) where
R: VecZnxDftToMut<B>,
A: VecZnxToRef;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VecZnxDftZeroImpl<B: Backend> {
fn vec_znx_dft_zero_impl<R>(module: &Module<B>, res: &mut R)
where
R: VecZnxDftToMut<B>;
}

View File

@@ -0,0 +1,121 @@
use crate::layouts::{
Backend, MatZnxToRef, Module, Scratch, VecZnxDftToMut, VecZnxDftToRef, VmpPMatOwned, VmpPMatToMut, VmpPMatToRef,
};
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpPMatAllocImpl<B: Backend> {
fn vmp_pmat_alloc_impl(n: usize, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> VmpPMatOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO 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;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpPMatFromBytesImpl<B: Backend> {
fn vmp_pmat_from_bytes_impl(
n: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
size: usize,
bytes: Vec<u8>,
) -> VmpPMatOwned<B>;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpPrepareTmpBytesImpl<B: Backend> {
fn vmp_prepare_tmp_bytes_impl(
module: &Module<B>,
n: usize,
rows: usize,
cols_in: usize,
cols_out: usize,
size: usize,
) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpPMatPrepareImpl<B: Backend> {
fn vmp_prepare_impl<R, A>(module: &Module<B>, res: &mut R, a: &A, scratch: &mut Scratch<B>)
where
R: VmpPMatToMut<B>,
A: MatZnxToRef;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpApplyTmpBytesImpl<B: Backend> {
fn vmp_apply_tmp_bytes_impl(
module: &Module<B>,
n: usize,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpApplyImpl<B: Backend> {
fn vmp_apply_impl<R, A, C>(module: &Module<B>, res: &mut R, a: &A, b: &C, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
C: VmpPMatToRef<B>;
}
#[allow(clippy::too_many_arguments)]
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpApplyAddTmpBytesImpl<B: Backend> {
fn vmp_apply_add_tmp_bytes_impl(
module: &Module<B>,
n: usize,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize;
}
/// # THIS TRAIT IS AN OPEN EXTENSION POINT (unsafe)
/// * See TODO for reference code.
/// * See TODO for corresponding public API.
/// # Safety [crate::doc::backend_safety] for safety contract.
pub unsafe trait VmpApplyAddImpl<B: Backend> {
// Same as [MatZnxDftOps::vmp_apply] except result is added on R instead of overwritting R.
fn vmp_apply_add_impl<R, A, C>(module: &Module<B>, res: &mut R, a: &A, b: &C, scale: usize, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
C: VmpPMatToRef<B>;
}

62
poulpy-hal/src/source.rs Normal file
View File

@@ -0,0 +1,62 @@
use rand_chacha::{ChaCha8Rng, rand_core::SeedableRng};
use rand_core::RngCore;
const MAXF64: f64 = 9007199254740992.0;
pub struct Source {
source: ChaCha8Rng,
}
impl Source {
pub fn new(seed: [u8; 32]) -> Source {
Source {
source: ChaCha8Rng::from_seed(seed),
}
}
pub fn branch(&mut self) -> ([u8; 32], Self) {
let seed: [u8; 32] = self.new_seed();
(seed, Source::new(seed))
}
pub fn new_seed(&mut self) -> [u8; 32] {
let mut seed: [u8; 32] = [0u8; 32];
self.fill_bytes(&mut seed);
seed
}
#[inline(always)]
pub fn next_u64n(&mut self, max: u64, mask: u64) -> u64 {
let mut x: u64 = self.next_u64() & mask;
while x >= max {
x = self.next_u64() & mask;
}
x
}
#[inline(always)]
pub fn next_f64(&mut self, min: f64, max: f64) -> f64 {
min + ((self.next_u64() << 11 >> 11) as f64) / MAXF64 * (max - min)
}
pub fn next_i64(&mut self) -> i64 {
self.next_u64() as i64
}
}
impl RngCore for Source {
#[inline(always)]
fn next_u32(&mut self) -> u32 {
self.source.next_u32()
}
#[inline(always)]
fn next_u64(&mut self) -> u64 {
self.source.next_u64()
}
#[inline(always)]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
self.source.fill_bytes(bytes)
}
}

View File

@@ -0,0 +1,3 @@
pub mod serialization;
pub mod vec_znx;
pub mod vmp_pmat;

View File

@@ -0,0 +1,55 @@
use std::fmt::Debug;
use crate::{
api::{FillUniform, Reset},
layouts::{ReaderFrom, WriterTo},
source::Source,
};
/// Generic test for serialization and deserialization.
///
/// - `T` must implement I/O traits, zeroing, cloning, and random filling.
pub fn test_reader_writer_interface<T>(mut original: T)
where
T: WriterTo + ReaderFrom + PartialEq + Eq + Debug + Clone + Reset + FillUniform,
{
// Fill original with uniform random data
let mut source = Source::new([0u8; 32]);
original.fill_uniform(&mut source);
// Serialize into a buffer
let mut buffer = Vec::new();
original.write_to(&mut buffer).expect("write_to failed");
// Prepare receiver: same shape, but zeroed
let mut receiver = original.clone();
receiver.reset();
// Deserialize from buffer
let mut reader: &[u8] = &buffer;
receiver.read_from(&mut reader).expect("read_from failed");
// Ensure serialization round-trip correctness
assert_eq!(
&original, &receiver,
"Deserialized object does not match the original"
);
}
#[test]
fn scalar_znx_serialize() {
let original: crate::layouts::ScalarZnx<Vec<u8>> = crate::layouts::ScalarZnx::alloc(1024, 3);
test_reader_writer_interface(original);
}
#[test]
fn vec_znx_serialize() {
let original: crate::layouts::VecZnx<Vec<u8>> = crate::layouts::VecZnx::alloc(1024, 3, 4);
test_reader_writer_interface(original);
}
#[test]
fn mat_znx_serialize() {
let original: crate::layouts::MatZnx<Vec<u8>> = crate::layouts::MatZnx::alloc(1024, 3, 2, 2, 4);
test_reader_writer_interface(original);
}

View File

@@ -0,0 +1,51 @@
use crate::{
api::{ZnxInfos, ZnxViewMut},
layouts::VecZnx,
source::Source,
};
pub fn test_vec_znx_encode_vec_i64_lo_norm() {
let n: usize = 32;
let basek: usize = 17;
let size: usize = 5;
let k: usize = size * basek - 5;
let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, 2, size);
let mut source: Source = Source::new([0u8; 32]);
let raw: &mut [i64] = a.raw_mut();
raw.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64);
(0..a.cols()).for_each(|col_i| {
let mut have: Vec<i64> = vec![i64::default(); n];
have.iter_mut()
.for_each(|x| *x = (source.next_i64() << 56) >> 56);
a.encode_vec_i64(basek, col_i, k, &have, 10);
let mut want: Vec<i64> = vec![i64::default(); n];
a.decode_vec_i64(basek, col_i, k, &mut want);
assert_eq!(have, want, "{:?} != {:?}", &have, &want);
});
}
pub fn test_vec_znx_encode_vec_i64_hi_norm() {
let n: usize = 32;
let basek: usize = 17;
let size: usize = 5;
for k in [1, basek / 2, size * basek - 5] {
let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, 2, size);
let mut source = Source::new([0u8; 32]);
let raw: &mut [i64] = a.raw_mut();
raw.iter_mut().enumerate().for_each(|(i, x)| *x = i as i64);
(0..a.cols()).for_each(|col_i| {
let mut have: Vec<i64> = vec![i64::default(); n];
have.iter_mut().for_each(|x| {
if k < 64 {
*x = source.next_u64n(1 << k, (1 << k) - 1) as i64;
} else {
*x = source.next_i64();
}
});
a.encode_vec_i64(basek, col_i, k, &have, 63);
let mut want: Vec<i64> = vec![i64::default(); n];
a.decode_vec_i64(basek, col_i, k, &mut want);
assert_eq!(have, want, "{:?} != {:?}", &have, &want);
})
}
}

View File

@@ -0,0 +1,67 @@
use crate::{
api::{VecZnxAddNormal, VecZnxFillUniform, ZnxView},
layouts::{Backend, Module, VecZnx},
source::Source,
};
pub fn test_vec_znx_fill_uniform<B: Backend>(module: &Module<B>)
where
Module<B>: VecZnxFillUniform,
{
let n: usize = module.n();
let basek: usize = 17;
let size: usize = 5;
let mut source: Source = Source::new([0u8; 32]);
let cols: usize = 2;
let zero: Vec<i64> = vec![0; n];
let one_12_sqrt: f64 = 0.28867513459481287;
(0..cols).for_each(|col_i| {
let mut a: VecZnx<_> = VecZnx::alloc(n, cols, size);
module.vec_znx_fill_uniform(basek, &mut a, col_i, size * basek, &mut source);
(0..cols).for_each(|col_j| {
if col_j != col_i {
(0..size).for_each(|limb_i| {
assert_eq!(a.at(col_j, limb_i), zero);
})
} else {
let std: f64 = a.std(basek, col_i);
assert!(
(std - one_12_sqrt).abs() < 0.01,
"std={} ~!= {}",
std,
one_12_sqrt
);
}
})
});
}
pub fn test_vec_znx_add_normal<B: Backend>(module: &Module<B>)
where
Module<B>: VecZnxAddNormal,
{
let n: usize = module.n();
let basek: usize = 17;
let k: usize = 2 * 17;
let size: usize = 5;
let sigma: f64 = 3.2;
let bound: f64 = 6.0 * sigma;
let mut source: Source = Source::new([0u8; 32]);
let cols: usize = 2;
let zero: Vec<i64> = vec![0; n];
let k_f64: f64 = (1u64 << k as u64) as f64;
(0..cols).for_each(|col_i| {
let mut a: VecZnx<_> = VecZnx::alloc(n, cols, size);
module.vec_znx_add_normal(basek, &mut a, col_i, k, &mut source, sigma, bound);
(0..cols).for_each(|col_j| {
if col_j != col_i {
(0..size).for_each(|limb_i| {
assert_eq!(a.at(col_j, limb_i), zero);
})
} else {
let std: f64 = a.std(basek, col_i) * k_f64;
assert!((std - sigma).abs() < 0.1, "std={} ~!= {}", std, sigma);
}
})
});
}

View File

@@ -0,0 +1,5 @@
mod generics;
pub use generics::*;
#[cfg(test)]
mod encoding;

View File

@@ -0,0 +1,3 @@
mod vmp_apply;
pub use vmp_apply::*;

View File

@@ -0,0 +1,114 @@
use crate::{
api::{
ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxBigAlloc, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes,
VecZnxDftAlloc, VecZnxDftFromVecZnx, VecZnxDftToVecZnxBigTmpA, VmpApply, VmpApplyTmpBytes, VmpPMatAlloc, VmpPrepare,
ZnxInfos, ZnxViewMut,
},
layouts::{MatZnx, Module, ScratchOwned, VecZnx, VecZnxBig, VecZnxDft, VmpPMat},
oep::{
ModuleNewImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, VecZnxBigAllocImpl, VecZnxBigNormalizeImpl,
VecZnxBigNormalizeTmpBytesImpl, VecZnxDftAllocImpl, VecZnxDftFromVecZnxImpl, VecZnxDftToVecZnxBigTmpAImpl, VmpApplyImpl,
VmpApplyTmpBytesImpl, VmpPMatAllocImpl, VmpPMatPrepareImpl,
},
};
use crate::layouts::Backend;
pub fn test_vmp_apply<B>()
where
B: Backend
+ ModuleNewImpl<B>
+ VmpApplyTmpBytesImpl<B>
+ VecZnxBigNormalizeTmpBytesImpl<B>
+ VmpPMatAllocImpl<B>
+ VecZnxDftAllocImpl<B>
+ VecZnxBigAllocImpl<B>
+ VmpPMatPrepareImpl<B>
+ VecZnxDftFromVecZnxImpl<B>
+ VmpApplyImpl<B>
+ VecZnxDftToVecZnxBigTmpAImpl<B>
+ ScratchOwnedAllocImpl<B>
+ ScratchOwnedBorrowImpl<B>
+ VecZnxBigNormalizeImpl<B>,
{
let log_n: i32 = 5;
let n: usize = 1 << log_n;
let module: Module<B> = Module::<B>::new(n as u64);
let basek: usize = 15;
let a_size: usize = 5;
let mat_size: usize = 6;
let res_size: usize = a_size;
[1, 2].iter().for_each(|cols_in| {
[1, 2].iter().for_each(|cols_out| {
let a_cols: usize = *cols_in;
let res_cols: usize = *cols_out;
let mat_rows: usize = a_size;
let mat_cols_in: usize = a_cols;
let mat_cols_out: usize = res_cols;
let mut scratch = ScratchOwned::alloc(
module.vmp_apply_tmp_bytes(
n,
res_size,
a_size,
mat_rows,
mat_cols_in,
mat_cols_out,
mat_size,
) | module.vec_znx_big_normalize_tmp_bytes(n),
);
let mut a: VecZnx<Vec<u8>> = VecZnx::alloc(n, a_cols, a_size);
(0..a_cols).for_each(|i| {
a.at_mut(i, a_size - 1)[i + 1] = 1;
});
let mut vmp: VmpPMat<Vec<u8>, B> = module.vmp_pmat_alloc(n, mat_rows, mat_cols_in, mat_cols_out, mat_size);
let mut c_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, mat_cols_out, mat_size);
let mut c_big: VecZnxBig<Vec<u8>, B> = module.vec_znx_big_alloc(n, mat_cols_out, mat_size);
let mut mat: MatZnx<Vec<u8>> = MatZnx::alloc(n, mat_rows, mat_cols_in, mat_cols_out, mat_size);
// Construts a [VecZnxMatDft] that performs cyclic rotations on each submatrix.
(0..a.size()).for_each(|row_i| {
(0..mat_cols_in).for_each(|col_in_i| {
(0..mat_cols_out).for_each(|col_out_i| {
let idx = 1 + col_in_i * mat_cols_out + col_out_i;
mat.at_mut(row_i, col_in_i).at_mut(col_out_i, row_i)[idx] = 1_i64; // X^{idx}
});
});
});
module.vmp_prepare(&mut vmp, &mat, scratch.borrow());
let mut a_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, a_cols, a_size);
(0..a_cols).for_each(|i| {
module.vec_znx_dft_from_vec_znx(1, 0, &mut a_dft, i, &a, i);
});
module.vmp_apply(&mut c_dft, &a_dft, &vmp, scratch.borrow());
let mut res_have_vi64: Vec<i64> = vec![i64::default(); n];
let mut res_have: VecZnx<Vec<u8>> = VecZnx::alloc(n, res_cols, res_size);
(0..mat_cols_out).for_each(|i| {
module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut c_big, i, &mut c_dft, i);
module.vec_znx_big_normalize(basek, &mut res_have, i, &c_big, i, scratch.borrow());
});
(0..mat_cols_out).for_each(|col_i| {
let mut res_want_vi64: Vec<i64> = vec![i64::default(); n];
(0..a_cols).for_each(|i| {
res_want_vi64[(i + 1) + (1 + i * mat_cols_out + col_i)] = 1;
});
res_have.decode_vec_i64(basek, col_i, basek * a_size, &mut res_have_vi64);
assert_eq!(res_have_vi64, res_want_vi64);
});
});
});
}