use crate::conformance::ParameterSetConformant;
use crate::core_crypto::backward_compatibility::entities::glwe_keyswitch_key::GlweKeyswitchKeyVersions;
use crate::core_crypto::commons::parameters::*;
use crate::core_crypto::commons::traits::*;
use crate::core_crypto::entities::*;
use tfhe_versionable::Versionize;
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(GlweKeyswitchKeyVersions)]
pub struct GlweKeyswitchKey<C: Container>
where
C::Element: UnsignedInteger,
{
data: C,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
output_glwe_size: GlweSize,
poly_size: PolynomialSize,
ciphertext_modulus: CiphertextModulus<C::Element>,
}
impl<T: UnsignedInteger, C: Container<Element = T>> AsRef<[T]> for GlweKeyswitchKey<C> {
fn as_ref(&self) -> &[T] {
self.data.as_ref()
}
}
impl<T: UnsignedInteger, C: ContainerMut<Element = T>> AsMut<[T]> for GlweKeyswitchKey<C> {
fn as_mut(&mut self) -> &mut [T] {
self.data.as_mut()
}
}
pub fn glwe_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count: DecompositionLevelCount,
output_glwe_size: GlweSize,
poly_size: PolynomialSize,
) -> usize {
decomp_level_count.0 * glwe_ciphertext_size(output_glwe_size, poly_size)
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> GlweKeyswitchKey<C> {
pub fn from_container(
container: C,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
output_glwe_size: GlweSize,
poly_size: PolynomialSize,
ciphertext_modulus: CiphertextModulus<C::Element>,
) -> Self {
assert!(
container.container_len() > 0,
"Got an empty container to create a GlweKeyswitchKey"
);
assert!(
container.container_len().is_multiple_of(
glwe_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count,
output_glwe_size,
poly_size
)
),
"The provided container length is not valid. \
It needs to be dividable by decomp_level_count * output_glwe_size * output_poly_size: {}. \
Got container length: {} and decomp_level_count: {decomp_level_count:?}, \
output_glwe_size: {output_glwe_size:?}, poly_size: {poly_size:?}.",
decomp_level_count.0 * output_glwe_size.0 * poly_size.0,
container.container_len()
);
Self {
data: container,
decomp_base_log,
decomp_level_count,
output_glwe_size,
poly_size,
ciphertext_modulus,
}
}
pub fn decomposition_base_log(&self) -> DecompositionBaseLog {
self.decomp_base_log
}
pub fn decomposition_level_count(&self) -> DecompositionLevelCount {
self.decomp_level_count
}
pub fn input_key_glwe_dimension(&self) -> GlweDimension {
GlweDimension(self.data.container_len() / self.input_key_element_encrypted_size())
}
pub fn polynomial_size(&self) -> PolynomialSize {
self.poly_size
}
pub fn output_key_glwe_dimension(&self) -> GlweDimension {
self.output_glwe_size.to_glwe_dimension()
}
pub fn output_glwe_size(&self) -> GlweSize {
self.output_glwe_size
}
pub fn input_key_element_encrypted_size(&self) -> usize {
glwe_keyswitch_key_input_key_element_encrypted_size(
self.decomp_level_count,
self.output_glwe_size,
self.poly_size,
)
}
pub fn as_view(&self) -> GlweKeyswitchKey<&'_ [Scalar]> {
GlweKeyswitchKey::from_container(
self.as_ref(),
self.decomp_base_log,
self.decomp_level_count,
self.output_glwe_size,
self.poly_size,
self.ciphertext_modulus,
)
}
pub fn into_container(self) -> C {
self.data
}
pub fn as_glwe_ciphertext_list(&self) -> GlweCiphertextListView<'_, Scalar> {
GlweCiphertextListView::from_container(
self.as_ref(),
self.output_glwe_size(),
self.polynomial_size(),
self.ciphertext_modulus(),
)
}
pub fn ciphertext_modulus(&self) -> CiphertextModulus<C::Element> {
self.ciphertext_modulus
}
}
impl<Scalar: UnsignedInteger, C: ContainerMut<Element = Scalar>> GlweKeyswitchKey<C> {
pub fn as_mut_view(&mut self) -> GlweKeyswitchKey<&'_ mut [Scalar]> {
let decomp_base_log = self.decomp_base_log;
let decomp_level_count = self.decomp_level_count;
let output_glwe_size = self.output_glwe_size;
let poly_size = self.poly_size;
let ciphertext_modulus = self.ciphertext_modulus;
GlweKeyswitchKey::from_container(
self.as_mut(),
decomp_base_log,
decomp_level_count,
output_glwe_size,
poly_size,
ciphertext_modulus,
)
}
pub fn as_mut_glwe_ciphertext_list(&mut self) -> GlweCiphertextListMutView<'_, Scalar> {
let output_glwe_size = self.output_glwe_size();
let poly_size = self.polynomial_size();
let ciphertext_modulus = self.ciphertext_modulus();
GlweCiphertextListMutView::from_container(
self.as_mut(),
output_glwe_size,
poly_size,
ciphertext_modulus,
)
}
}
pub type GlweKeyswitchKeyOwned<Scalar> = GlweKeyswitchKey<Vec<Scalar>>;
pub type GlweKeyswitchKeyView<'data, Scalar> = GlweKeyswitchKey<&'data [Scalar]>;
pub type GlweKeyswitchKeyMutView<'data, Scalar> = GlweKeyswitchKey<&'data mut [Scalar]>;
impl<Scalar: UnsignedInteger> GlweKeyswitchKeyOwned<Scalar> {
pub fn new(
fill_with: Scalar,
decomp_base_log: DecompositionBaseLog,
decomp_level_count: DecompositionLevelCount,
input_key_glwe_dimension: GlweDimension,
output_key_glwe_dimension: GlweDimension,
poly_size: PolynomialSize,
ciphertext_modulus: CiphertextModulus<Scalar>,
) -> Self {
Self::from_container(
vec![
fill_with;
input_key_glwe_dimension.0
* glwe_keyswitch_key_input_key_element_encrypted_size(
decomp_level_count,
output_key_glwe_dimension.to_glwe_size(),
poly_size,
)
],
decomp_base_log,
decomp_level_count,
output_key_glwe_dimension.to_glwe_size(),
poly_size,
ciphertext_modulus,
)
}
}
#[derive(Clone, Copy)]
pub struct GlweKeyswitchKeyCreationMetadata<Scalar: UnsignedInteger> {
pub decomp_base_log: DecompositionBaseLog,
pub decomp_level_count: DecompositionLevelCount,
pub output_glwe_size: GlweSize,
pub polynomial_size: PolynomialSize,
pub ciphertext_modulus: CiphertextModulus<Scalar>,
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> CreateFrom<C>
for GlweKeyswitchKey<C>
{
type Metadata = GlweKeyswitchKeyCreationMetadata<Scalar>;
#[inline]
fn create_from(from: C, meta: Self::Metadata) -> Self {
let GlweKeyswitchKeyCreationMetadata {
decomp_base_log,
decomp_level_count,
output_glwe_size,
polynomial_size,
ciphertext_modulus,
} = meta;
Self::from_container(
from,
decomp_base_log,
decomp_level_count,
output_glwe_size,
polynomial_size,
ciphertext_modulus,
)
}
}
impl<Scalar: UnsignedInteger, C: Container<Element = Scalar>> ContiguousEntityContainer
for GlweKeyswitchKey<C>
{
type Element = C::Element;
type EntityViewMetadata = GlweCiphertextListCreationMetadata<Self::Element>;
type EntityView<'this>
= GlweCiphertextListView<'this, Self::Element>
where
Self: 'this;
type SelfViewMetadata = GlweKeyswitchKeyCreationMetadata<Self::Element>;
type SelfView<'this>
= GlweKeyswitchKeyView<'this, Self::Element>
where
Self: 'this;
fn get_entity_view_creation_metadata(&self) -> Self::EntityViewMetadata {
GlweCiphertextListCreationMetadata {
glwe_size: self.output_glwe_size(),
polynomial_size: self.polynomial_size(),
ciphertext_modulus: self.ciphertext_modulus(),
}
}
fn get_entity_view_pod_size(&self) -> usize {
self.input_key_element_encrypted_size()
}
fn get_self_view_creation_metadata(&self) -> Self::SelfViewMetadata {
GlweKeyswitchKeyCreationMetadata {
decomp_base_log: self.decomposition_base_log(),
decomp_level_count: self.decomposition_level_count(),
output_glwe_size: self.output_glwe_size(),
polynomial_size: self.polynomial_size(),
ciphertext_modulus: self.ciphertext_modulus(),
}
}
}
impl<Scalar: UnsignedInteger, C: ContainerMut<Element = Scalar>> ContiguousEntityContainerMut
for GlweKeyswitchKey<C>
{
type EntityMutView<'this>
= GlweCiphertextListMutView<'this, Self::Element>
where
Self: 'this;
type SelfMutView<'this>
= GlweKeyswitchKeyMutView<'this, Self::Element>
where
Self: 'this;
}
pub struct GlweKeyswitchKeyConformanceParams {
pub decomp_base_log: DecompositionBaseLog,
pub decomp_level_count: DecompositionLevelCount,
pub output_glwe_size: GlweSize,
pub input_glwe_dimension: GlweDimension,
pub polynomial_size: PolynomialSize,
pub ciphertext_modulus: CiphertextModulus<u64>,
}
impl<C: Container<Element = u64>> ParameterSetConformant for GlweKeyswitchKey<C> {
type ParameterSet = GlweKeyswitchKeyConformanceParams;
fn is_conformant(&self, parameter_set: &Self::ParameterSet) -> bool {
let Self {
data,
decomp_base_log,
decomp_level_count,
output_glwe_size,
poly_size,
ciphertext_modulus,
} = self;
*ciphertext_modulus == parameter_set.ciphertext_modulus
&& data.container_len()
== parameter_set.input_glwe_dimension.0
* glwe_keyswitch_key_input_key_element_encrypted_size(
parameter_set.decomp_level_count,
parameter_set.output_glwe_size,
parameter_set.polynomial_size,
)
&& *decomp_base_log == parameter_set.decomp_base_log
&& *decomp_level_count == parameter_set.decomp_level_count
&& *output_glwe_size == parameter_set.output_glwe_size
&& *poly_size == parameter_set.polynomial_size
}
}