use crate::backward_compatibility::booleans::{
CompressedFheBoolVersions, InnerCompressedFheBoolVersions,
};
use crate::conformance::ParameterSetConformant;
use crate::high_level_api::global_state;
use crate::high_level_api::keys::InternalServerKey;
use crate::high_level_api::re_randomization::ReRandomizationMetadata;
use crate::high_level_api::traits::Tagged;
use crate::integer::BooleanBlock;
use crate::named::Named;
use crate::prelude::FheTryEncrypt;
use crate::shortint::ciphertext::{
CompressedModulusSwitchedCiphertext, CompressedModulusSwitchedCiphertextConformanceParams,
Degree,
};
use crate::shortint::{AtomicPatternParameters, CompressedCiphertext};
use crate::{ClientKey, FheBool, ServerKey, Tag};
use serde::{Deserialize, Serialize};
use tfhe_versionable::Versionize;
#[derive(Clone, Serialize, Deserialize, Versionize)]
#[versionize(InnerCompressedFheBoolVersions)]
pub enum InnerCompressedFheBool {
Seeded(CompressedCiphertext),
ModulusSwitched(CompressedModulusSwitchedCiphertext),
}
#[derive(Clone, Serialize, Deserialize, Versionize)]
#[versionize(CompressedFheBoolVersions)]
pub struct CompressedFheBool {
pub(in crate::high_level_api) inner: InnerCompressedFheBool,
pub(crate) tag: Tag,
}
impl Tagged for CompressedFheBool {
fn tag(&self) -> &Tag {
&self.tag
}
fn tag_mut(&mut self) -> &mut Tag {
&mut self.tag
}
}
impl CompressedFheBool {
pub(in crate::high_level_api) fn new(ciphertext: CompressedCiphertext, tag: Tag) -> Self {
Self {
inner: InnerCompressedFheBool::Seeded(ciphertext),
tag,
}
}
pub fn decompress(&self) -> FheBool {
let ciphertext = BooleanBlock::new_unchecked(match &self.inner {
InnerCompressedFheBool::Seeded(seeded) => seeded.decompress(),
InnerCompressedFheBool::ModulusSwitched(modulus_switched) => {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
cpu_key.pbs_key().key.decompress(modulus_switched)
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("decompress() on FheBool is not supported on GPU, use a CompressedCiphertextList instead");
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_) => {
panic!("decompress() on FheBool is not supported on HPU devices");
}
})
}
});
let mut ciphertext = FheBool::new(
ciphertext,
self.tag.clone(),
ReRandomizationMetadata::default(),
);
ciphertext.ciphertext.move_to_device_of_server_key_if_set();
ciphertext
}
}
impl FheTryEncrypt<bool, ClientKey> for CompressedFheBool {
type Error = crate::Error;
fn try_encrypt(value: bool, key: &ClientKey) -> Result<Self, Self::Error> {
let mut ciphertext = key.key.key.key.encrypt_compressed(u64::from(value));
ciphertext.degree = Degree::new(1);
Ok(Self::new(ciphertext, key.tag.clone()))
}
}
#[derive(Copy, Clone)]
pub struct CompressedFheBoolConformanceParams(
pub(crate) CompressedModulusSwitchedCiphertextConformanceParams,
);
impl<P: Into<AtomicPatternParameters>> From<P> for CompressedFheBoolConformanceParams {
fn from(params: P) -> Self {
let mut params = params.into().to_compressed_modswitched_conformance_param();
params.degree = crate::shortint::ciphertext::Degree::new(1);
Self(params)
}
}
impl From<&ServerKey> for CompressedFheBoolConformanceParams {
fn from(sk: &ServerKey) -> Self {
let mut parameter_set = Self(
sk.key
.pbs_key()
.key
.compressed_modswitched_conformance_params(),
);
parameter_set.0.degree = crate::shortint::ciphertext::Degree::new(1);
parameter_set
}
}
impl ParameterSetConformant for CompressedFheBool {
type ParameterSet = CompressedFheBoolConformanceParams;
fn is_conformant(&self, params: &CompressedFheBoolConformanceParams) -> bool {
match &self.inner {
InnerCompressedFheBool::Seeded(seeded) => seeded.is_conformant(¶ms.0.into()),
InnerCompressedFheBool::ModulusSwitched(ct) => ct.is_conformant(¶ms.0),
}
}
}
impl Named for CompressedFheBool {
const NAME: &'static str = "high_level_api::CompressedFheBool";
}
impl FheBool {
pub fn compress(&self) -> CompressedFheBool {
global_state::with_internal_keys(|keys| match keys {
InternalServerKey::Cpu(cpu_key) => {
let inner = InnerCompressedFheBool::ModulusSwitched(
cpu_key
.pbs_key()
.key
.switch_modulus_and_compress(&self.ciphertext.on_cpu().0),
);
CompressedFheBool {
inner,
tag: cpu_key.tag.clone(),
}
}
#[cfg(feature = "gpu")]
InternalServerKey::Cuda(_) => {
panic!("compress() on FheBool is not supported on GPU, use a CompressedCiphertextList instead");
}
#[cfg(feature = "hpu")]
InternalServerKey::Hpu(_) => {
panic!("compress() on FheBool is not supported on HPU devices");
}
})
}
}