tfhe/high_level_api/booleans/
compressed.rs1use crate::backward_compatibility::booleans::{
2 CompressedFheBoolVersions, InnerCompressedFheBoolVersions,
3};
4use crate::conformance::ParameterSetConformant;
5use crate::high_level_api::global_state;
6use crate::high_level_api::keys::InternalServerKey;
7use crate::high_level_api::re_randomization::ReRandomizationMetadata;
8use crate::high_level_api::traits::Tagged;
9use crate::integer::BooleanBlock;
10use crate::named::Named;
11use crate::prelude::FheTryEncrypt;
12use crate::shortint::ciphertext::{
13 CompressedModulusSwitchedCiphertext, CompressedModulusSwitchedCiphertextConformanceParams,
14 Degree,
15};
16use crate::shortint::{AtomicPatternParameters, CompressedCiphertext};
17use crate::{ClientKey, FheBool, ServerKey, Tag};
18use serde::{Deserialize, Serialize};
19use tfhe_versionable::Versionize;
20
21#[derive(Clone, Serialize, Deserialize, Versionize)]
22#[versionize(InnerCompressedFheBoolVersions)]
23pub enum InnerCompressedFheBool {
24 Seeded(CompressedCiphertext),
25 ModulusSwitched(CompressedModulusSwitchedCiphertext),
26}
27
28#[derive(Clone, Serialize, Deserialize, Versionize)]
50#[versionize(CompressedFheBoolVersions)]
51pub struct CompressedFheBool {
52 pub(in crate::high_level_api) inner: InnerCompressedFheBool,
53 pub(crate) tag: Tag,
54}
55
56impl Tagged for CompressedFheBool {
57 fn tag(&self) -> &Tag {
58 &self.tag
59 }
60
61 fn tag_mut(&mut self) -> &mut Tag {
62 &mut self.tag
63 }
64}
65
66impl CompressedFheBool {
67 pub(in crate::high_level_api) fn new(ciphertext: CompressedCiphertext, tag: Tag) -> Self {
68 Self {
69 inner: InnerCompressedFheBool::Seeded(ciphertext),
70 tag,
71 }
72 }
73
74 pub fn decompress(&self) -> FheBool {
78 let ciphertext = BooleanBlock::new_unchecked(match &self.inner {
79 InnerCompressedFheBool::Seeded(seeded) => seeded.decompress(),
80 InnerCompressedFheBool::ModulusSwitched(modulus_switched) => {
81 global_state::with_internal_keys(|keys| match keys {
82 InternalServerKey::Cpu(cpu_key) => {
83 cpu_key.pbs_key().key.decompress(modulus_switched)
84 }
85 #[cfg(feature = "gpu")]
86 InternalServerKey::Cuda(_) => {
87 panic!("decompress() on FheBool is not supported on GPU, use a CompressedCiphertextList instead");
88 }
89 #[cfg(feature = "hpu")]
90 InternalServerKey::Hpu(_) => {
91 panic!("decompress() on FheBool is not supported on HPU devices");
92 }
93 })
94 }
95 });
96 let mut ciphertext = FheBool::new(
97 ciphertext,
98 self.tag.clone(),
99 ReRandomizationMetadata::default(),
100 );
101 ciphertext.ciphertext.move_to_device_of_server_key_if_set();
102 ciphertext
103 }
104}
105
106impl FheTryEncrypt<bool, ClientKey> for CompressedFheBool {
107 type Error = crate::Error;
108
109 fn try_encrypt(value: bool, key: &ClientKey) -> Result<Self, Self::Error> {
111 let mut ciphertext = key.key.key.key.encrypt_compressed(u64::from(value));
112 ciphertext.degree = Degree::new(1);
113 Ok(Self::new(ciphertext, key.tag.clone()))
114 }
115}
116
117#[derive(Copy, Clone)]
118pub struct CompressedFheBoolConformanceParams(
119 pub(crate) CompressedModulusSwitchedCiphertextConformanceParams,
120);
121
122impl<P: Into<AtomicPatternParameters>> From<P> for CompressedFheBoolConformanceParams {
123 fn from(params: P) -> Self {
124 let mut params = params.into().to_compressed_modswitched_conformance_param();
125 params.degree = crate::shortint::ciphertext::Degree::new(1);
126 Self(params)
127 }
128}
129
130impl From<&ServerKey> for CompressedFheBoolConformanceParams {
131 fn from(sk: &ServerKey) -> Self {
132 let mut parameter_set = Self(
133 sk.key
134 .pbs_key()
135 .key
136 .compressed_modswitched_conformance_params(),
137 );
138 parameter_set.0.degree = crate::shortint::ciphertext::Degree::new(1);
139 parameter_set
140 }
141}
142
143impl ParameterSetConformant for CompressedFheBool {
144 type ParameterSet = CompressedFheBoolConformanceParams;
145
146 fn is_conformant(&self, params: &CompressedFheBoolConformanceParams) -> bool {
147 match &self.inner {
148 InnerCompressedFheBool::Seeded(seeded) => seeded.is_conformant(¶ms.0.into()),
149 InnerCompressedFheBool::ModulusSwitched(ct) => ct.is_conformant(¶ms.0),
150 }
151 }
152}
153
154impl Named for CompressedFheBool {
155 const NAME: &'static str = "high_level_api::CompressedFheBool";
156}
157
158impl FheBool {
159 pub fn compress(&self) -> CompressedFheBool {
160 global_state::with_internal_keys(|keys| match keys {
161 InternalServerKey::Cpu(cpu_key) => {
162 let inner = InnerCompressedFheBool::ModulusSwitched(
163 cpu_key
164 .pbs_key()
165 .key
166 .switch_modulus_and_compress(&self.ciphertext.on_cpu().0),
167 );
168 CompressedFheBool {
169 inner,
170 tag: cpu_key.tag.clone(),
171 }
172 }
173 #[cfg(feature = "gpu")]
174 InternalServerKey::Cuda(_) => {
175 panic!("compress() on FheBool is not supported on GPU, use a CompressedCiphertextList instead");
176 }
177 #[cfg(feature = "hpu")]
178 InternalServerKey::Hpu(_) => {
179 panic!("compress() on FheBool is not supported on HPU devices");
180 }
181 })
182 }
183}