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