use poulpy_core::layouts::{Base2K, GLWEInfos, GLWEToBackendMut, GLWEToBackendRef, LWEInfos, TorusPrecision};
use poulpy_hal::layouts::Backend;
pub mod api;
pub mod default;
pub(crate) mod delegates;
pub mod encoding;
mod error;
pub mod layouts;
pub mod leveled;
pub mod oep;
pub mod test_suite;
pub use error::CKKSCompositionError;
pub(crate) use error::{
checked_log_budget_sub, checked_mul_ct_log_budget, checked_mul_pt_log_budget, ensure_base2k_match,
ensure_plaintext_alignment, ensure_plaintext_coeff_in_range, ensure_plaintext_degree_match,
};
pub type CKKSCiphertextRef<'a, BE> = layouts::CKKSCiphertext<<BE as Backend>::BufRef<'a>>;
pub type CKKSCiphertextMut<'a, BE> = layouts::CKKSCiphertext<<BE as Backend>::BufMut<'a>>;
pub trait CKKSPlaintextToBackendRef<BE: Backend>: GLWEToBackendRef<BE> + GLWEInfos + LWEInfos {}
impl<BE: Backend, T> CKKSPlaintextToBackendRef<BE> for T where T: GLWEToBackendRef<BE> + GLWEInfos + LWEInfos {}
pub trait CKKSCtBounds: GLWEInfos + CKKSInfos {}
impl<T: GLWEInfos + CKKSInfos> CKKSCtBounds for T {}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct CKKSMeta {
pub log_delta: usize,
pub log_budget: usize,
}
pub trait CKKSInfos {
fn meta(&self) -> CKKSMeta;
fn log_delta(&self) -> usize;
fn log_budget(&self) -> usize;
fn min_k(&self, base2k: Base2K) -> TorusPrecision {
((self.log_delta() + self.log_budget()).next_multiple_of(base2k.as_usize())).into()
}
fn effective_k(&self) -> usize {
self.log_delta() + self.log_budget()
}
}
impl CKKSInfos for CKKSMeta {
fn meta(&self) -> CKKSMeta {
*self
}
fn log_delta(&self) -> usize {
self.log_delta
}
fn log_budget(&self) -> usize {
self.log_budget
}
}
pub trait SetCKKSInfos: CKKSInfos {
fn set_meta(&mut self, meta: CKKSMeta);
fn set_log_delta(&mut self, log_delta: usize) {
let mut meta = self.meta();
meta.log_delta = log_delta;
self.set_meta(meta);
}
fn set_log_budget(&mut self, log_budget: usize) {
let mut meta = self.meta();
meta.log_budget = log_budget;
self.set_meta(meta);
}
}
pub(crate) fn ckks_offset_binary<R, A, B>(res: &R, a: &A, b: &B) -> usize
where
R: LWEInfos + CKKSInfos + ?Sized,
A: LWEInfos + CKKSInfos + ?Sized,
B: LWEInfos + CKKSInfos + ?Sized,
{
a.effective_k().min(b.effective_k()).saturating_sub(res.max_k().as_usize())
}
pub(crate) fn ckks_offset_unary<R, A>(res: &R, a: &A) -> usize
where
R: LWEInfos + CKKSInfos + ?Sized,
A: LWEInfos + CKKSInfos + ?Sized,
{
a.effective_k().saturating_sub(res.max_k().as_usize())
}