mirror of
https://github.com/zama-ai/tfhe-rs.git
synced 2026-01-09 14:47:56 -05:00
docs(tfhe): add GlweCiphertext documentation
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
/// A GGSW Ciphertext.
|
||||
/// A [`GGSW Ciphertext`](`GgswCiphertext`).
|
||||
///
|
||||
/// # Formal Definition
|
||||
///
|
||||
|
||||
@@ -2,12 +2,29 @@ use crate::core_crypto::commons::parameters::*;
|
||||
use crate::core_crypto::commons::traits::*;
|
||||
use crate::core_crypto::entities::*;
|
||||
|
||||
/// A convenience structure to easily manipulate the body of a [`GlweCiphertext`].
|
||||
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct GlweBody<C: Container> {
|
||||
data: C,
|
||||
}
|
||||
|
||||
impl<C: Container> GlweBody<C> {
|
||||
/// Create a [`GlweBody`] from an existing container.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This docstring exhibits [`GlweBody`] primitives usage.
|
||||
///
|
||||
/// ```
|
||||
/// use tfhe::core_crypto::prelude::*;
|
||||
///
|
||||
/// // Define parameters for GlweBody creation
|
||||
/// let polynomial_size = PolynomialSize(1024);
|
||||
///
|
||||
/// let glwe_body = GlweBody::from_container(vec![0u64; polynomial_size.0]);
|
||||
///
|
||||
/// assert_eq!(glwe_body.polynomial_size(), polynomial_size);
|
||||
/// ```
|
||||
pub fn from_container(container: C) -> GlweBody<C> {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
@@ -16,21 +33,27 @@ impl<C: Container> GlweBody<C> {
|
||||
GlweBody { data: container }
|
||||
}
|
||||
|
||||
/// Returns the [`PolynomialSize`] of the [`GlweBody`].
|
||||
///
|
||||
/// See [`GlweBody::from_container`] for usage.
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
PolynomialSize(self.data.container_len())
|
||||
}
|
||||
|
||||
/// Interprets the [`GlweBody`] as a [`Polynomial`].
|
||||
pub fn as_polynomial(&self) -> PolynomialView<'_, C::Element> {
|
||||
PolynomialView::from_container(self.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> GlweBody<C> {
|
||||
/// Mutable variant of [`GlweBody::as_polynomial`].
|
||||
pub fn as_mut_polynomial(&mut self) -> PolynomialMutView<'_, C::Element> {
|
||||
PolynomialMutView::from_container(self.as_mut())
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience structure to easily manipulate the mask of a [`GlweCiphertext`].
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct GlweMask<C: Container> {
|
||||
data: C,
|
||||
@@ -38,6 +61,24 @@ pub struct GlweMask<C: Container> {
|
||||
}
|
||||
|
||||
impl<C: Container> GlweMask<C> {
|
||||
/// Create a [`GlweMask`] from an existing container.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This docstring exhibits [`GlweMask`] primitives usage.
|
||||
///
|
||||
/// ```
|
||||
/// use tfhe::core_crypto::prelude::*;
|
||||
///
|
||||
/// // Define parameters for GlweMask creation
|
||||
/// let glwe_dimension = GlweDimension(1);
|
||||
/// let polynomial_size = PolynomialSize(1024);
|
||||
///
|
||||
/// let glwe_mask = GlweMask::from_container(vec![0u64; glwe_dimension.0 * polynomial_size.0]);
|
||||
///
|
||||
/// assert_eq!(glwe_mask.glwe_dimension(), glwe_dimension);
|
||||
/// assert_eq!(glwe_mask.polynomial_size(), polynomial_size);
|
||||
/// ```
|
||||
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> Self {
|
||||
assert!(
|
||||
container.container_len() % polynomial_size.0 == 0,
|
||||
@@ -52,20 +93,28 @@ impl<C: Container> GlweMask<C> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
/// Returns the [`GlweDimension`] of the [`GlweMask`].
|
||||
///
|
||||
/// See [`GlweMask::from_container`] for usage.
|
||||
pub fn glwe_dimension(&self) -> GlweDimension {
|
||||
GlweDimension(self.data.container_len() / self.polynomial_size.0)
|
||||
}
|
||||
|
||||
/// Returns the [`PolynomialSize`] of the [`GlweMask`].
|
||||
///
|
||||
/// See [`GlweMask::from_container`] for usage.
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
/// Interprets the [`GlweMask`] as a [`PolynomialList`].
|
||||
pub fn as_polynomial_list(&self) -> PolynomialListView<'_, C::Element> {
|
||||
PolynomialListView::from_container(self.as_ref(), self.polynomial_size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ContainerMut> GlweMask<C> {
|
||||
/// Mutable variant of [`GlweMask::as_polynomial_list`].
|
||||
pub fn as_mut_polynomial_list(&mut self) -> PolynomialListMutView<'_, C::Element> {
|
||||
let polynomial_size = self.polynomial_size;
|
||||
PolynomialListMutView::from_container(self.as_mut(), polynomial_size)
|
||||
@@ -96,17 +145,48 @@ impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweBody<C> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of elements in a [`GlweCiphertext`] given a [`GlweSize`] and
|
||||
/// [`PolynomialSize`].
|
||||
pub fn glwe_ciphertext_size(glwe_size: GlweSize, polynomial_size: PolynomialSize) -> usize {
|
||||
glwe_size.0 * polynomial_size.0
|
||||
}
|
||||
|
||||
/// Returns the number of elements in a [`GlweMask`] given a [`GlweDimension`] and
|
||||
/// [`PolynomialSize`].
|
||||
pub fn glwe_ciphertext_mask_size(
|
||||
polynomial_size: PolynomialSize,
|
||||
glwe_dimension: GlweDimension,
|
||||
polynomial_size: PolynomialSize,
|
||||
) -> usize {
|
||||
polynomial_size.0 * glwe_dimension.0
|
||||
glwe_dimension.0 * polynomial_size.0
|
||||
}
|
||||
|
||||
/// A [`GLWE ciphertext`](`GlweCiphertext`).
|
||||
///
|
||||
/// **Remark:** GLWE ciphertexts generalize LWE ciphertexts by definition, however in this library,
|
||||
/// GLWE ciphertext entities do not generalize LWE ciphertexts, i.e., polynomial size cannot be 1.
|
||||
///
|
||||
/// # Formal Definition
|
||||
///
|
||||
/// ## GLWE Ciphertext
|
||||
///
|
||||
/// A GLWE ciphertext is an encryption of a polynomial plaintext.
|
||||
/// It is secure under the hardness assumption called General Learning With Errors (GLWE). It is a
|
||||
/// generalization of both [`LWE ciphertexts`](`crate::core_crypto::entities::LweCiphertext`) and
|
||||
/// RLWE ciphertexts. GLWE requires a cyclotomic ring. We use the notation $\mathcal{R}\_q$ for the
|
||||
/// following cyclotomic ring: $\mathbb{Z}\_q\[X\]/\left\langle X^N + 1\right\rangle$ where
|
||||
/// $N\in\mathbb{N}$ is a power of two.
|
||||
///
|
||||
/// We call $q$ the ciphertext modulus and $N$ the ring dimension.
|
||||
///
|
||||
/// We indicate a GLWE ciphertext of a plaintext $\mathsf{PT} \in\mathcal{R}\_q^{k+1}$ as the
|
||||
/// following couple: $$\mathsf{CT} = \left( \vec{A}, B\right) = \left( A\_0, \ldots, A\_{k-1},
|
||||
/// B\right) \in \mathsf{GLWE}\_{\vec{S}} \left( \mathsf{PT} \right) \subseteq
|
||||
/// \mathcal{R}\_q^{k+1}$$
|
||||
///
|
||||
/// ## Generalisation of LWE and RLWE
|
||||
///
|
||||
/// When we set $k=1$ a GLWE ciphertext becomes an RLWE ciphertext.
|
||||
/// When we set $N=1$ a GLWE ciphertext becomes an LWE ciphertext with $n=k$.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct GlweCiphertext<C: Container> {
|
||||
data: C,
|
||||
@@ -126,6 +206,34 @@ impl<T, C: ContainerMut<Element = T>> AsMut<[T]> for GlweCiphertext<C> {
|
||||
}
|
||||
|
||||
impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
|
||||
/// Create a [`GlweCiphertext`] from an existing container.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This docstring exhibits [`GlweCiphertext`] primitives usage.
|
||||
///
|
||||
/// ```
|
||||
/// use tfhe::core_crypto::prelude::*;
|
||||
///
|
||||
/// // Define parameters for GlweCiphertext creation
|
||||
/// let glwe_size = GlweSize(2);
|
||||
/// let polynomial_size = PolynomialSize(1024);
|
||||
///
|
||||
/// // Create a new GlweCiphertext
|
||||
/// let glwe = GlweCiphertext::new(0u64, glwe_size, polynomial_size);
|
||||
///
|
||||
/// assert_eq!(glwe.glwe_size(), glwe_size);
|
||||
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
|
||||
///
|
||||
/// // Demonstrate how to recover the allocated container
|
||||
/// let underlying_container: Vec<u64> = glwe.into_container();
|
||||
///
|
||||
/// // Recreate a ciphertext using from_container
|
||||
/// let glwe = GlweCiphertext::from_container(underlying_container, polynomial_size);
|
||||
///
|
||||
/// assert_eq!(glwe.glwe_size(), glwe_size);
|
||||
/// assert_eq!(glwe.polynomial_size(), polynomial_size);
|
||||
/// ```
|
||||
pub fn from_container(container: C, polynomial_size: PolynomialSize) -> GlweCiphertext<C> {
|
||||
assert!(
|
||||
container.container_len() > 0,
|
||||
@@ -144,18 +252,25 @@ impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
/// Returns the [`GlweSize`] of the [`GlweCiphertext`].
|
||||
///
|
||||
/// See [`GlweCiphertext::from_container`] for usage.
|
||||
pub fn glwe_size(&self) -> GlweSize {
|
||||
GlweSize(self.as_ref().container_len() / self.polynomial_size.0)
|
||||
}
|
||||
|
||||
/// Returns the [`PolynomialSize`] of the [`GlweCiphertext`].
|
||||
///
|
||||
/// See [`GlweCiphertext::from_container`] for usage.
|
||||
pub fn polynomial_size(&self) -> PolynomialSize {
|
||||
self.polynomial_size
|
||||
}
|
||||
|
||||
/// Returns immutable views to the [`GlweMask`] and [`GlweBody`] of a [`GlweCiphertext`].
|
||||
pub fn get_mask_and_body(&self) -> (GlweMask<&[Scalar]>, GlweBody<&[Scalar]>) {
|
||||
let (mask, body) = self.data.as_ref().split_at(glwe_ciphertext_mask_size(
|
||||
self.polynomial_size,
|
||||
self.glwe_size().to_glwe_dimension(),
|
||||
self.polynomial_size,
|
||||
));
|
||||
|
||||
(
|
||||
@@ -164,29 +279,34 @@ impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns an immutable view to the [`GlweBody`] of a [`GlweCiphertext`].
|
||||
pub fn get_body(&self) -> GlweBody<&[Scalar]> {
|
||||
let body = &self.data.as_ref()[glwe_ciphertext_mask_size(
|
||||
self.polynomial_size,
|
||||
self.glwe_size().to_glwe_dimension(),
|
||||
self.polynomial_size,
|
||||
)..];
|
||||
|
||||
GlweBody::from_container(body)
|
||||
}
|
||||
|
||||
/// Returns an immutable view to the [`GlweMask`] of a [`GlweCiphertext`].
|
||||
pub fn get_mask(&self) -> GlweMask<&[Scalar]> {
|
||||
GlweMask::from_container(
|
||||
&self.as_ref()[0..glwe_ciphertext_mask_size(
|
||||
self.polynomial_size,
|
||||
self.glwe_size().to_glwe_dimension(),
|
||||
self.polynomial_size,
|
||||
)],
|
||||
self.polynomial_size,
|
||||
)
|
||||
}
|
||||
|
||||
/// Interprets the [`GlweCiphertext`] as a [`PolynomialList`].
|
||||
pub fn as_polynomial_list(&self) -> PolynomialList<&'_ [Scalar]> {
|
||||
PolynomialList::from_container(self.as_ref(), self.polynomial_size)
|
||||
}
|
||||
|
||||
/// Returns a view of the [`GlweCiphertext`]. This is useful if an algorithm takes a view by
|
||||
/// value.
|
||||
pub fn as_view(&self) -> GlweCiphertext<&'_ [Scalar]> {
|
||||
GlweCiphertext {
|
||||
data: self.data.as_ref(),
|
||||
@@ -201,14 +321,15 @@ impl<Scalar, C: Container<Element = Scalar>> GlweCiphertext<C> {
|
||||
}
|
||||
|
||||
impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertext<C> {
|
||||
/// Mutable variant of [`GlweCiphertext::get_mask_and_body`].
|
||||
pub fn get_mut_mask_and_body(&mut self) -> (GlweMask<&mut [Scalar]>, GlweBody<&mut [Scalar]>) {
|
||||
let polynomial_size = self.polynomial_size();
|
||||
let glwe_dimension = self.glwe_size().to_glwe_dimension();
|
||||
let polynomial_size = self.polynomial_size();
|
||||
|
||||
let (mask, body) = self
|
||||
.data
|
||||
.as_mut()
|
||||
.split_at_mut(glwe_ciphertext_mask_size(polynomial_size, glwe_dimension));
|
||||
.split_at_mut(glwe_ciphertext_mask_size(glwe_dimension, polynomial_size));
|
||||
|
||||
(
|
||||
GlweMask::from_container(mask, polynomial_size),
|
||||
@@ -216,31 +337,35 @@ impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertext<C> {
|
||||
)
|
||||
}
|
||||
|
||||
/// Mutable variant of [`GlweCiphertext::get_body`].
|
||||
pub fn get_mut_body(&mut self) -> GlweBody<&mut [Scalar]> {
|
||||
let polynomial_size = self.polynomial_size();
|
||||
let glwe_dimension = self.glwe_size().to_glwe_dimension();
|
||||
let polynomial_size = self.polynomial_size();
|
||||
|
||||
let body =
|
||||
&mut self.data.as_mut()[glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)..];
|
||||
&mut self.data.as_mut()[glwe_ciphertext_mask_size(glwe_dimension, polynomial_size)..];
|
||||
|
||||
GlweBody::from_container(body)
|
||||
}
|
||||
|
||||
/// Mutable variant of [`GlweCiphertext::get_mask`].
|
||||
pub fn get_mut_mask(&mut self) -> GlweMask<&mut [Scalar]> {
|
||||
let polynomial_size = self.polynomial_size();
|
||||
let glwe_dimension = self.glwe_size().to_glwe_dimension();
|
||||
|
||||
GlweMask::from_container(
|
||||
&mut self.as_mut()[0..glwe_ciphertext_mask_size(polynomial_size, glwe_dimension)],
|
||||
&mut self.as_mut()[0..glwe_ciphertext_mask_size(glwe_dimension, polynomial_size)],
|
||||
polynomial_size,
|
||||
)
|
||||
}
|
||||
|
||||
/// Mutable variant of [`GlweCiphertext::as_polynomial_list`].
|
||||
pub fn as_mut_polynomial_list(&mut self) -> PolynomialList<&'_ mut [Scalar]> {
|
||||
let polynomial_size = self.polynomial_size;
|
||||
PolynomialList::from_container(self.as_mut(), polynomial_size)
|
||||
}
|
||||
|
||||
/// Mutable variant of [`GlweCiphertext::as_view`].
|
||||
pub fn as_mut_view(&mut self) -> GlweCiphertext<&'_ mut [Scalar]> {
|
||||
GlweCiphertext {
|
||||
data: self.data.as_mut(),
|
||||
@@ -249,11 +374,17 @@ impl<Scalar, C: ContainerMut<Element = Scalar>> GlweCiphertext<C> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A [`GlweCiphertext`] owning the memory for its own storage.
|
||||
pub type GlweCiphertextOwned<Scalar> = GlweCiphertext<Vec<Scalar>>;
|
||||
/// A [`GlweCiphertext`] immutably borrowing memory for its own storage.
|
||||
pub type GlweCiphertextView<'data, Scalar> = GlweCiphertext<&'data [Scalar]>;
|
||||
/// A [`GlweCiphertext`] mutably borrowing memory for its own storage.
|
||||
pub type GlweCiphertextMutView<'data, Scalar> = GlweCiphertext<&'data mut [Scalar]>;
|
||||
|
||||
impl<Scalar: Copy> GlweCiphertextOwned<Scalar> {
|
||||
/// Allocate memory and create a new owned [`GlweCiphertext`].
|
||||
///
|
||||
/// See [`GlweCiphertext::from_container`] for usage.
|
||||
pub fn new(
|
||||
fill_with: Scalar,
|
||||
glwe_size: GlweSize,
|
||||
@@ -266,6 +397,7 @@ impl<Scalar: Copy> GlweCiphertextOwned<Scalar> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata used in the [`CreateFrom`] implementation to create [`GlweCiphertext`] entities.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GlweCiphertextCreationMetadata(pub PolynomialSize);
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ impl<Scalar: Copy> GlweCiphertextListOwned<Scalar> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Metadata used in the [`CreateFrom`] implementation to create [`GlweCiphertextList`] entities.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct GlweCiphertextListCreationMetadata(pub GlweSize, pub PolynomialSize);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user