poulpy/core/src/lwe/conversion.rs
core/src/lwe/conversion.rsRaw
1use backend::hal::{
2 api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, ZnxView, ZnxViewMut, ZnxZero},
3 layouts::{Backend, DataMut, DataRef, Module, Scratch},
4};
5
6use crate::{
7 GLWECiphertext, GLWEKeyswitchFamily, GLWEToLWESwitchingKeyExec, Infos, LWECiphertext, LWESwitchingKeyExec,
8 LWEToGLWESwitchingKeyExec, TakeGLWECt,
9};
10
11impl<DLwe: DataMut> LWECiphertext<DLwe> {
12 pub fn sample_extract<DGlwe: DataRef>(&mut self, a: &GLWECiphertext<DGlwe>) {
13 #[cfg(debug_assertions)]
14 {
15 assert!(self.n() <= a.n());
16 }
17
18 let min_size: usize = self.size().min(a.size());
19 let n: usize = self.n();
20
21 self.data.zero();
22 (0..min_size).for_each(|i| {
23 let data_lwe: &mut [i64] = self.data.at_mut(0, i);
24 data_lwe[0] = a.data.at(0, i)[0];
25 data_lwe[1..].copy_from_slice(&a.data.at(1, i)[..n]);
26 });
27 }
28
29 pub fn from_glwe<DGlwe, DKs, B: Backend>(
30 &mut self,
31 module: &Module<B>,
32 a: &GLWECiphertext<DGlwe>,
33 ks: &GLWEToLWESwitchingKeyExec<DKs, B>,
34 scratch: &mut Scratch<B>,
35 ) where
36 DGlwe: DataRef,
37 DKs: DataRef,
38 Module<B>: GLWEKeyswitchFamily<B>,
39 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
40 {
41 #[cfg(debug_assertions)]
42 {
43 assert_eq!(self.basek(), a.basek());
44 assert_eq!(a.n(), ks.n());
45 }
46 let (mut tmp_glwe, scratch1) = scratch.take_glwe_ct(a.n(), a.basek(), self.k(), 1);
47 tmp_glwe.keyswitch(module, a, &ks.0, scratch1);
48 self.sample_extract(&tmp_glwe);
49 }
50
51 pub fn keyswitch<A, DKs, B: Backend>(
52 &mut self,
53 module: &Module<B>,
54 a: &LWECiphertext<A>,
55 ksk: &LWESwitchingKeyExec<DKs, B>,
56 scratch: &mut Scratch<B>,
57 ) where
58 A: DataRef,
59 DKs: DataRef,
60 Module<B>: GLWEKeyswitchFamily<B>,
61 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
62 {
63 #[cfg(debug_assertions)]
64 {
65 assert!(self.n() <= module.n());
66 assert!(a.n() <= module.n());
67 assert_eq!(self.basek(), a.basek());
68 }
69
70 let max_k: usize = self.k().max(a.k());
71 let basek: usize = self.basek();
72
73 let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), basek, max_k, 1);
74 glwe.data.zero();
75
76 let n_lwe: usize = a.n();
77
78 (0..a.size()).for_each(|i| {
79 let data_lwe: &[i64] = a.data.at(0, i);
80 glwe.data.at_mut(0, i)[0] = data_lwe[0];
81 glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
82 });
83
84 glwe.keyswitch_inplace(module, &ksk.0, scratch1);
85
86 self.sample_extract(&glwe);
87 }
88}
89
90impl GLWECiphertext<Vec<u8>> {
91 pub fn from_lwe_scratch_space<B: Backend>(
92 module: &Module<B>,
93 n: usize,
94 basek: usize,
95 k_lwe: usize,
96 k_glwe: usize,
97 k_ksk: usize,
98 rank: usize,
99 ) -> usize
100 where
101 Module<B>: GLWEKeyswitchFamily<B>,
102 {
103 GLWECiphertext::keyswitch_scratch_space(module, n, basek, k_glwe, k_lwe, k_ksk, 1, 1, rank)
104 + GLWECiphertext::bytes_of(n, basek, k_lwe, 1)
105 }
106}
107
108impl<D: DataMut> GLWECiphertext<D> {
109 pub fn from_lwe<DLwe, DKsk, B: Backend>(
110 &mut self,
111 module: &Module<B>,
112 lwe: &LWECiphertext<DLwe>,
113 ksk: &LWEToGLWESwitchingKeyExec<DKsk, B>,
114 scratch: &mut Scratch<B>,
115 ) where
116 DLwe: DataRef,
117 DKsk: DataRef,
118 Module<B>: GLWEKeyswitchFamily<B>,
119 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
120 {
121 #[cfg(debug_assertions)]
122 {
123 assert!(lwe.n() <= self.n());
124 assert_eq!(self.basek(), self.basek());
125 }
126
127 let (mut glwe, scratch1) = scratch.take_glwe_ct(ksk.n(), lwe.basek(), lwe.k(), 1);
128 glwe.data.zero();
129
130 let n_lwe: usize = lwe.n();
131
132 (0..lwe.size()).for_each(|i| {
133 let data_lwe: &[i64] = lwe.data.at(0, i);
134 glwe.data.at_mut(0, i)[0] = data_lwe[0];
135 glwe.data.at_mut(1, i)[..n_lwe].copy_from_slice(&data_lwe[1..]);
136 });
137
138 self.keyswitch(module, &glwe, &ksk.0, scratch1);
139 }
140}