arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/layouts/prepared/gglwe_tsk.rs
core/src/layouts/prepared/gglwe_tsk.rsRaw
  1use backend::hal::{
  2    api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPMatPrepare},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch, VmpPMat},
  4};
  5
  6use crate::layouts::{GGLWETensorKey, Infos, prepared::GGLWESwitchingKeyExec};
  7
  8#[derive(PartialEq, Eq)]
  9pub struct GGLWETensorKeyExec<D: Data, B: Backend> {
 10    pub(crate) keys: Vec<GGLWESwitchingKeyExec<D, B>>,
 11}
 12
 13impl<B: Backend> GGLWETensorKeyExec<Vec<u8>, B> {
 14    pub fn alloc(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> Self
 15    where
 16        Module<B>: VmpPMatAlloc<B>,
 17    {
 18        let mut keys: Vec<GGLWESwitchingKeyExec<Vec<u8>, B>> = Vec::new();
 19        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
 20        (0..pairs).for_each(|_| {
 21            keys.push(GGLWESwitchingKeyExec::alloc(
 22                module, n, basek, k, rows, digits, 1, rank,
 23            ));
 24        });
 25        Self { keys }
 26    }
 27
 28    pub fn bytes_of(module: &Module<B>, n: usize, basek: usize, k: usize, rows: usize, digits: usize, rank: usize) -> usize
 29    where
 30        Module<B>: VmpPMatAllocBytes,
 31    {
 32        let pairs: usize = (((rank + 1) * rank) >> 1).max(1);
 33        pairs * GGLWESwitchingKeyExec::bytes_of(module, n, basek, k, rows, digits, 1, rank)
 34    }
 35
 36    pub fn from<D: DataRef>(
 37        module: &Module<B>,
 38        other: &GGLWETensorKey<D>,
 39        scratch: &mut Scratch<B>,
 40    ) -> GGLWETensorKeyExec<Vec<u8>, B>
 41    where
 42        Module<B>: VmpPMatAlloc<B> + VmpPMatPrepare<B>,
 43    {
 44        let mut tsk_exec: GGLWETensorKeyExec<Vec<u8>, B> = Self::alloc(
 45            module,
 46            other.n(),
 47            other.basek(),
 48            other.k(),
 49            other.rows(),
 50            other.digits(),
 51            other.rank(),
 52        );
 53        tsk_exec.prepare(module, other, scratch);
 54        tsk_exec
 55    }
 56}
 57
 58impl<D: Data, B: Backend> Infos for GGLWETensorKeyExec<D, B> {
 59    type Inner = VmpPMat<D, B>;
 60
 61    fn inner(&self) -> &Self::Inner {
 62        &self.keys[0].inner()
 63    }
 64
 65    fn basek(&self) -> usize {
 66        self.keys[0].basek()
 67    }
 68
 69    fn k(&self) -> usize {
 70        self.keys[0].k()
 71    }
 72}
 73
 74impl<D: Data, B: Backend> GGLWETensorKeyExec<D, B> {
 75    pub fn rank(&self) -> usize {
 76        self.keys[0].rank()
 77    }
 78
 79    pub fn rank_in(&self) -> usize {
 80        self.keys[0].rank_in()
 81    }
 82
 83    pub fn rank_out(&self) -> usize {
 84        self.keys[0].rank_out()
 85    }
 86
 87    pub fn digits(&self) -> usize {
 88        self.keys[0].digits()
 89    }
 90}
 91
 92impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> {
 93    // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
 94    pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyExec<D, B> {
 95        if i > j {
 96            std::mem::swap(&mut i, &mut j);
 97        };
 98        let rank: usize = self.rank();
 99        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
100    }
101}
102
103impl<D: DataRef, B: Backend> GGLWETensorKeyExec<D, B> {
104    // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
105    pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyExec<D, B> {
106        if i > j {
107            std::mem::swap(&mut i, &mut j);
108        };
109        let rank: usize = self.rank();
110        &self.keys[i * rank + j - (i * (i + 1) / 2)]
111    }
112}
113
114impl<D: DataMut, B: Backend> GGLWETensorKeyExec<D, B> {
115    pub fn prepare<DataOther>(&mut self, module: &Module<B>, other: &GGLWETensorKey<DataOther>, scratch: &mut Scratch<B>)
116    where
117        DataOther: DataRef,
118        Module<B>: VmpPMatPrepare<B>,
119    {
120        #[cfg(debug_assertions)]
121        {
122            assert_eq!(self.keys.len(), other.keys.len());
123        }
124        self.keys
125            .iter_mut()
126            .zip(other.keys.iter())
127            .for_each(|(a, b)| {
128                a.prepare(module, b, scratch);
129            });
130    }
131}