|
| 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