docs(tfhe): update polynomial and slice algorithms naming

- update docstrings to be better rendered in html.
This commit is contained in:
Arthur Meyre
2022-12-07 11:40:08 +01:00
committed by jborfila
parent 0481fdadfb
commit 1b3baf5635
12 changed files with 156 additions and 100 deletions

View File

@@ -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 {

View File

@@ -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(),

View File

@@ -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);
}

View File

@@ -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(),

View File

@@ -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>(

View File

@@ -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());
}
}

View File

@@ -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(

View File

@@ -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);

View File

@@ -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,
{

View File

@@ -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,

View File

@@ -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);

View File

@@ -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));