use poulpy_hal::{ api::{VmpPMatAlloc, VmpPMatAllocBytes}, layouts::{Backend, Data, DataMut, DataRef, Module, Scratch}, }; use crate::layouts::{ Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, GLWESwitchingKey, GLWESwitchingKeyToRef, LWEInfos, Rank, TorusPrecision, prepared::{GGLWEPrepare, GGLWEPrepareTmpBytes, GGLWEPrepared, GGLWEPreparedToMut, GGLWEPreparedToRef}, }; #[derive(PartialEq, Eq)] pub struct GLWESwitchingKeyPrepared { pub(crate) key: GGLWEPrepared, pub(crate) sk_in_n: usize, // Degree of sk_in pub(crate) sk_out_n: usize, // Degree of sk_out } pub(crate) trait GLWESwitchingKeyPreparedSetMetaData { fn set_sk_in_n(&mut self, sk_in_n: usize); fn set_sk_out_n(&mut self, sk_out_n: usize); } impl GLWESwitchingKeyPreparedSetMetaData for GLWESwitchingKeyPrepared { fn set_sk_in_n(&mut self, sk_in_n: usize) { self.sk_in_n = sk_in_n } fn set_sk_out_n(&mut self, sk_out_n: usize) { self.sk_out_n = self.sk_out_n } } impl LWEInfos for GLWESwitchingKeyPrepared { fn n(&self) -> Degree { self.key.n() } fn base2k(&self) -> Base2K { self.key.base2k() } fn k(&self) -> TorusPrecision { self.key.k() } fn size(&self) -> usize { self.key.size() } } impl GLWEInfos for GLWESwitchingKeyPrepared { fn rank(&self) -> Rank { self.rank_out() } } impl GGLWEInfos for GLWESwitchingKeyPrepared { fn rank_in(&self) -> Rank { self.key.rank_in() } fn rank_out(&self) -> Rank { self.key.rank_out() } fn dsize(&self) -> Dsize { self.key.dsize() } fn dnum(&self) -> Dnum { self.key.dnum() } } impl GLWESwitchingKeyPrepared, B> { pub fn alloc(module: &Module, infos: &A) -> Self where A: GGLWEInfos, Module: VmpPMatAlloc, { debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()"); GLWESwitchingKeyPrepared::, B> { key: GGLWEPrepared::alloc(module, infos), sk_in_n: 0, sk_out_n: 0, } } pub fn alloc_with( module: &Module, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, ) -> Self where Module: VmpPMatAlloc, { GLWESwitchingKeyPrepared::, B> { key: GGLWEPrepared::alloc_with(module, base2k, k, rank_in, rank_out, dnum, dsize), sk_in_n: 0, sk_out_n: 0, } } pub fn alloc_bytes(module: &Module, infos: &A) -> usize where A: GGLWEInfos, Module: VmpPMatAllocBytes, { debug_assert_eq!(module.n() as u32, infos.n(), "module.n() != infos.n()"); GGLWEPrepared::alloc_bytes(module, infos) } pub fn alloc_bytes_with( module: &Module, base2k: Base2K, k: TorusPrecision, rank_in: Rank, rank_out: Rank, dnum: Dnum, dsize: Dsize, ) -> usize where Module: VmpPMatAllocBytes, { GGLWEPrepared::alloc_bytes_with(module, base2k, k, rank_in, rank_out, dnum, dsize) } } pub trait GLWESwitchingKeyPrepareTmpBytes { fn glwe_switching_key_prepare_tmp_bytes(&self, infos: &A) -> usize where A: GGLWEInfos; } impl GLWESwitchingKeyPrepareTmpBytes for Module where Module: GGLWEPrepareTmpBytes, { fn glwe_switching_key_prepare_tmp_bytes(&self, infos: &A) -> usize where A: GGLWEInfos, { self.gglwe_prepare_tmp_bytes(infos) } } impl GLWESwitchingKeyPrepared, B> where Module: GGLWEPrepareTmpBytes, { pub fn prepare_tmp_bytes(&self, module: &Module) -> usize { module.gglwe_prepare_tmp_bytes(self) } } pub trait GLWESwitchingKeyPrepare { fn glwe_switching_prepare(&self, res: &R, other: &O, scratch: &mut Scratch) where R: GLWESwitchingKeyPreparedToMut + GLWESwitchingKeyPreparedSetMetaData, O: GLWESwitchingKeyToRef; } impl GLWESwitchingKeyPrepare for Module where Module: GGLWEPrepare, { fn glwe_switching_prepare(&self, res: &R, other: &O, scratch: &mut Scratch) where R: GLWESwitchingKeyPreparedToMut + GLWESwitchingKeyPreparedSetMetaData, O: GLWESwitchingKeyToRef, { self.gglwe_prepare(&res.to_mut(), other, scratch); res.set_sk_in_n(other.sk_in_n); res.set_sk_out_n(other.sk_out_n); } } impl GLWESwitchingKeyPrepared { pub fn prepare(&mut self, module: &Module, other: &O, scratch: &mut Scratch) where O: GLWESwitchingKeyToRef, Module: GLWESwitchingKeyPrepare, { module.glwe_switching_prepare(self, other, scratch); } } pub trait GLWESwitchingKeyPrepareAlloc { fn glwe_switching_key_prepare_alloc(&self, other: &O, scratch: &mut Scratch) where O: GLWESwitchingKeyToRef; } impl GLWESwitchingKeyPrepareAlloc for Module where Module: GLWESwitchingKeyPrepare, { fn glwe_switching_key_prepare_alloc(&self, other: &O, scratch: &mut Scratch) where O: GLWESwitchingKeyToRef, { let mut ct_prepared: GLWESwitchingKeyPrepared, B> = GLWESwitchingKeyPrepared::alloc(self, self); self.glwe_switching_prepare(&mut ct_prepared, other, scratch); ct_prepared } } impl GLWESwitchingKey { pub fn prepare_alloc(&self, module: &Module, scratch: &mut Scratch) -> GLWESwitchingKeyPrepared, B> where Module: GLWESwitchingKeyPrepareAlloc, { module.glwe_switching_key_prepare_alloc(self, scratch); } } pub trait GLWESwitchingKeyPreparedToMut { fn to_mut(&mut self) -> GLWESwitchingKeyPrepared<&mut [u8], B>; } impl GLWESwitchingKeyPreparedToMut for GLWESwitchingKeyPrepared { fn to_mut(&mut self) -> GLWESwitchingKeyPrepared<&mut [u8], B> { GLWESwitchingKeyPrepared { sk_in_n: self.sk_in_n, sk_out_n: self.sk_out_n, key: self.key.to_mut(), } } } pub trait GLWESwitchingKeyPreparedToRef { fn to_ref(&self) -> GLWESwitchingKeyPrepared<&[u8], B>; } impl GLWESwitchingKeyPreparedToRef for GLWESwitchingKeyPrepared { fn to_ref(&self) -> GLWESwitchingKeyPrepared<&[u8], B> { GLWESwitchingKeyPrepared { sk_in_n: self.sk_in_n, sk_out_n: self.sk_out_n, key: self.key.to_ref(), } } }