mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-08 22:28:01 -05:00
docs(tfhe): update polynomial and slice algorithms naming
- update docstrings to be better rendered in html.
This commit is contained in:
@@ -184,7 +184,7 @@ fn encrypt_ggsw_level_matrix_row<Scalar, KeyCont, InputCont, OutputCont, Gen>(
|
||||
let mut body = row_as_glwe.get_mut_body();
|
||||
body.as_mut().copy_from_slice(sk_poly.as_ref());
|
||||
|
||||
update_slice_with_wrapping_scalar_mul(body.as_mut(), factor);
|
||||
slice_wrapping_scalar_mul_assign(body.as_mut(), factor);
|
||||
|
||||
encrypt_glwe_ciphertext_in_place(glwe_secret_key, row_as_glwe, noise_parameters, generator);
|
||||
} else {
|
||||
|
||||
@@ -37,7 +37,7 @@ pub fn encrypt_glwe_ciphertext_in_place<Scalar, KeyCont, OutputCont, Gen>(
|
||||
|
||||
generator.update_slice_with_wrapping_add_random_noise(body.as_mut(), noise_parameters);
|
||||
|
||||
update_polynomial_with_wrapping_add_multisum(
|
||||
polynomial_wrapping_add_multisum_assign(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
@@ -85,12 +85,12 @@ pub fn encrypt_glwe_ciphertext<Scalar, KeyCont, InputCont, OutputCont, Gen>(
|
||||
|
||||
generator.fill_slice_with_random_noise(body.as_mut(), noise_parameters);
|
||||
|
||||
update_polynomial_with_wrapping_add(
|
||||
polynomial_wrapping_add_assign(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&input_plaintext_list.as_polynomial(),
|
||||
);
|
||||
|
||||
update_polynomial_with_wrapping_add_multisum(
|
||||
polynomial_wrapping_add_multisum_assign(
|
||||
&mut body.as_mut_polynomial(),
|
||||
&mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
@@ -186,7 +186,7 @@ pub fn decrypt_glwe_ciphertext<Scalar, KeyCont, InputCont, OutputCont>(
|
||||
output_plaintext_list
|
||||
.as_mut()
|
||||
.copy_from_slice(body.as_ref());
|
||||
update_polynomial_with_wrapping_sub_multisum(
|
||||
polynomial_wrapping_sub_multisum_assign(
|
||||
&mut output_plaintext_list.as_mut_polynomial(),
|
||||
&mask.as_polynomial_list(),
|
||||
&glwe_secret_key.as_polynomial_list(),
|
||||
|
||||
@@ -41,7 +41,7 @@ pub fn extract_lwe_sample_from_glwe_ciphertext<Scalar, InputCont, OutputCont>(
|
||||
// We reverse the polynomial
|
||||
lwe_mask_poly.reverse();
|
||||
// We compute the opposite of the proper coefficients
|
||||
update_slice_with_wrapping_opposite(&mut lwe_mask_poly[0..opposite_count]);
|
||||
slice_wrapping_opposite_assign(&mut lwe_mask_poly[0..opposite_count]);
|
||||
// We rotate the polynomial properly
|
||||
lwe_mask_poly.rotate_left(opposite_count);
|
||||
}
|
||||
|
||||
@@ -32,10 +32,7 @@ pub fn keyswitch_lwe_ciphertext<Scalar, KSKCont, InputCont, OutputCont>(
|
||||
);
|
||||
|
||||
// Clear the output ciphertext, as it will get updated gradually
|
||||
output_lwe_ciphertext
|
||||
.as_mut()
|
||||
.iter_mut()
|
||||
.for_each(|elt| *elt = Scalar::ZERO);
|
||||
output_lwe_ciphertext.as_mut().fill(Scalar::ZERO);
|
||||
|
||||
// Copy the input body to the output ciphertext
|
||||
*output_lwe_ciphertext.get_mut_body().0 = *input_lwe_ciphertext.get_body().0;
|
||||
@@ -55,7 +52,7 @@ pub fn keyswitch_lwe_ciphertext<Scalar, KSKCont, InputCont, OutputCont>(
|
||||
for (level_key_ciphertext, decomposed) in
|
||||
keyswitch_key_block.iter().rev().zip(decomposition_iter)
|
||||
{
|
||||
update_slice_with_wrapping_sub_scalar_mul(
|
||||
slice_wrapping_sub_scalar_mul_assign(
|
||||
output_lwe_ciphertext.as_mut(),
|
||||
level_key_ciphertext.as_ref(),
|
||||
decomposed.value(),
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn lwe_ciphertext_in_place_addition<Scalar, LhsCont, RhsCont>(
|
||||
LhsCont: ContainerMut<Element = Scalar>,
|
||||
RhsCont: Container<Element = Scalar>,
|
||||
{
|
||||
update_slice_with_wrapping_add(lhs.as_mut(), rhs.as_ref());
|
||||
slice_wrapping_add_assign(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_addition<Scalar, OutputCont, LhsCont, RhsCont>(
|
||||
@@ -47,7 +47,7 @@ where
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
update_slice_with_wrapping_opposite(ct.as_mut());
|
||||
slice_wrapping_opposite_assign(ct.as_mut());
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_cleartext_multiplication<Scalar, InCont>(
|
||||
@@ -57,7 +57,7 @@ pub fn lwe_ciphertext_in_place_cleartext_multiplication<Scalar, InCont>(
|
||||
Scalar: UnsignedInteger,
|
||||
InCont: ContainerMut<Element = Scalar>,
|
||||
{
|
||||
update_slice_with_wrapping_scalar_mul(lhs.as_mut(), rhs.0);
|
||||
slice_wrapping_scalar_mul_assign(lhs.as_mut(), rhs.0);
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_in_place_subtraction<Scalar, LhsCont, RhsCont>(
|
||||
@@ -68,7 +68,7 @@ pub fn lwe_ciphertext_in_place_subtraction<Scalar, LhsCont, RhsCont>(
|
||||
LhsCont: ContainerMut<Element = Scalar>,
|
||||
RhsCont: Container<Element = Scalar>,
|
||||
{
|
||||
update_slice_with_wrapping_sub(lhs.as_mut(), rhs.as_ref());
|
||||
slice_wrapping_sub_assign(lhs.as_mut(), rhs.as_ref());
|
||||
}
|
||||
|
||||
pub fn lwe_ciphertext_cleartext_multiplication<Scalar, InputCont, OutputCont>(
|
||||
|
||||
@@ -49,7 +49,7 @@ pub fn private_functional_keyswitch_lwe_ciphertext_into_glwe_ciphertext<
|
||||
// We compute the multiplication of a ciphertext from the private functional
|
||||
// keyswitching key with a piece of the decomposition and subtract it to the buffer
|
||||
for (level_key_cipher, decomposed) in keyswitch_key_block.iter().rev().zip(decomp) {
|
||||
update_slice_with_wrapping_sub_scalar_mul(
|
||||
slice_wrapping_sub_scalar_mul_assign(
|
||||
output_glwe_ciphertext.as_mut(),
|
||||
level_key_cipher.as_ref(),
|
||||
decomposed.value(),
|
||||
@@ -87,11 +87,8 @@ pub fn private_functional_keyswitch_lwe_ciphertext_list_and_pack_in_glwe_ciphere
|
||||
.as_mut_polynomial_list()
|
||||
.iter_mut()
|
||||
.for_each(|mut poly| {
|
||||
update_polynomial_with_wrapping_monic_monomial_mul(
|
||||
&mut poly,
|
||||
MonomialDegree(degree),
|
||||
)
|
||||
polynomial_wrapping_monic_monomial_mul_assign(&mut poly, MonomialDegree(degree))
|
||||
});
|
||||
update_slice_with_wrapping_add(output.as_mut(), buffer.as_ref());
|
||||
slice_wrapping_add_assign(output.as_mut(), buffer.as_ref());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ pub fn generate_lwe_private_functional_packing_keyswitch_key<
|
||||
.map(DecompositionLevel)
|
||||
.zip(messages.chunks_exact_mut(polynomial_size.0))
|
||||
{
|
||||
update_slice_with_wrapping_add_scalar_mul(
|
||||
slice_wrapping_add_scalar_mul_assign(
|
||||
message.as_mut(),
|
||||
polynomial.as_ref(),
|
||||
DecompositionTerm::new(
|
||||
@@ -204,7 +204,7 @@ pub fn par_generate_lwe_private_functional_packing_keyswitch_key<
|
||||
.map(DecompositionLevel)
|
||||
.zip(messages.chunks_exact_mut(polynomial_size.0))
|
||||
{
|
||||
update_slice_with_wrapping_add_scalar_mul(
|
||||
slice_wrapping_add_scalar_mul_assign(
|
||||
message.as_mut(),
|
||||
polynomial.as_ref(),
|
||||
DecompositionTerm::new(
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
//! Module providing algorithms to perform computations on polynomials modulo $X^{N} + 1$.
|
||||
|
||||
use crate::core_crypto::algorithms::slice_algorithms::*;
|
||||
use crate::core_crypto::commons::numeric::UnsignedInteger;
|
||||
use crate::core_crypto::commons::parameters::MonomialDegree;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
/// Adds a polynomial with unsinged integers coefficients to another one in place, wrapping around
|
||||
/// (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned integer capacity.
|
||||
/// Adds a polynomial to the output polynomial.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -14,10 +20,10 @@ use crate::core_crypto::entities::*;
|
||||
/// use tfhe::core_crypto::entities::*;
|
||||
/// let mut first = Polynomial::from_container(vec![1u8, 2, 3, 4, 5, 6]);
|
||||
/// let second = Polynomial::from_container(vec![255u8, 255, 255, 1, 2, 3]);
|
||||
/// update_polynomial_with_wrapping_add(&mut first, &second);
|
||||
/// polynomial_wrapping_add_assign(&mut first, &second);
|
||||
/// assert_eq!(first.as_ref(), &[0u8, 1, 2, 5, 7, 9]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_add<Scalar, OutputCont, InputCont>(
|
||||
pub fn polynomial_wrapping_add_assign<Scalar, OutputCont, InputCont>(
|
||||
lhs: &mut Polynomial<OutputCont>,
|
||||
rhs: &Polynomial<InputCont>,
|
||||
) where
|
||||
@@ -26,11 +32,11 @@ pub fn update_polynomial_with_wrapping_add<Scalar, OutputCont, InputCont>(
|
||||
InputCont: Container<Element = Scalar>,
|
||||
{
|
||||
assert_eq!(lhs.polynomial_size(), rhs.polynomial_size());
|
||||
update_slice_with_wrapping_add(lhs.as_mut(), rhs.as_ref())
|
||||
slice_wrapping_add_assign(lhs.as_mut(), rhs.as_ref())
|
||||
}
|
||||
|
||||
/// Adds the sum of the element-wise product between two lists of unsigned integer polynomial to the
|
||||
/// output polynomial.
|
||||
/// Adds the sum of the element-wise product between two lists of polynomials to the output
|
||||
/// polynomial.
|
||||
///
|
||||
/// I.e., if the output polynomial is $C(X)$, for a collection of polynomials $(P\_i(X)))\_i$
|
||||
/// and another collection of polynomials $(B\_i(X))\_i$ we perform the operation:
|
||||
@@ -38,6 +44,11 @@ pub fn update_polynomial_with_wrapping_add<Scalar, OutputCont, InputCont>(
|
||||
/// C(X) := C(X) + \sum\_i P\_i(X) \times B\_i(X) mod (X^{N} + 1)
|
||||
/// $$
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
@@ -47,10 +58,10 @@ pub fn update_polynomial_with_wrapping_add<Scalar, OutputCont, InputCont>(
|
||||
/// let poly_list = PolynomialList::from_container(vec![100_u8, 20, 3, 4, 5, 6], PolynomialSize(3));
|
||||
/// let bin_poly_list = PolynomialList::from_container(vec![0, 1, 1, 1, 0, 0], PolynomialSize(3));
|
||||
/// let mut output = Polynomial::new(250, PolynomialSize(3));
|
||||
/// update_polynomial_with_wrapping_add_multisum(&mut output, &poly_list, &bin_poly_list);
|
||||
/// polynomial_wrapping_add_multisum_assign(&mut output, &poly_list, &bin_poly_list);
|
||||
/// assert_eq!(output.as_ref(), &[231, 96, 120]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_add_multisum<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
pub fn polynomial_wrapping_add_multisum_assign<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
output: &mut Polynomial<OutputCont>,
|
||||
poly_list_1: &PolynomialList<InputCont1>,
|
||||
poly_list_2: &PolynomialList<InputCont2>,
|
||||
@@ -61,12 +72,17 @@ pub fn update_polynomial_with_wrapping_add_multisum<Scalar, OutputCont, InputCon
|
||||
InputCont2: Container<Element = Scalar>,
|
||||
{
|
||||
for (poly_1, poly_2) in poly_list_1.iter().zip(poly_list_2.iter()) {
|
||||
update_polynomial_with_wrapping_add_mul(output, &poly_1, &poly_2);
|
||||
polynomial_wrapping_add_mul_assign(output, &poly_1, &poly_2);
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds the result of the product between two integer polynomials, reduced modulo $(X^{N}+1)$,
|
||||
/// to the output polynomial.
|
||||
/// Adds the result of the product between two polynomials, reduced modulo $(X^{N}+1)$, to the
|
||||
/// output polynomial.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -76,10 +92,10 @@ pub fn update_polynomial_with_wrapping_add_multisum<Scalar, OutputCont, InputCon
|
||||
/// let poly_1 = Polynomial::from_container(vec![1_u8, 2, 3]);
|
||||
/// let poly_2 = Polynomial::from_container(vec![0, 1, 1]);
|
||||
/// let mut res = Polynomial::from_container(vec![1, 0, 253]);
|
||||
/// update_polynomial_with_wrapping_add_mul(&mut res, &poly_1, &poly_2);
|
||||
/// polynomial_wrapping_add_mul_assign(&mut res, &poly_1, &poly_2);
|
||||
/// assert_eq!(res.as_ref(), &[252, 254, 0]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_add_mul<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
pub fn polynomial_wrapping_add_mul_assign<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
output: &mut Polynomial<OutputCont>,
|
||||
lhs: &Polynomial<InputCont1>,
|
||||
rhs: &Polynomial<InputCont2>,
|
||||
@@ -126,6 +142,11 @@ pub fn update_polynomial_with_wrapping_add_mul<Scalar, OutputCont, InputCont1, I
|
||||
/// Divides (mod $(X^{N}+1)$), the output polynomial with a monic monomial of a given degree i.e.
|
||||
/// $X^{degree}$.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@@ -133,10 +154,10 @@ pub fn update_polynomial_with_wrapping_add_mul<Scalar, OutputCont, InputCont1, I
|
||||
/// use tfhe::core_crypto::commons::parameters::*;
|
||||
/// use tfhe::core_crypto::entities::*;
|
||||
/// let mut poly = Polynomial::from_container(vec![1u8, 2, 3]);
|
||||
/// update_polynomial_with_wrapping_monic_monomial_div(&mut poly, MonomialDegree(2));
|
||||
/// polynomial_wrapping_monic_monomial_div_assign(&mut poly, MonomialDegree(2));
|
||||
/// assert_eq!(poly.as_ref(), &[3, 255, 254]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_monic_monomial_div<Scalar, OutputCont>(
|
||||
pub fn polynomial_wrapping_monic_monomial_div_assign<Scalar, OutputCont>(
|
||||
output: &mut Polynomial<OutputCont>,
|
||||
monomial_degree: MonomialDegree,
|
||||
) where
|
||||
@@ -163,6 +184,11 @@ pub fn update_polynomial_with_wrapping_monic_monomial_div<Scalar, OutputCont>(
|
||||
/// Multiplies (mod $(X^{N}+1)$), the output polynomial with a monic monomial of a given degree i.e.
|
||||
/// $X^{degree}$.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@@ -170,10 +196,10 @@ pub fn update_polynomial_with_wrapping_monic_monomial_div<Scalar, OutputCont>(
|
||||
/// use tfhe::core_crypto::commons::parameters::*;
|
||||
/// use tfhe::core_crypto::entities::*;
|
||||
/// let mut poly = Polynomial::from_container(vec![1u8, 2, 3]);
|
||||
/// update_polynomial_with_wrapping_monic_monomial_mul(&mut poly, MonomialDegree(2));
|
||||
/// polynomial_wrapping_monic_monomial_mul_assign(&mut poly, MonomialDegree(2));
|
||||
/// assert_eq!(poly.as_ref(), &[254, 253, 1]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_monic_monomial_mul<Scalar, OutputCont>(
|
||||
pub fn polynomial_wrapping_monic_monomial_mul_assign<Scalar, OutputCont>(
|
||||
output: &mut Polynomial<OutputCont>,
|
||||
monomial_degree: MonomialDegree,
|
||||
) where
|
||||
@@ -196,8 +222,8 @@ pub fn update_polynomial_with_wrapping_monic_monomial_mul<Scalar, OutputCont>(
|
||||
.for_each(|a| *a = a.wrapping_neg());
|
||||
}
|
||||
|
||||
/// Subtracts the sum of the element-wise product between two lists of integer polynomials,
|
||||
/// to the output polynomial.
|
||||
/// Subtracts the sum of the element-wise product between two lists of polynomials, to the output
|
||||
/// polynomial.
|
||||
///
|
||||
/// I.e., if the output polynomial is $C(X)$, for two lists of polynomials $(P\_i(X)))\_i$ and
|
||||
/// $(B\_i(X))\_i$ we perform the operation:
|
||||
@@ -205,6 +231,11 @@ pub fn update_polynomial_with_wrapping_monic_monomial_mul<Scalar, OutputCont>(
|
||||
/// C(X) := C(X) + \sum\_i P\_i(X) \times B\_i(X) mod (X^{N} + 1)
|
||||
/// $$
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
@@ -215,10 +246,10 @@ pub fn update_polynomial_with_wrapping_monic_monomial_mul<Scalar, OutputCont>(
|
||||
/// PolynomialList::from_container(vec![100 as u8, 20, 3, 4, 5, 6], PolynomialSize(3));
|
||||
/// let bin_poly_list = PolynomialList::from_container(vec![0, 1, 1, 1, 0, 0], PolynomialSize(3));
|
||||
/// let mut output = Polynomial::new(250 as u8, PolynomialSize(3));
|
||||
/// update_polynomial_with_wrapping_sub_multisum(&mut output, &poly_list, &bin_poly_list);
|
||||
/// polynomial_wrapping_sub_multisum_assign(&mut output, &poly_list, &bin_poly_list);
|
||||
/// assert_eq!(output.as_ref(), &[13, 148, 124]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_sub_multisum<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
pub fn polynomial_wrapping_sub_multisum_assign<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
output: &mut Polynomial<OutputCont>,
|
||||
poly_list_1: &PolynomialList<InputCont1>,
|
||||
poly_list_2: &PolynomialList<InputCont2>,
|
||||
@@ -229,12 +260,17 @@ pub fn update_polynomial_with_wrapping_sub_multisum<Scalar, OutputCont, InputCon
|
||||
InputCont2: Container<Element = Scalar>,
|
||||
{
|
||||
for (poly_1, poly_2) in poly_list_1.iter().zip(poly_list_2.iter()) {
|
||||
update_polynomial_with_wrapping_sub_mul(output, &poly_1, &poly_2);
|
||||
polynomial_wrapping_sub_mul_assign(output, &poly_1, &poly_2);
|
||||
}
|
||||
}
|
||||
|
||||
/// Subtracts the result of the product between two integer polynomials, reduced modulo $(X^{N}+1)$,
|
||||
/// to the output polynomial.
|
||||
/// Subtracts the result of the product between two polynomials, reduced modulo $(X^{N}+1)$, to the
|
||||
/// output polynomial.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -244,10 +280,10 @@ pub fn update_polynomial_with_wrapping_sub_multisum<Scalar, OutputCont, InputCon
|
||||
/// let poly_1 = Polynomial::from_container(vec![1_u8, 2, 3]);
|
||||
/// let poly_2 = Polynomial::from_container(vec![0, 1, 1]);
|
||||
/// let mut res = Polynomial::from_container(vec![255, 255, 1]);
|
||||
/// update_polynomial_with_wrapping_sub_mul(&mut res, &poly_1, &poly_2);
|
||||
/// polynomial_wrapping_sub_mul_assign(&mut res, &poly_1, &poly_2);
|
||||
/// assert_eq!(res.as_ref(), &[4, 1, 254]);
|
||||
/// ```
|
||||
pub fn update_polynomial_with_wrapping_sub_mul<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
pub fn polynomial_wrapping_sub_mul_assign<Scalar, OutputCont, InputCont1, InputCont2>(
|
||||
output: &mut Polynomial<OutputCont>,
|
||||
lhs: &Polynomial<InputCont1>,
|
||||
rhs: &Polynomial<InputCont2>,
|
||||
@@ -321,8 +357,8 @@ mod test {
|
||||
r %= polynomial_size;
|
||||
|
||||
// multiply by X^r and then divides by X^r
|
||||
update_polynomial_with_wrapping_monic_monomial_mul(&mut poly, MonomialDegree(r));
|
||||
update_polynomial_with_wrapping_monic_monomial_div(&mut poly, MonomialDegree(r));
|
||||
polynomial_wrapping_monic_monomial_mul_assign(&mut poly, MonomialDegree(r));
|
||||
polynomial_wrapping_monic_monomial_div_assign(&mut poly, MonomialDegree(r));
|
||||
|
||||
// test
|
||||
assert_eq!(&poly, &ground_truth);
|
||||
@@ -332,15 +368,15 @@ mod test {
|
||||
r_big = r_big % polynomial_size + 2048;
|
||||
|
||||
// multiply by X^r_big and then divides by X^r_big
|
||||
update_polynomial_with_wrapping_monic_monomial_mul(&mut poly, MonomialDegree(r_big));
|
||||
update_polynomial_with_wrapping_monic_monomial_div(&mut poly, MonomialDegree(r_big));
|
||||
polynomial_wrapping_monic_monomial_mul_assign(&mut poly, MonomialDegree(r_big));
|
||||
polynomial_wrapping_monic_monomial_div_assign(&mut poly, MonomialDegree(r_big));
|
||||
|
||||
// test
|
||||
assert_eq!(&poly, &ground_truth);
|
||||
|
||||
// divides by X^r_big and then multiply by X^r_big
|
||||
update_polynomial_with_wrapping_monic_monomial_mul(&mut poly, MonomialDegree(r_big));
|
||||
update_polynomial_with_wrapping_monic_monomial_div(&mut poly, MonomialDegree(r_big));
|
||||
polynomial_wrapping_monic_monomial_mul_assign(&mut poly, MonomialDegree(r_big));
|
||||
polynomial_wrapping_monic_monomial_div_assign(&mut poly, MonomialDegree(r_big));
|
||||
|
||||
// test
|
||||
assert_eq!(&poly, &ground_truth);
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
//! Module providing algorithms to perform computations on raw slices.
|
||||
|
||||
use crate::core_crypto::commons::numeric::UnsignedInteger;
|
||||
|
||||
/// Computes a dot product between two slices containing unsigned integers, wrapping
|
||||
/// around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned integer
|
||||
/// capacity.
|
||||
/// Computes a dot product between two slices containing unsigned integers.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -31,9 +36,12 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
/// Adds a slice containing unsigned integers to another one element-wise, wrapping
|
||||
/// around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned integer
|
||||
/// capacity.
|
||||
/// Adds a slice containing unsigned integers to another one element-wise.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -68,9 +76,12 @@ where
|
||||
.for_each(|(out, (&lhs, &rhs))| *out = lhs.wrapping_add(rhs));
|
||||
}
|
||||
|
||||
/// Adds a slice containing unsigned integers to another one element-wise and in place, wrapping
|
||||
/// around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned integer
|
||||
/// capacity.
|
||||
/// Adds a slice containing unsigned integers to another one element-wise and in place.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -78,10 +89,10 @@ where
|
||||
/// use tfhe::core_crypto::algorithms::slice_algorithms::*;
|
||||
/// let mut first = vec![1u8, 2, 3, 4, 5, 6];
|
||||
/// let second = vec![255u8, 255, 255, 1, 2, 3];
|
||||
/// update_slice_with_wrapping_add(&mut first, &second);
|
||||
/// slice_wrapping_add_assign(&mut first, &second);
|
||||
/// assert_eq!(&first, &[0u8, 1, 2, 5, 7, 9]);
|
||||
/// ```
|
||||
pub fn update_slice_with_wrapping_add<Scalar>(lhs: &mut [Scalar], rhs: &[Scalar])
|
||||
pub fn slice_wrapping_add_assign<Scalar>(lhs: &mut [Scalar], rhs: &[Scalar])
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
@@ -97,10 +108,14 @@ where
|
||||
.for_each(|(lhs, &rhs)| *lhs = (*lhs).wrapping_add(rhs));
|
||||
}
|
||||
|
||||
/// Adds a slice containing unsigned integers to another one mutiplied by a scalar, element-wise and
|
||||
/// in place, wrapping around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the
|
||||
/// unsigned integer capacity. Let *a*,*b* be two slices, let *c* be a scalar, this computes:
|
||||
/// *a <- a+bc*
|
||||
/// Adds a slice containing unsigned integers to another one mutiplied by a scalar.
|
||||
///
|
||||
/// Let *a*,*b* be two slices, let *c* be a scalar, this computes: *a <- a+bc*
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -109,10 +124,10 @@ where
|
||||
/// let mut first = vec![1u8, 2, 3, 4, 5, 6];
|
||||
/// let second = vec![255u8, 255, 255, 1, 2, 3];
|
||||
/// let scalar = 4u8;
|
||||
/// update_slice_with_wrapping_add_scalar_mul(&mut first, &second, scalar);
|
||||
/// slice_wrapping_add_scalar_mul_assign(&mut first, &second, scalar);
|
||||
/// assert_eq!(&first, &[253u8, 254, 255, 8, 13, 18]);
|
||||
/// ```
|
||||
pub fn update_slice_with_wrapping_add_scalar_mul<Scalar>(
|
||||
pub fn slice_wrapping_add_scalar_mul_assign<Scalar>(
|
||||
lhs: &mut [Scalar],
|
||||
rhs: &[Scalar],
|
||||
scalar: Scalar,
|
||||
@@ -130,9 +145,12 @@ pub fn update_slice_with_wrapping_add_scalar_mul<Scalar>(
|
||||
.for_each(|(lhs, &rhs)| *lhs = (*lhs).wrapping_add(rhs.wrapping_mul(scalar)));
|
||||
}
|
||||
|
||||
/// Subtracts a slice containing unsigned integers to another one, element-wise and in place,
|
||||
/// wrapping around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned
|
||||
/// integer capacity.
|
||||
/// Subtracts a slice containing unsigned integers to another one, element-wise and in place.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -140,10 +158,10 @@ pub fn update_slice_with_wrapping_add_scalar_mul<Scalar>(
|
||||
/// use tfhe::core_crypto::algorithms::slice_algorithms::*;
|
||||
/// let mut first = vec![1u8, 2, 3, 4, 5, 6];
|
||||
/// let second = vec![255u8, 255, 255, 1, 2, 3];
|
||||
/// update_slice_with_wrapping_sub(&mut first, &second);
|
||||
/// slice_wrapping_sub_assign(&mut first, &second);
|
||||
/// assert_eq!(&first, &[2u8, 3, 4, 3, 3, 3]);
|
||||
/// ```
|
||||
pub fn update_slice_with_wrapping_sub<Scalar>(lhs: &mut [Scalar], rhs: &[Scalar])
|
||||
pub fn slice_wrapping_sub_assign<Scalar>(lhs: &mut [Scalar], rhs: &[Scalar])
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
@@ -160,9 +178,14 @@ where
|
||||
}
|
||||
|
||||
/// Subtracts a slice containing unsigned integers to another one mutiplied by a scalar,
|
||||
/// element-wise and in place, wrapping around (similar to computing modulo $$2^{n\_bits}$$) when
|
||||
/// exceeding the unsigned integer capacity. Let *a*,*b* be two slices, let *c* be a scalar, this
|
||||
/// computes: *a <- a-bc*
|
||||
/// element-wise and in place.
|
||||
///
|
||||
/// Let *a*,*b* be two slices, let *c* be a scalar, this computes: *a <- a-bc*
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -171,9 +194,9 @@ where
|
||||
/// let mut first = vec![1u8, 2, 3, 4, 5, 6];
|
||||
/// let second = vec![255u8, 255, 255, 1, 2, 3];
|
||||
/// let scalar = 4u8;
|
||||
/// update_slice_with_wrapping_sub_scalar_mul(&mut first, &second, scalar);
|
||||
/// slice_wrapping_sub_scalar_mul_assign(&mut first, &second, scalar);
|
||||
/// assert_eq!(&first, &[5u8, 6, 7, 0, 253, 250]);
|
||||
pub fn update_slice_with_wrapping_sub_scalar_mul<Scalar>(
|
||||
pub fn slice_wrapping_sub_scalar_mul_assign<Scalar>(
|
||||
lhs: &mut [Scalar],
|
||||
rhs: &[Scalar],
|
||||
scalar: Scalar,
|
||||
@@ -191,19 +214,22 @@ pub fn update_slice_with_wrapping_sub_scalar_mul<Scalar>(
|
||||
.for_each(|(lhs, &rhs)| *lhs = (*lhs).wrapping_sub(rhs.wrapping_mul(scalar)));
|
||||
}
|
||||
|
||||
/// Computes the opposite of a slice containing unsigned integers, element-wise and in place,
|
||||
/// wrapping around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned
|
||||
/// integer capacity.
|
||||
/// Computes the opposite of a slice containing unsigned integers, element-wise and in place.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use tfhe::core_crypto::algorithms::slice_algorithms::*;
|
||||
/// let mut first = vec![1u8, 2, 3, 4, 5, 6];
|
||||
/// update_slice_with_wrapping_opposite(&mut first);
|
||||
/// slice_wrapping_opposite_assign(&mut first);
|
||||
/// assert_eq!(&first, &[255u8, 254, 253, 252, 251, 250]);
|
||||
/// ```
|
||||
pub fn update_slice_with_wrapping_opposite<Scalar>(slice: &mut [Scalar])
|
||||
pub fn slice_wrapping_opposite_assign<Scalar>(slice: &mut [Scalar])
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
@@ -212,9 +238,12 @@ where
|
||||
.for_each(|elt| *elt = (*elt).wrapping_neg());
|
||||
}
|
||||
|
||||
/// Multiplies a slice containing unsigned integers by a scalar, element-wise and in place, wrapping
|
||||
/// around (similar to computing modulo $$2^{n\_bits}$$) when exceeding the unsigned integer
|
||||
/// capacity.
|
||||
/// Multiplies a slice containing unsigned integers by a scalar, element-wise and in place.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Computations wrap around (similar to computing modulo $2^{n\_{bits}}$) when exceeding the
|
||||
/// unsigned integer capacity.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@@ -222,10 +251,10 @@ where
|
||||
/// use tfhe::core_crypto::algorithms::slice_algorithms::*;
|
||||
/// let mut first = vec![1u8, 2, 3, 4, 5, 6];
|
||||
/// let scalar = 252;
|
||||
/// update_slice_with_wrapping_scalar_mul(&mut first, scalar);
|
||||
/// slice_wrapping_scalar_mul_assign(&mut first, scalar);
|
||||
/// assert_eq!(&first, &[252, 248, 244, 240, 236, 232]);
|
||||
/// ```
|
||||
pub fn update_slice_with_wrapping_scalar_mul<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
|
||||
pub fn slice_wrapping_scalar_mul_assign<Scalar>(lhs: &mut [Scalar], rhs: Scalar)
|
||||
where
|
||||
Scalar: UnsignedInteger,
|
||||
{
|
||||
|
||||
@@ -233,7 +233,7 @@ impl<'a> FourierLweBootstrapKeyView<'a> {
|
||||
lut.as_mut_polynomial_list()
|
||||
.iter_mut()
|
||||
.for_each(|mut poly| {
|
||||
update_polynomial_with_wrapping_monic_monomial_div(
|
||||
polynomial_wrapping_monic_monomial_div_assign(
|
||||
&mut poly,
|
||||
MonomialDegree(monomial_degree),
|
||||
)
|
||||
@@ -254,7 +254,7 @@ impl<'a> FourierLweBootstrapKeyView<'a> {
|
||||
|
||||
// We rotate ct_1 by performing ct_1 <- ct_1 * X^{a_hat}
|
||||
for mut poly in ct1.as_mut_polynomial_list().iter_mut() {
|
||||
update_polynomial_with_wrapping_monic_monomial_mul(
|
||||
polynomial_wrapping_monic_monomial_mul_assign(
|
||||
&mut poly,
|
||||
MonomialDegree(pbs_modulus_switch(
|
||||
*lwe_mask_element,
|
||||
|
||||
@@ -1022,7 +1022,7 @@ pub fn blind_rotate<Scalar: UnsignedTorus + CastInto<usize>>(
|
||||
ct_1.as_mut_polynomial_list()
|
||||
.iter_mut()
|
||||
.for_each(|mut poly| {
|
||||
update_polynomial_with_wrapping_monic_monomial_div(&mut poly, monomial_degree)
|
||||
polynomial_wrapping_monic_monomial_div_assign(&mut poly, monomial_degree)
|
||||
});
|
||||
monomial_degree.0 <<= 1;
|
||||
cmux(ct_0, ct_1, ggsw, fft, stack);
|
||||
|
||||
@@ -322,10 +322,7 @@ fn test_circuit_bootstrapping_binary() {
|
||||
|
||||
let multiplying_factor = 0u64.wrapping_sub(value);
|
||||
|
||||
update_slice_with_wrapping_scalar_mul(
|
||||
expected_decryption.as_mut(),
|
||||
multiplying_factor,
|
||||
);
|
||||
slice_wrapping_scalar_mul_assign(expected_decryption.as_mut(), multiplying_factor);
|
||||
|
||||
let decomposer =
|
||||
SignedDecomposer::new(base_log_cbs, DecompositionLevelCount(current_level));
|
||||
|
||||
Reference in New Issue
Block a user