use poulpy_hal::{ api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare}, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat}, }; use crate::layouts::{ GGLWECiphertext, Infos, prepared::{Prepare, PrepareAlloc}, }; #[derive(PartialEq, Eq)] pub struct GGLWECiphertextPrepared { pub(crate) data: VmpPMat, pub(crate) basek: usize, pub(crate) k: usize, pub(crate) digits: usize, } impl GGLWECiphertextPrepared, B> { #[allow(clippy::too_many_arguments)] pub fn alloc( module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> Self where Module: VmpPMatAlloc, { let size: usize = k.div_ceil(basek); debug_assert!( size > digits, "invalid gglwe: ceil(k/basek): {} <= digits: {}", size, digits ); assert!( rows * digits <= size, "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", rows, digits, size ); Self { data: module.vmp_pmat_alloc(n, rows, rank_in, rank_out + 1, size), basek, k, digits, } } #[allow(clippy::too_many_arguments)] pub fn bytes_of( module: &Module, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank_in: usize, rank_out: usize, ) -> usize where Module: VmpPMatAllocBytes, { let size: usize = k.div_ceil(basek); debug_assert!( size > digits, "invalid gglwe: ceil(k/basek): {} <= digits: {}", size, digits ); assert!( rows * digits <= size, "invalid gglwe: rows: {} * digits:{} > ceil(k/basek): {}", rows, digits, size ); module.vmp_pmat_alloc_bytes(n, rows, rank_in, rank_out + 1, rows) } } impl Infos for GGLWECiphertextPrepared { type Inner = VmpPMat; fn inner(&self) -> &Self::Inner { &self.data } fn basek(&self) -> usize { self.basek } fn k(&self) -> usize { self.k } } impl GGLWECiphertextPrepared { pub fn rank(&self) -> usize { self.data.cols_out() - 1 } pub fn digits(&self) -> usize { self.digits } pub fn rank_in(&self) -> usize { self.data.cols_in() } pub fn rank_out(&self) -> usize { self.data.cols_out() - 1 } } impl Prepare> for GGLWECiphertextPrepared where Module: VmpPrepare, { fn prepare(&mut self, module: &Module, other: &GGLWECiphertext, scratch: &mut Scratch) { module.vmp_prepare(&mut self.data, &other.data, scratch); self.basek = other.basek; self.k = other.k; self.digits = other.digits; } } impl PrepareAlloc, B>> for GGLWECiphertext where Module: VmpPMatAlloc + VmpPrepare, { fn prepare_alloc(&self, module: &Module, scratch: &mut Scratch) -> GGLWECiphertextPrepared, B> { let mut atk_prepared: GGLWECiphertextPrepared, B> = GGLWECiphertextPrepared::alloc( module, self.n(), self.basek(), self.k(), self.rows(), self.digits(), self.rank_in(), self.rank_out(), ); atk_prepared.prepare(module, self, scratch); atk_prepared } }