poulpy/core/src/glwe_ops.rs
core/src/glwe_ops.rsRaw
1use backend::{FFT64, Module, Scratch, VecZnx, VecZnxOps, ZnxZero};
2
3use crate::{GLWECiphertext, GLWECiphertextToMut, GLWECiphertextToRef, Infos, SetMetaData};
4
5pub trait GLWEOps: GLWECiphertextToMut + Infos + SetMetaData {
6 fn add<A, B>(&mut self, module: &Module<FFT64>, a: &A, b: &B)
7 where
8 A: GLWECiphertextToRef + Infos,
9 B: GLWECiphertextToRef + Infos,
10 {
11 #[cfg(debug_assertions)]
12 {
13 assert_eq!(a.n(), module.n());
14 assert_eq!(b.n(), module.n());
15 assert_eq!(self.n(), module.n());
16 assert_eq!(a.basek(), b.basek());
17 assert!(self.rank() >= a.rank().max(b.rank()));
18 }
19
20 let min_col: usize = a.rank().min(b.rank()) + 1;
21 let max_col: usize = a.rank().max(b.rank() + 1);
22 let self_col: usize = self.rank() + 1;
23
24 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
25 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
26 let b_ref: &GLWECiphertext<&[u8]> = &b.to_ref();
27
28 (0..min_col).for_each(|i| {
29 module.vec_znx_add(&mut self_mut.data, i, &a_ref.data, i, &b_ref.data, i);
30 });
31
32 if a.rank() > b.rank() {
33 (min_col..max_col).for_each(|i| {
34 module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
35 });
36 } else {
37 (min_col..max_col).for_each(|i| {
38 module.vec_znx_copy(&mut self_mut.data, i, &b_ref.data, i);
39 });
40 }
41
42 let size: usize = self_mut.size();
43 (max_col..self_col).for_each(|i| {
44 (0..size).for_each(|j| {
45 self_mut.data.zero_at(i, j);
46 });
47 });
48
49 self.set_basek(a.basek());
50 self.set_k(a.k().max(b.k()));
51 }
52
53 fn add_inplace<A>(&mut self, module: &Module<FFT64>, a: &A)
54 where
55 A: GLWECiphertextToRef + Infos,
56 {
57 #[cfg(debug_assertions)]
58 {
59 assert_eq!(a.n(), module.n());
60 assert_eq!(self.n(), module.n());
61 assert_eq!(self.basek(), a.basek());
62 assert!(self.rank() >= a.rank())
63 }
64
65 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
66 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
67
68 (0..a.rank() + 1).for_each(|i| {
69 module.vec_znx_add_inplace(&mut self_mut.data, i, &a_ref.data, i);
70 });
71
72 self.set_k(a.k().max(self.k()));
73 }
74
75 fn sub<A, B>(&mut self, module: &Module<FFT64>, a: &A, b: &B)
76 where
77 A: GLWECiphertextToRef + Infos,
78 B: GLWECiphertextToRef + Infos,
79 {
80 #[cfg(debug_assertions)]
81 {
82 assert_eq!(a.n(), module.n());
83 assert_eq!(b.n(), module.n());
84 assert_eq!(self.n(), module.n());
85 assert_eq!(a.basek(), b.basek());
86 assert!(self.rank() >= a.rank().max(b.rank()));
87 }
88
89 let min_col: usize = a.rank().min(b.rank()) + 1;
90 let max_col: usize = a.rank().max(b.rank() + 1);
91 let self_col: usize = self.rank() + 1;
92
93 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
94 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
95 let b_ref: &GLWECiphertext<&[u8]> = &b.to_ref();
96
97 (0..min_col).for_each(|i| {
98 module.vec_znx_sub(&mut self_mut.data, i, &a_ref.data, i, &b_ref.data, i);
99 });
100
101 if a.rank() > b.rank() {
102 (min_col..max_col).for_each(|i| {
103 module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
104 });
105 } else {
106 (min_col..max_col).for_each(|i| {
107 module.vec_znx_copy(&mut self_mut.data, i, &b_ref.data, i);
108 module.vec_znx_negate_inplace(&mut self_mut.data, i);
109 });
110 }
111
112 let size: usize = self_mut.size();
113 (max_col..self_col).for_each(|i| {
114 (0..size).for_each(|j| {
115 self_mut.data.zero_at(i, j);
116 });
117 });
118
119 self.set_basek(a.basek());
120 self.set_k(a.k().max(b.k()));
121 }
122
123 fn sub_inplace_ab<A>(&mut self, module: &Module<FFT64>, a: &A)
124 where
125 A: GLWECiphertextToRef + Infos,
126 {
127 #[cfg(debug_assertions)]
128 {
129 assert_eq!(a.n(), module.n());
130 assert_eq!(self.n(), module.n());
131 assert_eq!(self.basek(), a.basek());
132 assert!(self.rank() >= a.rank())
133 }
134
135 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
136 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
137
138 (0..a.rank() + 1).for_each(|i| {
139 module.vec_znx_sub_ab_inplace(&mut self_mut.data, i, &a_ref.data, i);
140 });
141
142 self.set_k(a.k().max(self.k()));
143 }
144
145 fn sub_inplace_ba<A>(&mut self, module: &Module<FFT64>, a: &A)
146 where
147 A: GLWECiphertextToRef + Infos,
148 {
149 #[cfg(debug_assertions)]
150 {
151 assert_eq!(a.n(), module.n());
152 assert_eq!(self.n(), module.n());
153 assert_eq!(self.basek(), a.basek());
154 assert!(self.rank() >= a.rank())
155 }
156
157 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
158 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
159
160 (0..a.rank() + 1).for_each(|i| {
161 module.vec_znx_sub_ba_inplace(&mut self_mut.data, i, &a_ref.data, i);
162 });
163
164 self.set_k(a.k().max(self.k()));
165 }
166
167 fn rotate<A>(&mut self, module: &Module<FFT64>, k: i64, a: &A)
168 where
169 A: GLWECiphertextToRef + Infos,
170 {
171 #[cfg(debug_assertions)]
172 {
173 assert_eq!(a.n(), module.n());
174 assert_eq!(self.n(), module.n());
175 assert_eq!(self.rank(), a.rank())
176 }
177
178 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
179 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
180
181 (0..a.rank() + 1).for_each(|i| {
182 module.vec_znx_rotate(k, &mut self_mut.data, i, &a_ref.data, i);
183 });
184
185 self.set_basek(a.basek());
186 self.set_k(a.k());
187 }
188
189 fn rotate_inplace(&mut self, module: &Module<FFT64>, k: i64) {
190 #[cfg(debug_assertions)]
191 {
192 assert_eq!(self.n(), module.n());
193 }
194
195 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
196
197 (0..self_mut.rank() + 1).for_each(|i| {
198 module.vec_znx_rotate_inplace(k, &mut self_mut.data, i);
199 });
200 }
201
202 fn copy<A>(&mut self, module: &Module<FFT64>, a: &A)
203 where
204 A: GLWECiphertextToRef + Infos,
205 {
206 #[cfg(debug_assertions)]
207 {
208 assert_eq!(self.n(), module.n());
209 assert_eq!(a.n(), module.n());
210 assert_eq!(self.rank(), a.rank());
211 }
212
213 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
214 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
215
216 (0..self_mut.rank() + 1).for_each(|i| {
217 module.vec_znx_copy(&mut self_mut.data, i, &a_ref.data, i);
218 });
219
220 self.set_k(a.k());
221 self.set_basek(a.basek());
222 }
223
224 fn rsh(&mut self, k: usize, scratch: &mut Scratch) {
225 let basek: usize = self.basek();
226 let mut self_mut: GLWECiphertext<&mut [u8]> = self.to_mut();
227 self_mut.data.rsh(basek, k, scratch);
228 }
229
230 fn normalize<A>(&mut self, module: &Module<FFT64>, a: &A, scratch: &mut Scratch)
231 where
232 A: GLWECiphertextToRef + Infos,
233 {
234 #[cfg(debug_assertions)]
235 {
236 assert_eq!(self.n(), module.n());
237 assert_eq!(a.n(), module.n());
238 assert_eq!(self.rank(), a.rank());
239 }
240
241 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
242 let a_ref: &GLWECiphertext<&[u8]> = &a.to_ref();
243
244 (0..self_mut.rank() + 1).for_each(|i| {
245 module.vec_znx_normalize(a.basek(), &mut self_mut.data, i, &a_ref.data, i, scratch);
246 });
247 self.set_basek(a.basek());
248 self.set_k(a.k());
249 }
250
251 fn normalize_inplace(&mut self, module: &Module<FFT64>, scratch: &mut Scratch) {
252 #[cfg(debug_assertions)]
253 {
254 assert_eq!(self.n(), module.n());
255 }
256 let self_mut: &mut GLWECiphertext<&mut [u8]> = &mut self.to_mut();
257 (0..self_mut.rank() + 1).for_each(|i| {
258 module.vec_znx_normalize_inplace(self_mut.basek(), &mut self_mut.data, i, scratch);
259 });
260 }
261}
262
263impl GLWECiphertext<Vec<u8>> {
264 pub fn rsh_scratch_space(module: &Module<FFT64>) -> usize {
265 VecZnx::rsh_scratch_space(module.n())
266 }
267}