use tfhe_versionable::Versionize;
use crate::conformance::ParameterSetConformant;
use crate::integer::backward_compatibility::ciphertext::{
CompressedModulusSwitchedRadixCiphertextGenericVersions,
CompressedModulusSwitchedRadixCiphertextVersions,
CompressedModulusSwitchedSignedRadixCiphertextVersions,
};
use crate::integer::parameters::RadixCiphertextConformanceParams;
use crate::shortint::ciphertext::{
CompressedModulusSwitchedCiphertext, CompressedModulusSwitchedCiphertextConformanceParams,
MaxDegree,
};
use crate::shortint::parameters::Degree;
#[derive(Clone, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(CompressedModulusSwitchedRadixCiphertextVersions)]
pub struct CompressedModulusSwitchedRadixCiphertext(
pub(crate) CompressedModulusSwitchedRadixCiphertextGeneric,
);
impl ParameterSetConformant for CompressedModulusSwitchedRadixCiphertext {
type ParameterSet = CompressedModulusSwitchedRadixCiphertextConformanceParams;
fn is_conformant(
&self,
params: &CompressedModulusSwitchedRadixCiphertextConformanceParams,
) -> bool {
let Self(ct) = self;
ct.is_conformant(params)
}
}
#[derive(Clone, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(CompressedModulusSwitchedSignedRadixCiphertextVersions)]
pub struct CompressedModulusSwitchedSignedRadixCiphertext(
pub(crate) CompressedModulusSwitchedRadixCiphertextGeneric,
);
impl ParameterSetConformant for CompressedModulusSwitchedSignedRadixCiphertext {
type ParameterSet = CompressedModulusSwitchedRadixCiphertextConformanceParams;
fn is_conformant(
&self,
params: &CompressedModulusSwitchedRadixCiphertextConformanceParams,
) -> bool {
let Self(ct) = self;
ct.is_conformant(params)
}
}
#[derive(Clone, serde::Serialize, serde::Deserialize, Versionize)]
#[versionize(CompressedModulusSwitchedRadixCiphertextGenericVersions)]
pub(crate) struct CompressedModulusSwitchedRadixCiphertextGeneric {
pub paired_blocks: Vec<CompressedModulusSwitchedCiphertext>,
pub last_block: Option<CompressedModulusSwitchedCiphertext>,
}
#[derive(Copy, Clone)]
pub struct CompressedModulusSwitchedRadixCiphertextConformanceParams {
pub shortint_params: CompressedModulusSwitchedCiphertextConformanceParams,
pub num_blocks_per_integer: usize,
}
impl From<CompressedModulusSwitchedRadixCiphertextConformanceParams>
for RadixCiphertextConformanceParams
{
fn from(value: CompressedModulusSwitchedRadixCiphertextConformanceParams) -> Self {
Self {
shortint_params: value.shortint_params.into(),
num_blocks_per_integer: value.num_blocks_per_integer,
}
}
}
impl ParameterSetConformant for CompressedModulusSwitchedRadixCiphertextGeneric {
type ParameterSet = CompressedModulusSwitchedRadixCiphertextConformanceParams;
fn is_conformant(
&self,
params: &CompressedModulusSwitchedRadixCiphertextConformanceParams,
) -> bool {
let Self {
paired_blocks,
last_block,
} = self;
let mut shortint_params = params.shortint_params;
shortint_params.degree = Degree::new(
MaxDegree::from_msg_carry_modulus(
shortint_params.message_modulus,
shortint_params.carry_modulus,
)
.get(),
);
let paired_blocks_len_ok = paired_blocks.len() == params.num_blocks_per_integer / 2;
let paired_blocks_ok = paired_blocks
.iter()
.all(|block| block.is_conformant(&shortint_params));
let last_item_ok = if params.num_blocks_per_integer % 2 == 1 {
last_block
.as_ref()
.is_some_and(|last_block| last_block.is_conformant(¶ms.shortint_params))
} else {
true
};
paired_blocks_len_ok && paired_blocks_ok && last_item_ok
}
}