Skip to content

Commit a04fa51

Browse files
committed
vec_znx_arithmetic api def
- implementation of reim naive fft (for tests purposes) - implementation of reim16 ref + assembly - precompute omega for the reim16 ref function - unittests of the reim fft16 functions.
1 parent d76a952 commit a04fa51

File tree

3 files changed

+834
-0
lines changed

3 files changed

+834
-0
lines changed

spqlios/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ set(SRCS_F128
8787
# H header files containing the public API (these headers are installed)
8888
set(HEADERSPUBLIC
8989
commons.h
90+
arithmetic/vec_znx_arithmetic.h
9091
cplx/cplx_fft.h
9192
reim/reim_fft.h
9293
q120/q120_common.h
@@ -107,6 +108,7 @@ set(HEADERSPRIVATE
107108
reim/reim_fft_private.h
108109
q120/q120_arithmetic_private.h
109110
q120/q120_ntt_private.h
111+
arithmetic/vec_znx_arithmetic.h
110112
)
111113

112114
set(SPQLIOSSOURCES
+344
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,344 @@
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+
*/
20+
typedef enum module_type_t { FFT64, NTT120 } MODULE_TYPE;
21+
22+
/** @brief opaque structure that describr the modules (ZnX,TnX) and the hardware */
23+
typedef struct module_info_t MODULE;
24+
/** @brief opaque type that represents a prepared matrix */
25+
typedef struct vmp_pmat_t VMP_PMAT;
26+
/** @brief opaque type that represents a vector of znx in DFT space */
27+
typedef struct vec_znx_dft_t VEC_ZNX_DFT;
28+
/** @brief opaque type that represents a vector of znx in large coeffs space */
29+
typedef struct vec_znx_bigcoeff_t VEC_ZNX_BIG;
30+
/** @brief opaque type that represents a prepared scalar vector product */
31+
typedef struct svp_ppol_t SVP_PPOL;
32+
/** @brief opaque type that represents a prepared left convolution vector product */
33+
typedef struct cnv_pvec_l_t CNV_PVEC_L;
34+
/** @brief opaque type that represents a prepared right convolution vector product */
35+
typedef struct cnv_pvec_r_t CNV_PVEC_R;
36+
37+
/** @brief allocates a prepared matrix (release with free) */
38+
EXPORT VMP_PMAT* vmp_pmat_alloc(const MODULE* module, // N
39+
uint64_t nrows, uint64_t ncols // dimensions
40+
);
41+
42+
/** @brief allocates a vec_znx in DFT space (release with free) */
43+
EXPORT VEC_ZNX_DFT* vec_znx_dft_alloc(const MODULE* module, // N
44+
uint64_t size);
45+
46+
/** @brief allocates a vec_znx_big (release with free) */
47+
EXPORT VEC_ZNX_BIG* vec_znx_big_alloc(const MODULE* module, // N
48+
uint64_t size);
49+
50+
/** @brief allocates a prepared vector (release with free) */
51+
EXPORT SVP_PPOL* svp_ppol_alloc(const MODULE* module); // N
52+
53+
/** @brief free something (vec_znx, pvmp, pcnv...) was allocated
54+
* It just calls free. It is required to expose it for foreign
55+
* languages bindings that do cannot call libc directly
56+
*/
57+
EXPORT void std_free(void* address);
58+
59+
/**
60+
* @brief obtain a module info for ring dimension N
61+
* the module-info knows about:
62+
* - the dimension N (or the complex dimension m=N/2)
63+
* - any moduleuted fft or ntt items
64+
* - the hardware (avx, arm64, x86, ...)
65+
*/
66+
EXPORT MODULE* new_module_info(uint64_t N, MODULE_TYPE mode);
67+
EXPORT void delete_module_info(MODULE* module_info);
68+
EXPORT uint64_t module_get_n(const MODULE* module);
69+
70+
/** @brief sets res = 0 */
71+
EXPORT void vec_znx_zero(const MODULE* module, // N
72+
int64_t* res, uint64_t res_size, uint64_t res_sl // res
73+
);
74+
75+
/** @brief sets res = a */
76+
EXPORT void vec_znx_copy(const MODULE* module, // N
77+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
78+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
79+
);
80+
81+
/** @brief sets res = a */
82+
EXPORT void vec_znx_negate(const MODULE* module, // N
83+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
84+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
85+
);
86+
87+
/** @brief sets res = a + b */
88+
EXPORT void vec_znx_add(const MODULE* module, // N
89+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
90+
const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
91+
const int64_t* b, uint64_t b_size, uint64_t b_sl // b
92+
);
93+
94+
/** @brief sets res = a - b */
95+
EXPORT void vec_znx_sub(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+
const int64_t* b, uint64_t b_size, uint64_t b_sl // b
99+
);
100+
101+
/** @brief sets res = k-normalize-reduce(a) */
102+
EXPORT void vec_znx_normalize_base2k(const MODULE* module, // N
103+
uint64_t log2_base2k, // output base 2^K
104+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
105+
const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
106+
uint8_t* tmp_space // scratch space (size >= N)
107+
);
108+
109+
/** @brief returns the minimal byte length of scratch space for vec_znx_normalize_base2k */
110+
EXPORT uint64_t vec_znx_normalize_base2k_tmp_bytes(const MODULE* module, // N
111+
uint64_t res_size, // res size
112+
uint64_t inp_size // inp size
113+
);
114+
115+
/** @brief sets res = a . X^p */
116+
EXPORT void vec_znx_rotate(const MODULE* module, // N
117+
const int64_t p, // rotation value
118+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
119+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
120+
);
121+
122+
/** @brief sets res = a(X^p) */
123+
EXPORT void vec_znx_automorphism(const MODULE* module, // N
124+
const int64_t p, // X-X^p
125+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
126+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
127+
);
128+
129+
/** @brief prepares a vmp matrix (contiguous row-major version) */
130+
EXPORT void vmp_prepare_contiguous(const MODULE* module, // N
131+
VMP_PMAT* pmat, // output
132+
const int64_t* mat, uint64_t nrows, uint64_t ncols, // a
133+
uint8_t* tmp_space // scratch space
134+
);
135+
136+
/** @brief prepares a vmp matrix (mat[row*ncols+col] points to the item) */
137+
EXPORT void vmp_prepare_dblptr(const MODULE* module, // N
138+
VMP_PMAT* pmat, // output
139+
const int64_t** mat, uint64_t nrows, uint64_t ncols, // a
140+
uint8_t* tmp_space // scratch space
141+
);
142+
143+
/** @brief sets res = 0 */
144+
EXPORT void vec_dft_zero(const MODULE* module, // N
145+
VEC_ZNX_DFT* res, uint64_t res_size // res
146+
);
147+
148+
/** @brief sets res = a+b */
149+
EXPORT void vec_dft_add(const MODULE* module, // N
150+
VEC_ZNX_DFT* res, uint64_t res_size, // res
151+
const VEC_ZNX_DFT* a, uint64_t a_size, // a
152+
const VEC_ZNX_DFT* b, uint64_t b_size // b
153+
);
154+
155+
/** @brief sets res = a-b */
156+
EXPORT void vec_dft_sub(const MODULE* module, // N
157+
VEC_ZNX_DFT* res, uint64_t res_size, // res
158+
const VEC_ZNX_DFT* a, uint64_t a_size, // a
159+
const VEC_ZNX_DFT* b, uint64_t b_size // b
160+
);
161+
162+
/** @brief sets res = DFT(a) */
163+
EXPORT void vec_znx_dft(const MODULE* module, // N
164+
VEC_ZNX_DFT* res, uint64_t res_size, // res
165+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
166+
);
167+
168+
/** @brief sets res = iDFT(a_dft) -- output in big coeffs space */
169+
EXPORT void vec_znx_idft(const MODULE* module, // N
170+
VEC_ZNX_BIG* res, uint64_t res_size, // res
171+
const VEC_ZNX_DFT* a_dft, uint64_t a_size, // a
172+
uint8_t* tmp // scratch space
173+
);
174+
175+
/** @brief tmp bytes required for vec_znx_idft */
176+
EXPORT uint64_t vec_znx_idft_tmp_bytes(const MODULE* module);
177+
178+
/**
179+
* @brief sets res = iDFT(a_dft) -- output in big coeffs space
180+
*
181+
* @note a_dft is overwritten
182+
*/
183+
EXPORT void vec_znx_idft_tmp_a(const MODULE* module, // N
184+
VEC_ZNX_BIG* res, uint64_t res_size, // res
185+
VEC_ZNX_DFT* a_dft, uint64_t a_size // a is overwritten
186+
);
187+
188+
/** @brief sets res = a+b */
189+
EXPORT void vec_znx_big_add(const MODULE* module, // N
190+
VEC_ZNX_BIG* res, uint64_t res_size, // res
191+
const VEC_ZNX_BIG* a, uint64_t a_size, // a
192+
const VEC_ZNX_BIG* b, uint64_t b_size // b
193+
);
194+
/** @brief sets res = a+b */
195+
EXPORT void vec_znx_big_add_small(const MODULE* module, // N
196+
VEC_ZNX_BIG* res, uint64_t res_size, // res
197+
const VEC_ZNX_BIG* a, uint64_t a_size, // a
198+
const int64_t* b, uint64_t b_size, uint64_t b_sl // b
199+
);
200+
EXPORT void vec_znx_big_add_small2(const MODULE* module, // N
201+
VEC_ZNX_BIG* res, uint64_t res_size, // res
202+
const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
203+
const int64_t* b, uint64_t b_size, uint64_t b_sl // b
204+
);
205+
206+
/** @brief sets res = a-b */
207+
EXPORT void vec_znx_big_sub(const MODULE* module, // N
208+
VEC_ZNX_BIG* res, uint64_t res_size, // res
209+
const VEC_ZNX_BIG* a, uint64_t a_size, // a
210+
const VEC_ZNX_BIG* b, uint64_t b_size // b
211+
);
212+
EXPORT void vec_znx_big_sub_small_b(const MODULE* module, // N
213+
VEC_ZNX_BIG* res, uint64_t res_size, // res
214+
const VEC_ZNX_BIG* a, uint64_t a_size, // a
215+
const int64_t* b, uint64_t b_size, uint64_t b_sl // b
216+
);
217+
EXPORT void vec_znx_big_sub_small_a(const MODULE* module, // N
218+
VEC_ZNX_BIG* res, uint64_t res_size, // res
219+
const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
220+
const VEC_ZNX_BIG* b, uint64_t b_size // b
221+
);
222+
EXPORT void vec_znx_big_sub_small2(const MODULE* module, // N
223+
VEC_ZNX_BIG* res, uint64_t res_size, // res
224+
const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
225+
const int64_t* b, uint64_t b_size, uint64_t b_sl // b
226+
);
227+
228+
/** @brief sets res = k-normalize(a) -- output in int64 coeffs space */
229+
EXPORT void vec_znx_big_normalize_base2k(const MODULE* module, // N
230+
uint64_t log2_base2k, // base-2^k
231+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
232+
const VEC_ZNX_BIG* a, uint64_t a_size, // a
233+
uint8_t* tmp_space // temp space
234+
);
235+
236+
/** @brief returns the minimal byte length of scratch space for vec_znx_big_normalize_base2k */
237+
EXPORT uint64_t vec_znx_big_normalize_base2k_tmp_bytes(const MODULE* module, // N
238+
uint64_t res_size, // res size
239+
uint64_t inp_size // inp size
240+
);
241+
242+
/** @brief apply a svp product, result = ppol * a, presented in DFT space */
243+
EXPORT void fft64_svp_apply_dft(const MODULE* module, // N
244+
const VEC_ZNX_DFT* res, uint64_t res_size, // output
245+
const SVP_PPOL* ppol, // prepared pol
246+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
247+
);
248+
249+
/** @brief sets res = k-normalize(a.subrange) -- output in int64 coeffs space */
250+
EXPORT void vec_znx_big_range_normalize_base2k( //
251+
const MODULE* module, // N
252+
uint64_t log2_base2k, // base-2^k
253+
int64_t* res, uint64_t res_size, uint64_t res_sl, // res
254+
const VEC_ZNX_BIG* a, uint64_t a_range_begin, uint64_t a_range_xend, uint64_t a_range_step, // range
255+
uint8_t* tmp_space // temp space
256+
);
257+
258+
/** @brief returns the minimal byte length of scratch space for vec_znx_big_range_normalize_base2k */
259+
EXPORT uint64_t vec_znx_big_range_normalize_base2k_tmp_bytes( //
260+
const MODULE* module, // N
261+
uint64_t res_size, // res size
262+
uint64_t inp_size // inp size
263+
);
264+
265+
/** @brief sets res = a . X^p */
266+
EXPORT void vec_znx_big_rotate(const MODULE* module, // N
267+
int64_t p, // rotation value
268+
VEC_ZNX_BIG* res, uint64_t res_size, // res
269+
const VEC_ZNX_BIG* a, uint64_t a_size // a
270+
);
271+
272+
/** @brief sets res = a(X^p) */
273+
EXPORT void vec_znx_big_automorphism(const MODULE* module, // N
274+
int64_t p, // X-X^p
275+
VEC_ZNX_BIG* res, uint64_t res_size, // res
276+
const VEC_ZNX_BIG* a, uint64_t a_size // a
277+
);
278+
279+
/** @brief apply a svp product, result = ppol * a, presented in DFT space */
280+
EXPORT void svp_apply_dft(const MODULE* module, // N
281+
const VEC_ZNX_DFT* res, uint64_t res_size, // output
282+
const SVP_PPOL* ppol, // prepared pol
283+
const int64_t* a, uint64_t a_size, uint64_t a_sl // a
284+
);
285+
286+
/** @brief prepares a svp polynomial */
287+
EXPORT void svp_prepare(const MODULE* module, // N
288+
SVP_PPOL* ppol, // output
289+
const int64_t* pol // a
290+
);
291+
292+
/** @brief res = a * b : small integer polynomial product */
293+
EXPORT void znx_small_single_product(const MODULE* module, // N
294+
int64_t* res, // output
295+
const int64_t* a, // a
296+
const int64_t* b, // b
297+
uint8_t* tmp);
298+
299+
/** @brief tmp bytes required for znx_small_single_product */
300+
EXPORT uint64_t znx_small_single_product_tmp_bytes(const MODULE* module);
301+
302+
/** @brief prepares a vmp matrix (contiguous row-major version) */
303+
EXPORT void vmp_prepare_contiguous(const MODULE* module, // N
304+
VMP_PMAT* pmat, // output
305+
const int64_t* mat, uint64_t nrows, uint64_t ncols, // a
306+
uint8_t* tmp_space // scratch space
307+
);
308+
309+
/** @brief minimal scratch space byte-size required for the vmp_prepare function */
310+
EXPORT uint64_t vmp_prepare_contiguous_tmp_bytes(const MODULE* module, // N
311+
uint64_t nrows, uint64_t ncols);
312+
313+
/** @brief applies a vmp product (result in DFT space) */
314+
EXPORT void vmp_apply_dft(const MODULE* module, // N
315+
VEC_ZNX_DFT* res, uint64_t res_size, // res
316+
const int64_t* a, uint64_t a_size, uint64_t a_sl, // a
317+
const VMP_PMAT* pmat, uint64_t nrows, uint64_t ncols, // prep matrix
318+
uint8_t* tmp_space // scratch space
319+
);
320+
321+
/** @brief minimal size of the tmp_space */
322+
EXPORT uint64_t vmp_apply_dft_tmp_bytes(const MODULE* module, // N
323+
uint64_t res_size, // res
324+
uint64_t a_size, // a
325+
uint64_t nrows, uint64_t ncols // prep matrix
326+
);
327+
328+
/** @brief minimal size of the tmp_space */
329+
EXPORT void vmp_apply_dft_to_dft(const MODULE* module, // N
330+
VEC_ZNX_DFT* res, const uint64_t res_size, // res
331+
const VEC_ZNX_DFT* a_dft, uint64_t a_size, // a
332+
const VMP_PMAT* pmat, const uint64_t nrows,
333+
const uint64_t ncols, // prep matrix
334+
uint8_t* tmp_space // scratch space (a_size*sizeof(reim4) bytes)
335+
);
336+
;
337+
338+
/** @brief minimal size of the tmp_space */
339+
EXPORT uint64_t vmp_apply_dft_to_dft_tmp_bytes(const MODULE* module, // N
340+
uint64_t res_size, // res
341+
uint64_t a_size, // a
342+
uint64_t nrows, uint64_t ncols // prep matrix
343+
);
344+
#endif // SPQLIOS_VEC_ZNX_ARITHMETIC_H

0 commit comments

Comments
 (0)