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