use backend::{Backend, FFT64, MatZnxDft, Module}; use crate::{GLWESwitchingKey, Infos}; pub struct GLWETensorKey { pub(crate) keys: Vec>, } impl GLWETensorKey, FFT64> { pub fn alloc(module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self { let mut keys: Vec, FFT64>> = Vec::new(); let pairs: usize = (((rank + 1) * rank) >> 1).max(1); (0..pairs).for_each(|_| { keys.push(GLWESwitchingKey::alloc( module, basek, k, rows, digits, 1, rank, )); }); Self { keys: keys } } pub fn bytes_of(module: &Module, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize { let pairs: usize = (((rank + 1) * rank) >> 1).max(1); pairs * GLWESwitchingKey::, FFT64>::bytes_of(module, basek, k, rows, digits, 1, rank) } } impl Infos for GLWETensorKey { type Inner = MatZnxDft; fn inner(&self) -> &Self::Inner { &self.keys[0].inner() } fn basek(&self) -> usize { self.keys[0].basek() } fn k(&self) -> usize { self.keys[0].k() } } impl GLWETensorKey { pub fn rank(&self) -> usize { self.keys[0].rank() } pub fn rank_in(&self) -> usize { self.keys[0].rank_in() } pub fn rank_out(&self) -> usize { self.keys[0].rank_out() } pub fn digits(&self) -> usize { self.keys[0].digits() } } impl + AsRef<[u8]>> GLWETensorKey { // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j]) pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKey { if i > j { std::mem::swap(&mut i, &mut j); }; let rank: usize = self.rank(); &mut self.keys[i * rank + j - (i * (i + 1) / 2)] } } impl> GLWETensorKey { // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j]) pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKey { if i > j { std::mem::swap(&mut i, &mut j); }; let rank: usize = self.rank(); &self.keys[i * rank + j - (i * (i + 1) / 2)] } }