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},
  3    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
  4};
  5
  6use crate::layouts::{
  7    Base2K, Degree, Dnum, Dsize, GGLWEInfos, GLWEInfos, LWEInfos, Rank, TensorKey, TensorKeyToRef, TorusPrecision,
  8    compressed::TensorKeyCompressedToMut,
  9    prepared::{
 10        GLWESwitchingKeyPrepare, GLWESwitchingKeyPrepareTmpBytes, GLWESwitchingKeyPrepared, GLWESwitchingKeyPreparedToMut,
 11        GLWESwitchingKeyPreparedToRef,
 12    },
 13};
 14
 15#[derive(PartialEq, Eq)]
 16pub struct TensorKeyPrepared<D: Data, B: Backend> {
 17    pub(crate) keys: Vec<GLWESwitchingKeyPrepared<D, B>>,
 18}
 19
 20impl<D: Data, B: Backend> LWEInfos for TensorKeyPrepared<D, B> {
 21    fn n(&self) -> Degree {
 22        self.keys[0].n()
 23    }
 24
 25    fn base2k(&self) -> Base2K {
 26        self.keys[0].base2k()
 27    }
 28
 29    fn k(&self) -> TorusPrecision {
 30        self.keys[0].k()
 31    }
 32
 33    fn size(&self) -> usize {
 34        self.keys[0].size()
 35    }
 36}
 37
 38impl<D: Data, B: Backend> GLWEInfos for TensorKeyPrepared<D, B> {
 39    fn rank(&self) -> Rank {
 40        self.rank_out()
 41    }
 42}
 43
 44impl<D: Data, B: Backend> GGLWEInfos for TensorKeyPrepared<D, B> {
 45    fn rank_in(&self) -> Rank {
 46        self.rank_out()
 47    }
 48
 49    fn rank_out(&self) -> Rank {
 50        self.keys[0].rank_out()
 51    }
 52
 53    fn dsize(&self) -> Dsize {
 54        self.keys[0].dsize()
 55    }
 56
 57    fn dnum(&self) -> Dnum {
 58        self.keys[0].dnum()
 59    }
 60}
 61
 62impl<B: Backend> TensorKeyPrepared<Vec<u8>, B> {
 63    pub fn alloc<A>(module: &Module<B>, infos: &A) -> Self
 64    where
 65        A: GGLWEInfos,
 66        Module<B>: VmpPMatAlloc<B>,
 67    {
 68        assert_eq!(
 69            infos.rank_in(),
 70            infos.rank_out(),
 71            "rank_in != rank_out is not supported for GGLWETensorKeyPrepared"
 72        );
 73        Self::alloc_with(
 74            module,
 75            infos.base2k(),
 76            infos.k(),
 77            infos.dnum(),
 78            infos.dsize(),
 79            infos.rank_out(),
 80        )
 81    }
 82
 83    pub fn alloc_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, dnum: Dnum, dsize: Dsize, rank: Rank) -> Self
 84    where
 85        Module<B>: VmpPMatAlloc<B>,
 86    {
 87        let mut keys: Vec<GLWESwitchingKeyPrepared<Vec<u8>, B>> = Vec::new();
 88        let pairs: u32 = (((rank.0 + 1) * rank.0) >> 1).max(1);
 89        (0..pairs).for_each(|_| {
 90            keys.push(GLWESwitchingKeyPrepared::alloc_with(
 91                module,
 92                base2k,
 93                k,
 94                Rank(1),
 95                rank,
 96                dnum,
 97                dsize,
 98            ));
 99        });
100        Self { keys }
101    }
102
103    pub fn alloc_bytes<A>(module: &Module<B>, infos: &A) -> usize
104    where
105        A: GGLWEInfos,
106        Module<B>: VmpPMatAllocBytes,
107    {
108        assert_eq!(
109            infos.rank_in(),
110            infos.rank_out(),
111            "rank_in != rank_out is not supported for GGLWETensorKey"
112        );
113        let rank_out: usize = infos.rank_out().into();
114        let pairs: usize = (((rank_out + 1) * rank_out) >> 1).max(1);
115        pairs
116            * GLWESwitchingKeyPrepared::alloc_bytes_with(
117                module,
118                infos.base2k(),
119                infos.k(),
120                Rank(1),
121                infos.rank_out(),
122                infos.dnum(),
123                infos.dsize(),
124            )
125    }
126
127    pub fn alloc_bytes_with(module: &Module<B>, base2k: Base2K, k: TorusPrecision, rank: Rank, dnum: Dnum, dsize: Dsize) -> usize
128    where
129        Module<B>: VmpPMatAllocBytes,
130    {
131        let pairs: usize = (((rank.0 + 1) * rank.0) >> 1).max(1) as usize;
132        pairs * GLWESwitchingKeyPrepared::alloc_bytes_with(module, base2k, k, Rank(1), rank, dnum, dsize)
133    }
134}
135
136impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B> {
137    // Returns a mutable reference to GLWESwitchingKey_{s}(s[i] * s[j])
138    pub fn at_mut(&mut self, mut i: usize, mut j: usize) -> &mut GLWESwitchingKeyPrepared<D, B> {
139        if i > j {
140            std::mem::swap(&mut i, &mut j);
141        };
142        let rank: usize = self.rank_out().into();
143        &mut self.keys[i * rank + j - (i * (i + 1) / 2)]
144    }
145}
146
147impl<D: DataRef, B: Backend> TensorKeyPrepared<D, B> {
148    // Returns a reference to GLWESwitchingKey_{s}(s[i] * s[j])
149    pub fn at(&self, mut i: usize, mut j: usize) -> &GLWESwitchingKeyPrepared<D, B> {
150        if i > j {
151            std::mem::swap(&mut i, &mut j);
152        };
153        let rank: usize = self.rank_out().into();
154        &self.keys[i * rank + j - (i * (i + 1) / 2)]
155    }
156}
157
158pub trait TensorKeyPrepareTmpBytes {
159    fn tensor_key_prepare_tmp_bytes<A>(&self, infos: &A) -> usize;
160}
161
162impl<B: Backend> TensorKeyPrepareTmpBytes for Module<B>
163where
164    Module<B>: GLWESwitchingKeyPrepareTmpBytes,
165{
166    fn tensor_key_prepare_tmp_bytes<A>(&self, infos: &A) -> usize {
167        self.glwe_switching_key_prepare_tmp_bytes(infos)
168    }
169}
170
171impl<B: Backend> TensorKeyPrepared<Vec<u8>, B>
172where
173    Module<B>: TensorKeyPrepareTmpBytes,
174{
175    fn prepare_tmp_bytes<A>(&self, module: &Module<B>, infos: &A) -> usize
176    where
177        A: GGLWEInfos,
178    {
179        module.tensor_key_prepare_tmp_bytes(infos)
180    }
181}
182
183pub trait TensorKeyPrepare<B: Backend> {
184    fn tensor_key_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &Scratch<B>)
185    where
186        R: TensorKeyPreparedToMut<B>,
187        O: TensorKeyToRef;
188}
189
190impl<B: Backend> TensorKeyPrepare<B> for Module<B>
191where
192    Module<B>: GLWESwitchingKeyPrepare<B>,
193{
194    fn tensor_key_prepare<R, O>(&self, res: &mut R, other: &O, scratch: &Scratch<B>)
195    where
196        R: TensorKeyPreparedToMut<B>,
197        O: TensorKeyToRef,
198    {
199        let res = res.to_mut();
200        let other = other.to_ref();
201
202        assert_eq!(self.keys.len(), other.keys.len());
203
204        for (a, b) in res.keys.iter_mut().zip(other.keys.iter()) {
205            self.glwe_switching_prepare(a, b, scratch);
206        }
207    }
208}
209
210impl<D: DataMut, B: Backend> TensorKeyPrepared<D, B>
211where
212    Module<B>: TensorKeyPrepare<B>,
213{
214    fn prepare<O>(&mut self, module: &Module<B>, other: &O, scratch: &mut Scratch<B>)
215    where
216        O: TensorKeyToRef,
217    {
218        module.tensor_key_prepare(self, other, scratch);
219    }
220}
221
222pub trait TensorKeyPrepareAlloc<B: Backend> {
223    fn tensor_key_prepare_alloc<O>(&self, other: &O, scratch: &mut Scratch<B>)
224    where
225        O: TensorKeyToRef;
226}
227
228impl<B: Backend> TensorKeyPrepareAlloc<B> for Module<B>
229where
230    Module<B>: TensorKeyPrepare<B>,
231{
232    fn tensor_key_prepare_alloc<O>(&self, other: &O, scratch: &mut Scratch<B>)
233    where
234        O: TensorKeyToRef,
235    {
236        let mut ct_prepared: TensorKeyPrepared<Vec<u8>, B> = TensorKeyPrepared::alloc(self, other);
237        self.tensor_key_prepare(ct_prepared, other, scratch);
238        ct_prepared
239    }
240}
241
242impl<D: DataRef> TensorKey<D> {
243    pub fn prepare_alloc<B: Backend>(&self, module: &Module<B>, scratch: &Scratch<B>)
244    where
245        Module<B>: TensorKeyPrepareAlloc<B>,
246    {
247        module.tensor_key_prepare_alloc(self, scratch);
248    }
249}
250
251pub trait TensorKeyPreparedToMut<B: Backend> {
252    fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B>;
253}
254
255impl<D: DataMut, B: Backend> TensorKeyPreparedToMut<B> for TensorKeyPrepared<D, B>
256where
257    GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToMut<B>,
258{
259    fn to_mut(&mut self) -> TensorKeyPrepared<&mut [u8], B> {
260        TensorKeyPrepared {
261            keys: self.keys.iter_mut().map(|c| c.to_mut()).collect(),
262        }
263    }
264}
265
266pub trait TensorKeyPreparedToRef<B: Backend> {
267    fn to_ref(&self) -> TensorKeyPrepared<&[u8], B>;
268}
269
270impl<D: DataRef, B: Backend> TensorKeyPreparedToRef<B> for TensorKeyPrepared<D, B>
271where
272    GLWESwitchingKeyPrepared<D, B>: GLWESwitchingKeyPreparedToRef<B>,
273{
274    fn to_ref(&self) -> TensorKeyPrepared<&[u8], B> {
275        TensorKeyPrepared {
276            keys: self.keys.iter().map(|c| c.to_ref()).collect(),
277        }
278    }
279}