use crate::shortint::ciphertext::{Degree, NoiseLevel};
use crate::shortint::parameters::AtomicPatternKind;
use crate::shortint::{CarryModulus, MessageModulus};
use itertools::Itertools;
#[derive(Clone, Copy)]
pub struct CudaBlockInfo {
pub degree: Degree,
pub message_modulus: MessageModulus,
pub carry_modulus: CarryModulus,
pub atomic_pattern: AtomicPatternKind,
pub noise_level: NoiseLevel,
}
impl CudaBlockInfo {
pub fn carry_is_empty(&self) -> bool {
self.degree.get() < self.message_modulus.0
}
pub fn duplicate(&self) -> Self {
Self {
degree: self.degree,
message_modulus: self.message_modulus,
carry_modulus: self.carry_modulus,
atomic_pattern: self.atomic_pattern,
noise_level: self.noise_level,
}
}
}
#[derive(Clone)]
pub struct CudaRadixCiphertextInfo {
pub blocks: Vec<CudaBlockInfo>,
}
impl CudaRadixCiphertextInfo {
pub(crate) fn boolean_info(&self, noise_level: NoiseLevel) -> Self {
Self {
blocks: self
.blocks
.iter()
.map(|left| CudaBlockInfo {
degree: Degree::new(1),
message_modulus: left.message_modulus,
carry_modulus: left.carry_modulus,
atomic_pattern: left.atomic_pattern,
noise_level,
})
.collect(),
}
}
pub(crate) fn after_extend_radix_with_trivial_zero_blocks_lsb(
&self,
num_blocks: usize,
) -> Self {
let mut new_block_info = Self {
blocks: Vec::with_capacity(self.blocks.len() + num_blocks),
};
for _ in 0..num_blocks {
new_block_info.blocks.push(CudaBlockInfo {
degree: Degree::new(0),
message_modulus: self.blocks.first().unwrap().message_modulus,
carry_modulus: self.blocks.first().unwrap().carry_modulus,
atomic_pattern: self.blocks.first().unwrap().atomic_pattern,
noise_level: NoiseLevel::ZERO,
});
}
for &b in self.blocks.iter() {
new_block_info.blocks.push(b);
}
new_block_info
}
pub fn duplicate(&self) -> Self {
Self {
blocks: self
.blocks
.iter()
.map(|block| block.duplicate())
.collect_vec(),
}
}
}