use super::{IntegerCiphertext, IntegerRadixCiphertext};
use crate::integer::backward_compatibility::ciphertext::BooleanBlockVersions;
use crate::integer::ciphertext::{
re_randomize_ciphertext_blocks, ReRandomizationKey, ReRandomizationSeed,
};
use crate::integer::{RadixCiphertext, ServerKey};
use crate::shortint::ciphertext::NotTrivialCiphertextError;
use crate::shortint::Ciphertext;
use serde::{Deserialize, Serialize};
use tfhe_versionable::Versionize;
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq, Versionize)]
#[versionize(BooleanBlockVersions)]
pub struct BooleanBlock(pub(crate) Ciphertext);
impl BooleanBlock {
pub fn new_unchecked(block: Ciphertext) -> Self {
Self(block)
}
pub fn try_new<T>(ct: &T) -> Option<Self>
where
T: IntegerRadixCiphertext,
{
if ct.holds_boolean_value() {
Some(Self(ct.blocks()[0].clone()))
} else {
None
}
}
pub fn convert<T>(ct: &T, sks: &ServerKey) -> Self
where
T: IntegerRadixCiphertext,
{
if ct.holds_boolean_value() {
let block = ct.blocks()[0].clone();
Self(block)
} else {
sks.scalar_ne_parallelized(ct, 0)
}
}
pub fn into_raw_parts(self) -> Ciphertext {
self.0
}
pub fn into_radix<T>(self, num_blocks: usize, sks: &ServerKey) -> T
where
T: IntegerRadixCiphertext,
{
let mut radix_ct = RadixCiphertext::from_blocks(vec![self.0]);
let missing_blocks = num_blocks.saturating_sub(1);
sks.extend_radix_with_trivial_zero_blocks_msb_assign(&mut radix_ct, missing_blocks);
T::from_blocks(radix_ct.blocks)
}
pub fn decrypt_trivial(&self) -> Result<bool, NotTrivialCiphertextError> {
let value = self.0.decrypt_trivial()?;
Ok(value != 0)
}
pub fn is_trivial(&self) -> bool {
self.0.is_trivial()
}
pub fn re_randomize(
&mut self,
re_randomization_key: ReRandomizationKey<'_>,
seed: ReRandomizationSeed,
) -> crate::Result<()> {
re_randomize_ciphertext_blocks(
core::slice::from_mut(&mut self.0),
re_randomization_key,
seed,
)?;
Ok(())
}
}
impl AsRef<Ciphertext> for BooleanBlock {
fn as_ref(&self) -> &Ciphertext {
&self.0
}
}