arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/layouts/prepared/gglwe_tsk.rs
poulpy-core/src/layouts/prepared/gglwe_tsk.rsRaw
  1use poulpy_hal::{
  2    api::{VmpPMatAlloc, VmpPMatAllocBytes, VmpPrepare},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
  4};
  5
  6use crate::layouts::{
  7    Base2K, Degree, Dnum, Dsize, GGLWEInfos, GGLWETensorKey, GLWEInfos, LWEInfos, Rank, TorusPrecision,
  8    prepared::{GGLWESwitchingKeyPrepared, Prepare, PrepareAlloc, PrepareScratchSpace},
  9};
 10
 11#[derive(PartialEq, Eq)]
 12pub struct GGLWETensorKeyPrepared<D: Data, B: Backend> {
 13    pub(crate) keys: Vec<GGLWESwitchingKeyPrepared<D, B>>,
 14}
 15
 16impl<D: Data, B: Backend> LWEInfos for GGLWETensorKeyPrepared<D, B> {
 17    fn n(&self) -> Degree {
 18        self.keys[0].n()
 19    }
 20
 21    fn base2k(&self) -> Base2K {
 22        self.keys[0].base2k()
 23    }
 24
 25    fn k(&self) -> TorusPrecision {
 26        self.keys[0].k()
 27    }
 28
 29    fn size(&self) -> usize {
 30        self.keys[0].size()
 31    }
 32}
 33
 34impl<D: Data, B: Backend> GLWEInfos for GGLWETensorKeyPrepared<D, B> {
 35    fn rank(&self) -> Rank {
 36        self.rank_out()
 37    }
 38}
 39
 40impl<D: Data, B: Backend> GGLWEInfos for GGLWETensorKeyPrepared<D, B> {
 41    fn rank_in(&self) -> Rank {
 42        self.rank_out()
 43    }
 44
 45    fn rank_out(&self) -> Rank {
 46        self.keys[0].rank_out()
 47    }
 48
 49    fn dsize(&self) -> Dsize {
 50        self.keys[0].dsize()
 51    }
 52
 53    fn dnum(&self) -> Dnum {
 54        self.keys[0].dnum()
 55    }
 56}
 57
 58impl<B: Backend> GGLWETensorKeyPrepared<Vec<u8>, B> {
 59    pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
 60    where
 61        A: GGLWEInfos,
 62        Module<B>: VmpPMatAlloc<B>,
 63    {
 64        assert_eq!(
 65            infos.rank_in(),
 66            infos.rank_out(),
 67            "rank_in != rank_out is not supported for GGLWETensorKeyPrepared"
 68        );
 69        Self::alloc_with(
 70            module,
 71            infos.base2k(),
 72            infos.k(),
 73            infos.dnum(),
 74            infos.dsize(),
 75            infos.rank_out(),
 76        )
 77    }
 78
 79    pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
 80    where
 81        Module<B>: VmpPMatAlloc<B>,
 82    {
 83        let mut keys: Vec<GGLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new();
 84        let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
 85        (0..pairs).for_each(|_| {
 86            keys.push(GGLWESwitchingKeyPrepared::alloc_with(
 87                module,
 88                base2k,
 89                k,
 90                Rank(1),
 91                rank,
 92                dnum,
 93                dsize,
 94            ));
 95        });
 96        Self { keys }
 97    }
 98
 99    pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
100    where
101        A: GGLWEInfos,
102        Module<B>: VmpPMatAllocBytes,
103    {
104        assert_eq!(
105            infos.rank_in(),
106            infos.rank_out(),
107            "rank_in != rank_out is not supported for GGLWETensorKey"
108        );
109        let rank_out: usize = infos.rank_out().into();
110        let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
111        pairs
112            * GGLWESwitchingKeyPrepared::alloc_bytes_with(
113                module,
114                infos.base2k(),
115                infos.k(),
116                Rank(1),
117                infos.rank_out(),
118                infos.dnum(),
119                infos.dsize(),
120            )
121    }
122
123    pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
124    where
125        Module<B>: VmpPMatAllocBytes,
126    {
127        let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
128        pairs * GGLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank, dnum, dsize)
129    }
130}
131
132impl<D: DataMut, B: Backend> GGLWETensorKeyPrepared<D, B> {
133    // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
134    pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GGLWESwitchingKeyPrepared<D, B> {
135        if i > j {
136            std::mem::swap(&mut i, &mut j);
137        };
138        let rank: usize = self.rank_out().into();
139        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
140    }
141}
142
143impl<D: DataRef, B: Backend> GGLWETensorKeyPrepared<D, B> {
144    // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
145    pub fn at(&self, mut i: usize, mut j: usize) -> &GGLWESwitchingKeyPrepared<D, B> {
146        if i > j {
147            std::mem::swap(&mut i, &mut j);
148        };
149        let rank: usize = self.rank_out().into();
150        &self.keys[i * rank + j - (i * (i + 1) / 2)]
151    }
152}
153
154impl<B: Backend, A: GGLWEInfos> PrepareScratchSpace<B, A> for GGLWETensorKeyPrepared<Vec<u8>, B>
155where
156    GGLWESwitchingKeyPrepared<Vec<u8>, B>: PrepareScratchSpace<B, A>,
157{
158    fn prepare_scratch_space(module: &Module<B>, infos: &A) -> usize {
159        GGLWESwitchingKeyPrepared::prepare_scratch_space(module, infos)
160    }
161}
162
163impl<D: DataMut, DR: DataRef, B: Backend> Prepare<B, GGLWETensorKey<DR>> for GGLWETensorKeyPrepared<D, B>
164where
165    Module<B>: VmpPrepare<B>,
166{
167    fn prepare(&mut self, module: &Module<B>, other: &GGLWETensorKey<DR>, scratch: &mut Scratch<B>) {
168        #[cfg(debug_assertions)]
169        {
170            assert_eq!(self.keys.len(), other.keys.len());
171        }
172        self.keys
173            .iter_mut()
174            .zip(other.keys.iter())
175            .for_each(|(a, b)| {
176                a.prepare(module, b, scratch);
177            });
178    }
179}
180
181impl<D: DataRef, B: Backend> PrepareAlloc<B, GGLWETensorKeyPrepared<Vec<u8>, B>> for GGLWETensorKey<D>
182where
183    Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
184{
185    fn prepare_alloc(&self, module: &Module<B>, scratch: &mut Scratch<B>) -> GGLWETensorKeyPrepared<Vec<u8>, B> {
186        let mut tsk_prepared: GGLWETensorKeyPrepared<Vec<u8>, B> = GGLWETensorKeyPrepared::alloc(module, self);
187        tsk_prepared.prepare(module, self, scratch);
188        tsk_prepared
189    }
190}