poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/vec_znx_arithmetic.h
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/vec_znx_arithmetic.hRaw
1#ifndef SPQLIOS_VEC_ZNX_ARITHMETIC_H
2#define SPQLIOS_VEC_ZNX_ARITHMETIC_H
3
4#include <stdint.h>
5
6#include "../commons.h"
7#include "../reim/reim_fft.h"
8
9/**
10 * We support the following module families:
11 * - FFT64:
12 * all the polynomials should fit at all times over 52 bits.
13 * for FHE implementations, the recommended limb-sizes are
14 * between K=10 and 20, which is good for low multiplicative depths.
15 * - NTT120:
16 * all the polynomials should fit at all times over 119 bits.
17 * for FHE implementations, the recommended limb-sizes are
18 * between K=20 and 40, which is good for large multiplicative depths.
19 */
20typedef enum module_type_t { FFT64, NTT120 } MODULE_TYPE;
21
22/** @brief opaque structure that describr the modules (ZnX,TnX) and the hardware */
23typedef struct module_info_t MODULE;
24/** @brief opaque type that represents a prepared matrix */
25typedef struct vmp_pmat_t VMP_PMAT;
26/** @brief opaque type that represents a vector of znx in DFT space */
27typedef struct vec_znx_dft_t VEC_ZNX_DFT;
28/** @brief opaque type that represents a vector of znx in large coeffs space */
29typedef struct vec_znx_bigcoeff_t VEC_ZNX_BIG;
30/** @brief opaque type that represents a prepared scalar vector product */
31typedef struct svp_ppol_t SVP_PPOL;
32/** @brief opaque type that represents a prepared left convolution vector product */
33typedef struct cnv_pvec_l_t CNV_PVEC_L;
34/** @brief opaque type that represents a prepared right convolution vector product */
35typedef struct cnv_pvec_r_t CNV_PVEC_R;
36
37/** @brief bytes needed for a vec_znx in DFT space */
38EXPORT uint64_t bytes_of_vec_znx_dft(const MODULE* module, // N
39 uint64_t size);
40
41/** @brief allocates a vec_znx in DFT space */
42EXPORT VEC_ZNX_DFT* new_vec_znx_dft(const MODULE* module, // N
43 uint64_t size);
44
45/** @brief frees memory from a vec_znx in DFT space */
46EXPORT void delete_vec_znx_dft(VEC_ZNX_DFT* res);
47
48/** @brief bytes needed for a vec_znx_big */
49EXPORT uint64_t bytes_of_vec_znx_big(const MODULE* module, // N
50 uint64_t size);
51
52/** @brief allocates a vec_znx_big */
53EXPORT VEC_ZNX_BIG* new_vec_znx_big(const MODULE* module, // N
54 uint64_t size);
55/** @brief frees memory from a vec_znx_big */
56EXPORT void delete_vec_znx_big(VEC_ZNX_BIG* res);
57
58/** @brief bytes needed for a prepared vector */
59EXPORT uint64_t bytes_of_svp_ppol(const MODULE* module); // N
60
61/** @brief allocates a prepared vector */
62EXPORT SVP_PPOL* new_svp_ppol(const MODULE* module); // N
63
64/** @brief frees memory for a prepared vector */
65EXPORT void delete_svp_ppol(SVP_PPOL* res);
66
67/** @brief bytes needed for a prepared matrix */
68EXPORT uint64_t bytes_of_vmp_pmat(const MODULE* module, // N
69 uint64_t nrows, uint64_t ncols);
70
71/** @brief allocates a prepared matrix */
72EXPORT VMP_PMAT* new_vmp_pmat(const MODULE* module, // N
73 uint64_t nrows, uint64_t ncols);
74
75/** @brief frees memory for a prepared matrix */
76EXPORT void delete_vmp_pmat(VMP_PMAT* res);
77
78/**
79 * @brief obtain a module info for ring dimension N
80 * the module-info knows about:
81 * - the dimension N (or the complex dimension m=N/2)
82 * - any moduleuted fft or ntt items
83 * - the hardware (avx, arm64, x86, ...)
84 */
85EXPORT MODULE* new_module_info(uint64_t N, MODULE_TYPE mode);
86EXPORT void delete_module_info(MODULE* module_info);
87EXPORT uint64_t module_get_n(const MODULE* module);
88
89/** @brief sets res = 0 */
90EXPORT void vec_znx_zero(const MODULE* module, // N
91 int64_t* res, uint64_t res_size, uint64_t res_sl // res
92);
93
94/** @brief sets res = a */
95EXPORT void vec_znx_copy(const MODULE* module, // N
96 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
97 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
98);
99
100/** @brief sets res = a */
101EXPORT void vec_znx_negate(const MODULE* module, // N
102 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
103 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
104);
105
106/** @brief sets res = a + b */
107EXPORT void vec_znx_add(const MODULE* module, // N
108 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
109 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
110 const int64_t* b, uint64_t b_size, uint64_t b_sl // b
111);
112
113/** @brief sets res = a - b */
114EXPORT void vec_znx_sub(const MODULE* module, // N
115 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
116 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
117 const int64_t* b, uint64_t b_size, uint64_t b_sl // b
118);
119
120/** @brief sets res = k-normalize-reduce(a) */
121EXPORT void vec_znx_normalize_base2k(const MODULE* module, // MODULE
122 uint64_t nn, // N
123 uint64_t log2_base2k, // output base 2^K
124 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
125 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
126 uint8_t* tmp_space // scratch space (size >= N)
127);
128
129/** @brief returns the minimal byte length of scratch space for vec_znx_normalize_base2k */
130EXPORT uint64_t vec_znx_normalize_base2k_tmp_bytes(const MODULE* module, uint64_t nn // N
131);
132
133/** @brief sets res = a . X^p */
134EXPORT void vec_znx_rotate(const MODULE* module, // N
135 const int64_t p, // rotation value
136 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
137 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
138);
139
140/** @brief sets res = a * (X^{p} - 1) */
141EXPORT void vec_znx_mul_xp_minus_one(const MODULE* module, // N
142 const int64_t p, // rotation value
143 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
144 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
145);
146
147/** @brief sets res = a(X^p) */
148EXPORT void vec_znx_automorphism(const MODULE* module, // N
149 const int64_t p, // X-X^p
150 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
151 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
152);
153
154/** @brief sets res = 0 */
155EXPORT void vec_dft_zero(const MODULE* module, // N
156 VEC_ZNX_DFT* res, uint64_t res_size // res
157);
158
159/** @brief sets res = a+b */
160EXPORT void vec_dft_add(const MODULE* module, // N
161 VEC_ZNX_DFT* res, uint64_t res_size, // res
162 const VEC_ZNX_DFT* a, uint64_t a_size, // a
163 const VEC_ZNX_DFT* b, uint64_t b_size // b
164);
165
166/** @brief sets res = a-b */
167EXPORT void vec_dft_sub(const MODULE* module, // N
168 VEC_ZNX_DFT* res, uint64_t res_size, // res
169 const VEC_ZNX_DFT* a, uint64_t a_size, // a
170 const VEC_ZNX_DFT* b, uint64_t b_size // b
171);
172
173/** @brief sets res = DFT(a) */
174EXPORT void vec_znx_dft(const MODULE* module, // N
175 VEC_ZNX_DFT* res, uint64_t res_size, // res
176 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
177);
178
179/** @brief sets res = iDFT(a_dft) -- output in big coeffs space */
180EXPORT void vec_znx_idft(const MODULE* module, // N
181 VEC_ZNX_BIG* res, uint64_t res_size, // res
182 const VEC_ZNX_DFT* a_dft, uint64_t a_size, // a
183 uint8_t* tmp // scratch space
184);
185
186/** @brief tmp bytes required for vec_znx_idft */
187EXPORT uint64_t vec_znx_idft_tmp_bytes(const MODULE* module, uint64_t nn);
188
189/**
190 * @brief sets res = iDFT(a_dft) -- output in big coeffs space
191 *
192 * @note a_dft is overwritten
193 */
194EXPORT void vec_znx_idft_tmp_a(const MODULE* module, // N
195 VEC_ZNX_BIG* res, uint64_t res_size, // res
196 VEC_ZNX_DFT* a_dft, uint64_t a_size // a is overwritten
197);
198
199/** @brief sets res = a+b */
200EXPORT void vec_znx_big_add(const MODULE* module, // N
201 VEC_ZNX_BIG* res, uint64_t res_size, // res
202 const VEC_ZNX_BIG* a, uint64_t a_size, // a
203 const VEC_ZNX_BIG* b, uint64_t b_size // b
204);
205/** @brief sets res = a+b */
206EXPORT void vec_znx_big_add_small(const MODULE* module, // N
207 VEC_ZNX_BIG* res, uint64_t res_size, // res
208 const VEC_ZNX_BIG* a, uint64_t a_size, // a
209 const int64_t* b, uint64_t b_size, uint64_t b_sl // b
210);
211EXPORT void vec_znx_big_add_small2(const MODULE* module, // N
212 VEC_ZNX_BIG* res, uint64_t res_size, // res
213 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
214 const int64_t* b, uint64_t b_size, uint64_t b_sl // b
215);
216
217/** @brief sets res = a-b */
218EXPORT void vec_znx_big_sub(const MODULE* module, // N
219 VEC_ZNX_BIG* res, uint64_t res_size, // res
220 const VEC_ZNX_BIG* a, uint64_t a_size, // a
221 const VEC_ZNX_BIG* b, uint64_t b_size // b
222);
223EXPORT void vec_znx_big_sub_small_b(const MODULE* module, // N
224 VEC_ZNX_BIG* res, uint64_t res_size, // res
225 const VEC_ZNX_BIG* a, uint64_t a_size, // a
226 const int64_t* b, uint64_t b_size, uint64_t b_sl // b
227);
228EXPORT void vec_znx_big_sub_small_a(const MODULE* module, // N
229 VEC_ZNX_BIG* res, uint64_t res_size, // res
230 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
231 const VEC_ZNX_BIG* b, uint64_t b_size // b
232);
233EXPORT void vec_znx_big_sub_small2(const MODULE* module, // N
234 VEC_ZNX_BIG* res, uint64_t res_size, // res
235 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
236 const int64_t* b, uint64_t b_size, uint64_t b_sl // b
237);
238
239/** @brief sets res = k-normalize(a) -- output in int64 coeffs space */
240EXPORT void vec_znx_big_normalize_base2k(const MODULE* module, // MODULE
241 uint64_t nn, // N
242 uint64_t log2_base2k, // base-2^k
243 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
244 const VEC_ZNX_BIG* a, uint64_t a_size, // a
245 uint8_t* tmp_space // temp space
246);
247
248/** @brief returns the minimal byte length of scratch space for vec_znx_big_normalize_base2k */
249EXPORT uint64_t vec_znx_big_normalize_base2k_tmp_bytes(const MODULE* module, uint64_t nn // N
250);
251
252/** @brief sets res = k-normalize(a.subrange) -- output in int64 coeffs space */
253EXPORT void vec_znx_big_range_normalize_base2k( //
254 const MODULE* module, // MODULE
255 uint64_t nn,
256 uint64_t log2_base2k, // base-2^k
257 int64_t* res, uint64_t res_size, uint64_t res_sl, // res
258 const VEC_ZNX_BIG* a, uint64_t a_range_begin, uint64_t a_range_xend, uint64_t a_range_step, // range
259 uint8_t* tmp_space // temp space
260);
261
262/** @brief returns the minimal byte length of scratch space for vec_znx_big_range_normalize_base2k */
263EXPORT uint64_t vec_znx_big_range_normalize_base2k_tmp_bytes( //
264 const MODULE* module, uint64_t nn // N
265);
266
267/** @brief sets res = a . X^p */
268EXPORT void vec_znx_big_rotate(const MODULE* module, // N
269 int64_t p, // rotation value
270 VEC_ZNX_BIG* res, uint64_t res_size, // res
271 const VEC_ZNX_BIG* a, uint64_t a_size // a
272);
273
274/** @brief sets res = a(X^p) */
275EXPORT void vec_znx_big_automorphism(const MODULE* module, // N
276 int64_t p, // X-X^p
277 VEC_ZNX_BIG* res, uint64_t res_size, // res
278 const VEC_ZNX_BIG* a, uint64_t a_size // a
279);
280
281/** @brief apply a svp product, result = ppol * a, presented in DFT space */
282EXPORT void svp_apply_dft(const MODULE* module, // N
283 const VEC_ZNX_DFT* res, uint64_t res_size, // output
284 const SVP_PPOL* ppol, // prepared pol
285 const int64_t* a, uint64_t a_size, uint64_t a_sl // a
286);
287
288/** @brief apply a svp product, result = ppol * a, presented in DFT space */
289EXPORT void svp_apply_dft_to_dft(const MODULE* module, // N
290 const VEC_ZNX_DFT* res, uint64_t res_size,
291 uint64_t res_cols, // output
292 const SVP_PPOL* ppol, // prepared pol
293 const VEC_ZNX_DFT* a, uint64_t a_size, uint64_t a_cols // a
294);
295
296/** @brief prepares a svp polynomial */
297EXPORT void svp_prepare(const MODULE* module, // N
298 SVP_PPOL* ppol, // output
299 const int64_t* pol // a
300);
301
302/** @brief res = a * b : small integer polynomial product */
303EXPORT void znx_small_single_product(const MODULE* module, // N
304 int64_t* res, // output
305 const int64_t* a, // a
306 const int64_t* b, // b
307 uint8_t* tmp);
308
309/** @brief tmp bytes required for znx_small_single_product */
310EXPORT uint64_t znx_small_single_product_tmp_bytes(const MODULE* module, uint64_t nn);
311
312/** @brief minimal scratch space byte-size required for the vmp_prepare function */
313EXPORT uint64_t vmp_prepare_tmp_bytes(const MODULE* module, uint64_t nn, // N
314 uint64_t nrows, uint64_t ncols);
315
316/** @brief prepares a vmp matrix (contiguous row-major version) */
317EXPORT void vmp_prepare_contiguous(const MODULE* module, // N
318 VMP_PMAT* pmat, // output
319 const int64_t* mat, uint64_t nrows, uint64_t ncols, // a
320 uint8_t* tmp_space // scratch space
321);
322
323/** @brief applies a vmp product (result in DFT space) adds to res inplace */
324EXPORT void vmp_apply_dft_add(const MODULE* module, // N
325 VEC_ZNX_DFT* res, uint64_t res_size, // res
326 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
327 const VMP_PMAT* pmat, uint64_t nrows, uint64_t ncols, uint64_t pmat_scale, // prep matrix
328 uint8_t* tmp_space // scratch space
329);
330
331/** @brief applies a vmp product (result in DFT space) */
332EXPORT void vmp_apply_dft(const MODULE* module, // N
333 VEC_ZNX_DFT* res, uint64_t res_size, // res
334 const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
335 const VMP_PMAT* pmat, uint64_t nrows, uint64_t ncols, // prep matrix
336 uint8_t* tmp_space // scratch space
337);
338
339/** @brief minimal size of the tmp_space */
340EXPORT uint64_t vmp_apply_dft_tmp_bytes(const MODULE* module, uint64_t nn, // N
341 uint64_t res_size, // res
342 uint64_t a_size, // a
343 uint64_t nrows, uint64_t ncols // prep matrix
344);
345
346/** @brief applies vmp product */
347EXPORT void vmp_apply_dft_to_dft(const MODULE* module, // N
348 VEC_ZNX_DFT* res, const uint64_t res_size, // res
349 const VEC_ZNX_DFT* a_dft, uint64_t a_size, // a
350 const VMP_PMAT* pmat, const uint64_t nrows,
351 const uint64_t ncols, // prep matrix
352 uint8_t* tmp_space // scratch space (a_size*sizeof(reim4) bytes)
353);
354
355/** @brief applies vmp product and adds to res inplace */
356EXPORT void vmp_apply_dft_to_dft_add(const MODULE* module, // N
357 VEC_ZNX_DFT* res, const uint64_t res_size, // res
358 const VEC_ZNX_DFT* a_dft, uint64_t a_size, // a
359 const VMP_PMAT* pmat, const uint64_t nrows, const uint64_t ncols,
360 const uint64_t pmat_scale, // prep matrix
361 uint8_t* tmp_space // scratch space (a_size*sizeof(reim4) bytes)
362);
363
364/** @brief minimal size of the tmp_space */
365EXPORT uint64_t vmp_apply_dft_to_dft_tmp_bytes(const MODULE* module, uint64_t nn, // N
366 uint64_t res_size, // res
367 uint64_t a_size, // a
368 uint64_t nrows, uint64_t ncols // prep matrix
369);
370#endif // SPQLIOS_VEC_ZNX_ARITHMETIC_H