use tfhe_versionable::Versionize;
use crate::conformance::ParameterSetConformant;
use crate::core_crypto::backward_compatibility::entities::lwe_ciphertext::LweCiphertextVersions;
use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::prelude::misc::check_encrypted_content_respects_mod;
#[derive(Clone, Debug)]
pub struct LweBody<Scalar: UnsignedInteger> {
pub data: Scalar,
ciphertext_modulus: CiphertextModulus<Scalar>,
}
#[derive(Debug)]
pub struct LweBodyRef<'a, Scalar: UnsignedInteger> {
pub data: &'a Scalar,
ciphertext_modulus: CiphertextModulus<Scalar>,
}
#[derive(Debug)]
pub struct LweBodyRefMut<'a, Scalar: UnsignedInteger> {
pub data: &'a mut Scalar,
ciphertext_modulus: CiphertextModulus<Scalar>,
}
impl<Scalar: UnsignedInteger> LweBody<Scalar> {
pub fn new(data: Scalar, ciphertext_modulus: CiphertextModulus<Scalar>) -> Self {
Self {
data,
ciphertext_modulus,
}
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<Scalar> {
self.ciphertext_modulus
}
}
impl<'outer, T: UnsignedInteger> LweBodyRef<'outer, T> {
pub fn new(data: &'outer T, ciphertext_modulus: CiphertextModulus<T>) -> Self {
Self {
data,
ciphertext_modulus,
}
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<T> {
self.ciphertext_modulus
}
}
impl<'outer, T: UnsignedInteger> LweBodyRefMut<'outer, T> {
pub fn new(data: &'outer mut T, ciphertext_modulus: CiphertextModulus<T>) -> Self {
Self {
data,
ciphertext_modulus,
}
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<T> {
self.ciphertext_modulus
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data [T]> for LweBodyRef<'data, T> {
type Metadata = LweBodyCreationMetadata<T>;
#[inline]
fn create_from(from: &[T], meta: Self::Metadata) -> LweBodyRef<T> {
let LweBodyCreationMetadata { ciphertext_modulus } = meta;
LweBodyRef {
data: &from[0],
ciphertext_modulus,
}
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data mut [T]> for LweBodyRefMut<'data, T> {
type Metadata = LweBodyCreationMetadata<T>;
#[inline]
fn create_from(from: &mut [T], meta: Self::Metadata) -> LweBodyRefMut<T> {
let LweBodyCreationMetadata { ciphertext_modulus } = meta;
LweBodyRefMut {
data: &mut from[0],
ciphertext_modulus,
}
}
}
#[derive(Clone, Debug)]
pub struct LweBodyList<C: Container>
where
C::Element: UnsignedInteger,
{
data: C,
ciphertext_modulus: CiphertextModulus<C::Element>,
}
pub type LweBodyListView<'data, Scalar> = LweBodyList<&'data [Scalar]>;
pub type LweBodyListMutView<'data, Scalar> = LweBodyList<&'data mut [Scalar]>;
impl<T: UnsignedInteger, C: Container<Element = T>> AsRef<[T]> for LweBodyList<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T: UnsignedInteger, C: ContainerMut<Element = T>> AsMut<[T]> for LweBodyList<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data [T]> for LweBodyListView<'data, T> {
type Metadata = LweBodyListCreationMetadata<T>;
#[inline]
fn create_from(from: &[T], meta: Self::Metadata) -> LweBodyListView<'_, T> {
let LweBodyListCreationMetadata { ciphertext_modulus } = meta;
LweBodyList {
data: from,
ciphertext_modulus,
}
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data mut [T]> for LweBodyListMutView<'data, T> {
type Metadata = LweBodyListCreationMetadata<T>;
#[inline]
fn create_from(from: &mut [T], meta: Self::Metadata) -> LweBodyListMutView<'_, T> {
let LweBodyListCreationMetadata { ciphertext_modulus } = meta;
LweBodyList {
data: from,
ciphertext_modulus,
}
}
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweBodyList<C> {
pub fn from_container(container: C, ciphertext_modulus: CiphertextModulus<Scalar>) -> Self {
Self {
data: container,
ciphertext_modulus,
}
}
pub fn lwe_body_count(&self) -> LweBodyCount {
LweBodyCount(self.data.container_len())
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<Scalar> {
self.ciphertext_modulus
}
}
#[derive(Clone, Copy)]
pub struct LweBodyCreationMetadata<Scalar: UnsignedInteger> {
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
#[derive(Clone, Copy)]
pub struct LweBodyListCreationMetadata<Scalar: UnsignedInteger> {
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> ContiguousEntityContainer
for LweBodyList<C>
{
type Element = C::Element;
type EntityViewMetadata = LweBodyCreationMetadata<Self::Element>;
type EntityView<'this> = LweBodyRef<'this, Self::Element>
where
Self: 'this;
type SelfViewMetadata = LweBodyListCreationMetadata<Self::Element>;
type SelfView<'this> = LweBodyListView<'this,Self::Element>
where
Self: 'this;
fn get_entity_view_creation_metadata(&self) -> Self::EntityViewMetadata {
LweBodyCreationMetadata {
ciphertext_modulus: self.ciphertext_modulus(),
}
}
fn get_entity_view_pod_size(&self) -> usize {
1
}
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
LweBodyListCreationMetadata {
ciphertext_modulus: self.ciphertext_modulus(),
}
}
}
impl<Scalar: UnsignedInteger, C: ContainerMut<Element = Scalar>> ContiguousEntityContainerMut
for LweBodyList<C>
{
type EntityMutView<'this> = LweBodyRefMut<'this, Self::Element>
where
Self: 'this;
type SelfMutView<'this> = LweBodyListMutView<'this, Self::Element>
where
Self: 'this;
}
#[derive(Clone, Debug)]
pub struct LweMask<C: Container>
where
C::Element: UnsignedInteger,
{
data: C,
ciphertext_modulus: CiphertextModulus<C::Element>,
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweMask<C> {
pub fn from_container(container: C, ciphertext_modulus: CiphertextModulus<C::Element>) -> Self {
Self {
data: container,
ciphertext_modulus,
}
}
pub fn lwe_dimension(&self) -> LweDimension {
LweDimension(self.data.container_len())
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<C::Element> {
self.ciphertext_modulus
}
}
impl<T: UnsignedInteger, C: Container<Element = T>> AsRef<[T]> for LweMask<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T: UnsignedInteger, C: ContainerMut<Element = T>> AsMut<[T]> for LweMask<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data [T]> for LweMask<&'data [T]> {
type Metadata = LweMaskCreationMetadata<T>;
#[inline]
fn create_from(from: &[T], meta: Self::Metadata) -> LweMask<&[T]> {
let LweMaskCreationMetadata { ciphertext_modulus } = meta;
LweMask {
data: from,
ciphertext_modulus,
}
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data mut [T]> for LweMask<&'data mut [T]> {
type Metadata = LweMaskCreationMetadata<T>;
#[inline]
fn create_from(from: &mut [T], meta: Self::Metadata) -> LweMask<&mut [T]> {
let LweMaskCreationMetadata { ciphertext_modulus } = meta;
LweMask {
data: from,
ciphertext_modulus,
}
}
}
#[derive(Clone, Debug)]
pub struct LweMaskList<C: Container>
where
C::Element: UnsignedInteger,
{
data: C,
lwe_dimension: LweDimension,
ciphertext_modulus: CiphertextModulus<C::Element>,
}
pub type LweMaskListView<'data, Scalar> = LweMaskList<&'data [Scalar]>;
pub type LweMaskListMutView<'data, Scalar> = LweMaskList<&'data mut [Scalar]>;
pub fn lwe_mask_list_size(lwe_dimension: LweDimension, lwe_mask_count: LweMaskCount) -> usize {
lwe_dimension.0 * lwe_mask_count.0
}
impl<T: UnsignedInteger, C: Container<Element = T>> AsRef<[T]> for LweMaskList<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T: UnsignedInteger, C: ContainerMut<Element = T>> AsMut<[T]> for LweMaskList<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data [T]> for LweMaskListView<'data, T> {
type Metadata = LweMaskListCreationMetadata<T>;
#[inline]
fn create_from(from: &[T], meta: Self::Metadata) -> LweMaskListView<'_, T> {
let LweMaskListCreationMetadata {
lwe_dimension,
ciphertext_modulus,
} = meta;
LweMaskList {
data: from,
lwe_dimension,
ciphertext_modulus,
}
}
}
impl<'data, T: UnsignedInteger> CreateFrom<&'data mut [T]> for LweMaskListMutView<'data, T> {
type Metadata = LweMaskListCreationMetadata<T>;
#[inline]
fn create_from(from: &mut [T], meta: Self::Metadata) -> LweMaskListMutView<'_, T> {
let LweMaskListCreationMetadata {
lwe_dimension,
ciphertext_modulus,
} = meta;
LweMaskList {
data: from,
lwe_dimension,
ciphertext_modulus,
}
}
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweMaskList<C> {
pub fn from_container(
container: C,
lwe_dimension: LweDimension,
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
assert!(
container.container_len() % lwe_dimension.0 == 0,
"The provided container length is not valid. \
It needs to be dividable by lwe_dimension. \
Got container length: {} and lwe_dimension: {lwe_dimension:?}.",
container.container_len()
);
Self {
data: container,
lwe_dimension,
ciphertext_modulus,
}
}
pub fn lwe_dimension(&self) -> LweDimension {
self.lwe_dimension
}
pub fn lwe_mask_count(&self) -> LweMaskCount {
LweMaskCount(self.data.container_len() / self.lwe_dimension.0)
}
pub fn lwe_mask_list_size(&self) -> usize {
lwe_mask_list_size(self.lwe_dimension(), self.lwe_mask_count())
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<Scalar> {
self.ciphertext_modulus
}
}
#[derive(Clone, Copy)]
pub struct LweMaskCreationMetadata<Scalar: UnsignedInteger> {
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
#[derive(Clone, Copy)]
pub struct LweMaskListCreationMetadata<Scalar: UnsignedInteger> {
pub lwe_dimension: LweDimension,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> ContiguousEntityContainer
for LweMaskList<C>
{
type Element = C::Element;
type EntityViewMetadata = LweMaskCreationMetadata<Self::Element>;
type EntityView<'this> = LweMask<&'this [Self::Element]>
where
Self: 'this;
type SelfViewMetadata = LweMaskListCreationMetadata<Self::Element>;
type SelfView<'this> = LweMaskListView<'this, Self::Element>
where
Self: 'this;
fn get_entity_view_creation_metadata(&self) -> Self::EntityViewMetadata {
LweMaskCreationMetadata {
ciphertext_modulus: self.ciphertext_modulus(),
}
}
fn get_entity_view_pod_size(&self) -> usize {
self.lwe_dimension().0
}
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
LweMaskListCreationMetadata {
lwe_dimension: self.lwe_dimension(),
ciphertext_modulus: self.ciphertext_modulus(),
}
}
}
impl<Scalar: UnsignedInteger, C: ContainerMut<Element = Scalar>> ContiguousEntityContainerMut
for LweMaskList<C>
{
type EntityMutView<'this> = LweMask<&'this mut [Self::Element]>
where
Self: 'this;
type SelfMutView<'this> = LweMaskListMutView<'this,Self::Element>
where
Self: 'this;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(LweCiphertextVersions)]
pub struct LweCiphertext<C: Container>
where
C::Element: UnsignedInteger,
{
data: C,
ciphertext_modulus: CiphertextModulus<C::Element>,
}
impl<T: UnsignedInteger, C: Container<Element = T>> AsRef<[T]> for LweCiphertext<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T: UnsignedInteger, C: ContainerMut<Element = T>> AsMut<[T]> for LweCiphertext<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
#[cfg(test)]
#[allow(dead_code)]
impl<C: Container> LweCiphertext<C>
where
C::Element: UnsignedInteger,
{
pub(crate) fn get_mut_ciphertext_modulus(&mut self) -> &mut CiphertextModulus<C::Element> {
&mut self.ciphertext_modulus
}
}
pub fn lwe_ciphertext_encryption_mask_sample_count(
lwe_dimension: LweDimension,
) -> EncryptionMaskSampleCount {
EncryptionMaskSampleCount(lwe_dimension.0)
}
pub fn lwe_ciphertext_encryption_noise_sample_count() -> EncryptionNoiseSampleCount {
EncryptionNoiseSampleCount(1)
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> LweCiphertext<C> {
pub fn from_container(container: C, ciphertext_modulus: CiphertextModulus<C::Element>) -> Self {
assert!(
container.container_len() > 0,
"Got an empty container to create an LweCiphertext"
);
Self {
data: container,
ciphertext_modulus,
}
}
pub fn lwe_size(&self) -> LweSize {
LweSize(self.data.container_len())
}
pub fn get_mask_and_body(&self) -> (LweMask<&[Scalar]>, LweBodyRef<'_, Scalar>) {
let (body, mask) = self.data.as_ref().split_last().unwrap();
let ciphertext_modulus = self.ciphertext_modulus();
(
LweMask::from_container(mask, ciphertext_modulus),
LweBodyRef {
data: body,
ciphertext_modulus,
},
)
}
pub fn get_body(&self) -> LweBodyRef<'_, Scalar> {
let body = self.data.as_ref().last().unwrap();
let ciphertext_modulus = self.ciphertext_modulus();
LweBodyRef {
data: body,
ciphertext_modulus,
}
}
pub fn get_mask(&self) -> LweMask<&[Scalar]> {
LweMask::from_container(
&self.as_ref()[0..self.lwe_size().to_lwe_dimension().0],
self.ciphertext_modulus(),
)
}
pub fn as_view(&self) -> LweCiphertextView<'_, Scalar> {
LweCiphertextView::from_container(self.as_ref(), self.ciphertext_modulus())
}
pub fn into_container(self) -> C {
self.data
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<C::Element> {
self.ciphertext_modulus
}
}
impl<Scalar: UnsignedInteger, C: ContainerMut<Element = Scalar>> LweCiphertext<C> {
pub fn get_mut_mask_and_body(&mut self) -> (LweMask<&mut [Scalar]>, LweBodyRefMut<'_, Scalar>) {
let ciphertext_modulus = self.ciphertext_modulus();
let (body, mask) = self.data.as_mut().split_last_mut().unwrap();
(
LweMask::from_container(mask, ciphertext_modulus),
LweBodyRefMut {
data: body,
ciphertext_modulus,
},
)
}
pub fn get_mut_body(&mut self) -> LweBodyRefMut<'_, Scalar> {
let ciphertext_modulus = self.ciphertext_modulus();
let body = self.data.as_mut().last_mut().unwrap();
LweBodyRefMut {
data: body,
ciphertext_modulus,
}
}
pub fn get_mut_mask(&mut self) -> LweMask<&mut [Scalar]> {
let lwe_dimension = self.lwe_size().to_lwe_dimension();
let ciphertext_modulus = self.ciphertext_modulus();
LweMask::from_container(&mut self.as_mut()[0..lwe_dimension.0], ciphertext_modulus)
}
pub fn as_mut_view(&mut self) -> LweCiphertextMutView<'_, Scalar> {
let ciphertext_modulus = self.ciphertext_modulus();
LweCiphertextMutView::from_container(self.as_mut(), ciphertext_modulus)
}
}
pub type LweCiphertextOwned<Scalar> = LweCiphertext<Vec<Scalar>>;
pub type LweCiphertextView<'data, Scalar> = LweCiphertext<&'data [Scalar]>;
pub type LweCiphertextMutView<'data, Scalar> = LweCiphertext<&'data mut [Scalar]>;
#[derive(Copy, Clone)]
pub struct LweCiphertextParameters<T: UnsignedInteger> {
pub lwe_dim: LweDimension,
pub ct_modulus: CiphertextModulus<T>,
pub ms_decompression_method: MsDecompressionType,
}
#[derive(Copy, Clone)]
pub enum MsDecompressionType {
ClassicPbs,
MultiBitPbs(LweBskGroupingFactor),
}
impl<C: Container> ParameterSetConformant for LweCiphertext<C>
where
C::Element: UnsignedInteger,
{
type ParameterSet = LweCiphertextParameters<C::Element>;
fn is_conformant(&self, lwe_ct_parameters: &LweCiphertextParameters<C::Element>) -> bool {
let Self {
data,
ciphertext_modulus,
} = self;
check_encrypted_content_respects_mod(data, lwe_ct_parameters.ct_modulus)
&& self.lwe_size() == lwe_ct_parameters.lwe_dim.to_lwe_size()
&& *ciphertext_modulus == lwe_ct_parameters.ct_modulus
}
}
impl<Scalar: UnsignedInteger> LweCiphertextOwned<Scalar> {
pub fn new(
fill_with: Scalar,
lwe_size: LweSize,
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
Self::from_container(vec![fill_with; lwe_size.0], ciphertext_modulus)
}
}
#[derive(Clone, Copy)]
pub struct LweCiphertextCreationMetadata<Scalar: UnsignedInteger> {
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> CreateFrom<C> for LweCiphertext<C> {
type Metadata = LweCiphertextCreationMetadata<C::Element>;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> Self {
let LweCiphertextCreationMetadata { ciphertext_modulus } = meta;
Self::from_container(from, ciphertext_modulus)
}
}