Ref. + AVX code & generic tests + benches (#85)

This commit is contained in:
Jean-Philippe Bossuat
2025-09-15 16:16:11 +02:00
committed by GitHub
parent 99b9e3e10e
commit 56dbd29c59
286 changed files with 27797 additions and 7270 deletions

View File

@@ -1,4 +1,6 @@
use crate::layouts::{Backend, ScalarZnxToRef, SvpPPolOwned, SvpPPolToMut, SvpPPolToRef, VecZnxDftToMut, VecZnxDftToRef};
use crate::layouts::{
Backend, ScalarZnxToRef, SvpPPolOwned, SvpPPolToMut, SvpPPolToRef, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef,
};
/// Allocates as [crate::layouts::SvpPPol].
pub trait SvpPPolAlloc<B: Backend> {
@@ -25,8 +27,26 @@ pub trait SvpPrepare<B: Backend> {
}
/// 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)
pub trait SvpApplyDft<B: Backend> {
fn svp_apply_dft<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: VecZnxToRef;
}
/// Apply a scalar-vector product between `a[a_col]` and `b[b_col]` and stores the result on `res[res_col]`.
pub trait SvpApplyDftToDft<B: Backend> {
fn svp_apply_dft_to_dft<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 `a[a_col]` and `b[b_col]` and adds the result on `res[res_col]`.
pub trait SvpApplyDftToDftAdd<B: Backend> {
fn svp_apply_dft_to_dft_add<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>,
@@ -34,8 +54,8 @@ pub trait SvpApply<B: Backend> {
}
/// 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)
pub trait SvpApplyDftToDftInplace<B: Backend> {
fn svp_apply_dft_to_dft_inplace<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxDftToMut<B>,
A: SvpPPolToRef<B>;

View File

@@ -1,5 +1,3 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, ScalarZnxToRef, Scratch, VecZnxToMut, VecZnxToRef},
source::Source,
@@ -42,6 +40,16 @@ pub trait VecZnxAddInplace {
A: VecZnxToRef;
}
pub trait VecZnxAddScalar {
/// Adds the selected column of `a` on the selected column and limb of `b` and writes the result on the selected column of `res`.
#[allow(clippy::too_many_arguments)]
fn vec_znx_add_scalar<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize, b_limb: usize)
where
R: VecZnxToMut,
A: ScalarZnxToRef,
B: 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)
@@ -79,6 +87,16 @@ pub trait VecZnxSubBAInplace {
A: VecZnxToRef;
}
pub trait VecZnxSubScalar {
/// Subtracts the selected column of `a` on the selected column and limb of `b` and writes the result on the selected column of `res`.
#[allow(clippy::too_many_arguments)]
fn vec_znx_sub_scalar<R, A, B>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, b: &B, b_col: usize, b_limb: usize)
where
R: VecZnxToMut,
A: ScalarZnxToRef,
B: 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)
@@ -102,31 +120,61 @@ pub trait VecZnxNegateInplace {
A: VecZnxToMut;
}
pub trait VecZnxLshInplace {
pub trait VecZnxLshTmpBytes {
fn vec_znx_lsh_tmp_bytes(&self) -> usize;
}
pub trait VecZnxLsh<B: Backend> {
/// Left shift by k bits all columns of `a`.
fn vec_znx_lsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A)
#[allow(clippy::too_many_arguments)]
fn vec_znx_lsh<R, A>(&self, basek: usize, k: usize, r: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxRshTmpBytes {
fn vec_znx_rsh_tmp_bytes(&self) -> usize;
}
pub trait VecZnxRsh<B: Backend> {
/// Right shift by k bits all columns of `a`.
#[allow(clippy::too_many_arguments)]
fn vec_znx_rsh<R, A>(&self, basek: usize, k: usize, r: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxLshInplace<B: Backend> {
/// Left shift by k bits all columns of `a`.
fn vec_znx_lsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxToMut;
}
pub trait VecZnxRshInplace {
pub trait VecZnxRshInplace<B: Backend> {
/// Right shift by k bits all columns of `a`.
fn vec_znx_rsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A)
fn vec_znx_rsh_inplace<A>(&self, basek: usize, k: usize, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
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)
fn vec_znx_rotate<R, A>(&self, p: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
}
pub trait VecZnxRotateInplace {
pub trait VecZnxRotateInplaceTmpBytes {
fn vec_znx_rotate_inplace_tmp_bytes(&self) -> usize;
}
pub trait VecZnxRotateInplace<B: Backend> {
/// Multiplies the selected column of `a` by X^k.
fn vec_znx_rotate_inplace<A>(&self, k: i64, a: &mut A, a_col: usize)
fn vec_znx_rotate_inplace<A>(&self, p: i64, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxToMut;
}
@@ -139,54 +187,70 @@ pub trait VecZnxAutomorphism {
A: VecZnxToRef;
}
pub trait VecZnxAutomorphismInplace {
pub trait VecZnxAutomorphismInplaceTmpBytes {
fn vec_znx_automorphism_inplace_tmp_bytes(&self) -> usize;
}
pub trait VecZnxAutomorphismInplace<B: Backend> {
/// 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)
fn vec_znx_automorphism_inplace<R>(&self, k: i64, res: &mut R, res_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxToMut;
R: 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)
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;
}
pub trait VecZnxMulXpMinusOneInplace {
fn vec_znx_mul_xp_minus_one_inplace<R>(&self, p: i64, r: &mut R, r_col: usize)
pub trait VecZnxMulXpMinusOneInplaceTmpBytes {
fn vec_znx_mul_xp_minus_one_inplace_tmp_bytes(&self) -> usize;
}
pub trait VecZnxMulXpMinusOneInplace<B: Backend> {
fn vec_znx_mul_xp_minus_one_inplace<R>(&self, p: i64, res: &mut R, res_col: usize, scratch: &mut Scratch<B>)
where
R: VecZnxToMut;
}
pub trait VecZnxSplit<B: Backend> {
pub trait VecZnxSplitRingTmpBytes {
fn vec_znx_split_ring_tmp_bytes(&self) -> usize;
}
pub trait VecZnxSplitRing<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>)
fn vec_znx_split_ring<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 {
pub trait VecZnxMergeRingsTmpBytes {
fn vec_znx_merge_rings_tmp_bytes(&self) -> usize;
}
pub trait VecZnxMergeRings<B: Backend> {
/// 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)
fn vec_znx_merge_rings<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 VecZnxSwithcDegree {
fn vec_znx_switch_degree<R, A>(&self, res: &mut R, res_col: usize, a: &A, col_a: usize)
pub trait VecZnxSwitchRing {
fn vec_znx_switch_ring<R, A>(&self, res: &mut R, res_col: usize, a: &A, col_a: usize)
where
R: VecZnxToMut,
A: VecZnxToRef;
@@ -201,42 +265,11 @@ pub trait VecZnxCopy {
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)
fn vec_znx_fill_uniform<R>(&self, basek: usize, res: &mut R, res_col: 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>(

View File

@@ -1,10 +1,15 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, Scratch, VecZnxBigOwned, VecZnxBigToMut, VecZnxBigToRef, VecZnxToMut, VecZnxToRef},
source::Source,
};
pub trait VecZnxBigFromSmall<B: Backend> {
fn vec_znx_big_from_small<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxToRef;
}
/// Allocates as [crate::layouts::VecZnxBig].
pub trait VecZnxBigAlloc<B: Backend> {
fn vec_znx_big_alloc(&self, cols: usize, size: usize) -> VecZnxBigOwned<B>;
@@ -45,48 +50,6 @@ pub trait VecZnxBigAddNormal<B: Backend> {
);
}
#[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)
@@ -180,10 +143,17 @@ pub trait VecZnxBigSubSmallBInplace<B: Backend> {
A: VecZnxToRef;
}
pub trait VecZnxBigNegateInplace<B: Backend> {
fn vec_znx_big_negate_inplace<A>(&self, a: &mut A, a_col: usize)
pub trait VecZnxBigNegate<B: Backend> {
fn vec_znx_big_negate<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
A: VecZnxBigToMut<B>;
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigNegateInplace<B: Backend> {
fn vec_znx_big_negate_inplace<R>(&self, res: &mut R, res_col: usize)
where
R: VecZnxBigToMut<B>;
}
pub trait VecZnxBigNormalizeTmpBytes {
@@ -204,9 +174,13 @@ pub trait VecZnxBigNormalize<B: Backend> {
A: VecZnxBigToRef<B>;
}
pub trait VecZnxBigAutomorphismInplaceTmpBytes {
fn vec_znx_big_automorphism_inplace_tmp_bytes(&self) -> usize;
}
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)
fn vec_znx_big_automorphism<R, A>(&self, p: i64, res: &mut R, res_col: usize, a: &A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxBigToRef<B>;
@@ -214,7 +188,7 @@ pub trait VecZnxBigAutomorphism<B: Backend> {
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)
fn vec_znx_big_automorphism_inplace<R>(&self, p: i64, res: &mut R, res_col: usize, scratch: &mut Scratch<B>)
where
A: VecZnxBigToMut<B>;
R: VecZnxBigToMut<B>;
}

View File

@@ -14,33 +14,33 @@ pub trait VecZnxDftAllocBytes {
fn vec_znx_dft_alloc_bytes(&self, cols: usize, size: usize) -> usize;
}
pub trait DFT<B: Backend> {
fn dft<R, A>(&self, step: usize, offset: usize, res: &mut R, res_col: usize, a: &A, a_col: usize)
pub trait VecZnxDftApply<B: Backend> {
fn vec_znx_dft_apply<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 VecZnxIDFTTmpBytes {
fn vec_znx_idft_tmp_bytes(&self) -> usize;
pub trait VecZnxIdftApplyTmpBytes {
fn vec_znx_idft_apply_tmp_bytes(&self) -> usize;
}
pub trait IDFT<B: Backend> {
fn idft<R, A>(&self, res: &mut R, res_col: usize, a: &A, a_col: usize, scratch: &mut Scratch<B>)
pub trait VecZnxIdftApply<B: Backend> {
fn vec_znx_idft_apply<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 IDFTTmpA<B: Backend> {
fn idft_tmp_a<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
pub trait VecZnxIdftApplyTmpA<B: Backend> {
fn vec_znx_idft_apply_tmpa<R, A>(&self, res: &mut R, res_col: usize, a: &mut A, a_col: usize)
where
R: VecZnxBigToMut<B>,
A: VecZnxDftToMut<B>;
}
pub trait IDFTConsume<B: Backend> {
fn vec_znx_idft_consume<D: Data>(&self, a: VecZnxDft<D, B>) -> VecZnxBig<D, B>
pub trait VecZnxIdftApplyConsume<B: Backend> {
fn vec_znx_idft_apply_consume<D: Data>(&self, a: VecZnxDft<D, B>) -> VecZnxBig<D, B>
where
VecZnxDft<D, B>: VecZnxDftToMut<B>;
}

View File

@@ -1,4 +1,6 @@
use crate::layouts::{Backend, MatZnxToRef, Scratch, VecZnxDftToMut, VecZnxDftToRef, VmpPMatOwned, VmpPMatToMut, VmpPMatToRef};
use crate::layouts::{
Backend, MatZnxToRef, Scratch, VecZnxDftToMut, VecZnxDftToRef, VecZnxToRef, VmpPMatOwned, VmpPMatToMut, VmpPMatToRef,
};
pub trait VmpPMatAlloc<B: Backend> {
fn vmp_pmat_alloc(&self, rows: usize, cols_in: usize, cols_out: usize, size: usize) -> VmpPMatOwned<B>;
@@ -17,12 +19,33 @@ pub trait VmpPrepareTmpBytes {
}
pub trait VmpPrepare<B: Backend> {
fn vmp_prepare<R, A>(&self, res: &mut R, a: &A, scratch: &mut Scratch<B>)
fn vmp_prepare<R, A>(&self, pmat: &mut R, mat: &A, scratch: &mut Scratch<B>)
where
R: VmpPMatToMut<B>,
A: MatZnxToRef;
}
#[allow(clippy::too_many_arguments)]
pub trait VmpApplyDftTmpBytes {
fn vmp_apply_dft_tmp_bytes(
&self,
res_size: usize,
a_size: usize,
b_rows: usize,
b_cols_in: usize,
b_cols_out: usize,
b_size: usize,
) -> usize;
}
pub trait VmpApplyDft<B: Backend> {
fn vmp_apply_dft<R, A, C>(&self, res: &mut R, a: &A, pmat: &C, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxToRef,
C: VmpPMatToRef<B>;
}
#[allow(clippy::too_many_arguments)]
pub trait VmpApplyDftToDftTmpBytes {
fn vmp_apply_dft_to_dft_tmp_bytes(
@@ -61,7 +84,7 @@ pub trait VmpApplyDftToDft<B: Backend> {
/// * `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_dft_to_dft<R, A, C>(&self, res: &mut R, a: &A, b: &C, scratch: &mut Scratch<B>)
fn vmp_apply_dft_to_dft<R, A, C>(&self, res: &mut R, a: &A, pmat: &C, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,
@@ -82,7 +105,7 @@ pub trait VmpApplyDftToDftAddTmpBytes {
}
pub trait VmpApplyDftToDftAdd<B: Backend> {
fn vmp_apply_dft_to_dft_add<R, A, C>(&self, res: &mut R, a: &A, b: &C, scale: usize, scratch: &mut Scratch<B>)
fn vmp_apply_dft_to_dft_add<R, A, C>(&self, res: &mut R, a: &A, b: &C, limb_offset: usize, scratch: &mut Scratch<B>)
where
R: VecZnxDftToMut<B>,
A: VecZnxDftToRef<B>,

View File

@@ -1,57 +1,29 @@
use rand_distr::Distribution;
use crate::{
layouts::{Backend, Scratch, ZnToMut},
reference::zn::zn_normalize_tmp_bytes,
source::Source,
};
pub trait ZnNormalizeTmpBytes {
fn zn_normalize_tmp_bytes(&self, n: usize) -> usize {
zn_normalize_tmp_bytes(n)
}
}
pub trait ZnNormalizeInplace<B: Backend> {
/// Normalizes the selected column of `a`.
fn zn_normalize_inplace<A>(&self, n: usize, basek: usize, a: &mut A, a_col: usize, scratch: &mut Scratch<B>)
fn zn_normalize_inplace<R>(&self, n: usize, basek: usize, res: &mut R, res_col: usize, scratch: &mut Scratch<B>)
where
A: ZnToMut;
R: ZnToMut;
}
pub trait ZnFillUniform {
/// Fills the first `size` size with uniform values in \[-2^{basek-1}, 2^{basek-1}\]
fn zn_fill_uniform<R>(&self, n: usize, basek: usize, res: &mut R, res_col: usize, k: usize, source: &mut Source)
fn zn_fill_uniform<R>(&self, n: usize, basek: usize, res: &mut R, res_col: usize, source: &mut Source)
where
R: ZnToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait ZnFillDistF64 {
fn zn_fill_dist_f64<R, D: Distribution<f64>>(
&self,
n: usize,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: ZnToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait ZnAddDistF64 {
/// Adds vector sampled according to the provided distribution, scaled by 2^{-k} and bounded to \[-bound, bound\].
fn zn_add_dist_f64<R, D: Distribution<f64>>(
&self,
n: usize,
basek: usize,
res: &mut R,
res_col: usize,
k: usize,
source: &mut Source,
dist: D,
bound: f64,
) where
R: ZnToMut;
}
#[allow(clippy::too_many_arguments)]
pub trait ZnFillNormal {
fn zn_fill_normal<R>(