arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/vec_znx_dft.c
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/vec_znx_dft.cRaw
  1#include <string.h>
  2
  3#include "../q120/q120_arithmetic.h"
  4#include "vec_znx_arithmetic_private.h"
  5
  6EXPORT void vec_znx_dft(const MODULE* module,                             // N
  7                        VEC_ZNX_DFT* res, uint64_t res_size,              // res
  8                        const int64_t* a, uint64_t a_size, uint64_t a_sl  // a
  9) {
 10  return module->func.vec_znx_dft(module, res, res_size, a, a_size, a_sl);
 11}
 12
 13EXPORT void vec_dft_add(const MODULE* module,                   // N
 14                        VEC_ZNX_DFT* res, uint64_t res_size,    // res
 15                        const VEC_ZNX_DFT* a, uint64_t a_size,  // a
 16                        const VEC_ZNX_DFT* b, uint64_t b_size   // b
 17) {
 18  return module->func.vec_dft_add(module, res, res_size, a, a_size, b, b_size);
 19}
 20
 21EXPORT void vec_dft_sub(const MODULE* module,                   // N
 22                        VEC_ZNX_DFT* res, uint64_t res_size,    // res
 23                        const VEC_ZNX_DFT* a, uint64_t a_size,  // a
 24                        const VEC_ZNX_DFT* b, uint64_t b_size   // b
 25) {
 26  return module->func.vec_dft_sub(module, res, res_size, a, a_size, b, b_size);
 27}
 28
 29EXPORT void vec_znx_idft(const MODULE* module,                       // N
 30                         VEC_ZNX_BIG* res, uint64_t res_size,        // res
 31                         const VEC_ZNX_DFT* a_dft, uint64_t a_size,  // a
 32                         uint8_t* tmp                                // scratch space
 33) {
 34  return module->func.vec_znx_idft(module, res, res_size, a_dft, a_size, tmp);
 35}
 36
 37EXPORT uint64_t vec_znx_idft_tmp_bytes(const MODULE* module, uint64_t nn) { return module->func.vec_znx_idft_tmp_bytes(module, nn); }
 38
 39EXPORT void vec_znx_idft_tmp_a(const MODULE* module,                 // N
 40                               VEC_ZNX_BIG* res, uint64_t res_size,  // res
 41                               VEC_ZNX_DFT* a_dft, uint64_t a_size   // a is overwritten
 42) {
 43  return module->func.vec_znx_idft_tmp_a(module, res, res_size, a_dft, a_size);
 44}
 45
 46EXPORT uint64_t bytes_of_vec_znx_dft(const MODULE* module,  // N
 47                                     uint64_t size) {
 48  return module->func.bytes_of_vec_znx_dft(module, size);
 49}
 50
 51// fft64 backend
 52EXPORT uint64_t fft64_bytes_of_vec_znx_dft(const MODULE* module,  // N
 53                                           uint64_t size) {
 54  return module->nn * size * sizeof(double);
 55}
 56
 57EXPORT VEC_ZNX_DFT* new_vec_znx_dft(const MODULE* module,  // N
 58                                    uint64_t size) {
 59  return spqlios_alloc(bytes_of_vec_znx_dft(module, size));
 60}
 61
 62EXPORT void delete_vec_znx_dft(VEC_ZNX_DFT* res) { spqlios_free(res); }
 63
 64EXPORT void fft64_vec_znx_dft(const MODULE* module,                             // N
 65                              VEC_ZNX_DFT* res, uint64_t res_size,              // res
 66                              const int64_t* a, uint64_t a_size, uint64_t a_sl  // a
 67) {
 68  const uint64_t smin = res_size < a_size ? res_size : a_size;
 69  const uint64_t nn = module->nn;
 70
 71  for (uint64_t i = 0; i < smin; i++) {
 72    reim_from_znx64(module->mod.fft64.p_conv, ((double*)res) + i * nn, a + i * a_sl);
 73    reim_fft(module->mod.fft64.p_fft, ((double*)res) + i * nn);
 74  }
 75
 76  // fill up remaining part with 0's
 77  double* const dres = (double*)res;
 78  memset(dres + smin * nn, 0, (res_size - smin) * nn * sizeof(double));
 79}
 80
 81EXPORT void fft64_vec_dft_add(const MODULE* module,                   // N
 82                              VEC_ZNX_DFT* res, uint64_t res_size,    // res
 83                              const VEC_ZNX_DFT* a, uint64_t a_size,  // a
 84                              const VEC_ZNX_DFT* b, uint64_t b_size   // b
 85) {
 86  const uint64_t smin0 = a_size < b_size ? a_size : b_size;
 87  const uint64_t smin = res_size < smin0 ? res_size : smin0;
 88  const uint64_t nn = module->nn;
 89
 90  for (uint64_t i = 0; i < smin; i++) {
 91    reim_fftvec_add(module->mod.fft64.add_fft, ((double*)res) + i * nn, ((double*)a) + i * nn, ((double*)b) + i * nn);
 92  }
 93
 94  // fill remain `res` part with 0's
 95  double* const dres = (double*)res;
 96  memset(dres + smin * nn, 0, (res_size - smin) * nn * sizeof(double));
 97}
 98
 99EXPORT void fft64_vec_dft_sub(const MODULE* module,                   // N
100                              VEC_ZNX_DFT* res, uint64_t res_size,    // res
101                              const VEC_ZNX_DFT* a, uint64_t a_size,  // a
102                              const VEC_ZNX_DFT* b, uint64_t b_size   // b
103) {
104  const uint64_t smin0 = a_size < b_size ? a_size : b_size;
105  const uint64_t smin = res_size < smin0 ? res_size : smin0;
106  const uint64_t nn = module->nn;
107
108  for (uint64_t i = 0; i < smin; i++) {
109    reim_fftvec_sub(module->mod.fft64.sub_fft, ((double*)res) + i * nn, ((double*)a) + i * nn, ((double*)b) + i * nn);
110  }
111
112  // fill remain `res` part with 0's
113  double* const dres = (double*)res;
114  memset(dres + smin * nn, 0, (res_size - smin) * nn * sizeof(double));
115}
116
117EXPORT void fft64_vec_znx_idft(const MODULE* module,                       // N
118                               VEC_ZNX_BIG* res, uint64_t res_size,        // res
119                               const VEC_ZNX_DFT* a_dft, uint64_t a_size,  // a
120                               uint8_t* tmp                                // unused
121) {
122  const uint64_t nn = module->nn;
123  const uint64_t smin = res_size < a_size ? res_size : a_size;
124  if ((double*)res != (double*)a_dft) {
125    memcpy(res, a_dft, smin * nn * sizeof(double));
126  }
127
128  for (uint64_t i = 0; i < smin; i++) {
129    reim_ifft(module->mod.fft64.p_ifft, ((double*)res) + i * nn);
130    reim_to_znx64(module->mod.fft64.p_reim_to_znx, ((int64_t*)res) + i * nn, ((int64_t*)res) + i * nn);
131  }
132
133  // fill up remaining part with 0's
134  int64_t* const dres = (int64_t*)res;
135  memset(dres + smin * nn, 0, (res_size - smin) * nn * sizeof(double));
136}
137
138EXPORT uint64_t fft64_vec_znx_idft_tmp_bytes(const MODULE* module, uint64_t nn) { return 0; }
139
140EXPORT void fft64_vec_znx_idft_tmp_a(const MODULE* module,                 // N
141                                     VEC_ZNX_BIG* res, uint64_t res_size,  // res
142                                     VEC_ZNX_DFT* a_dft, uint64_t a_size   // a is overwritten
143) {
144  const uint64_t nn = module->nn;
145  const uint64_t smin = res_size < a_size ? res_size : a_size;
146
147  int64_t* const tres = (int64_t*)res;
148  double* const ta = (double*)a_dft;
149  for (uint64_t i = 0; i < smin; i++) {
150    reim_ifft(module->mod.fft64.p_ifft, ta + i * nn);
151    reim_to_znx64(module->mod.fft64.p_reim_to_znx, tres + i * nn, ta + i * nn);
152  }
153
154  // fill up remaining part with 0's
155  memset(tres + smin * nn, 0, (res_size - smin) * nn * sizeof(double));
156}
157
158// ntt120 backend
159
160EXPORT void ntt120_vec_znx_dft_avx(const MODULE* module,                             // N
161                                   VEC_ZNX_DFT* res, uint64_t res_size,              // res
162                                   const int64_t* a, uint64_t a_size, uint64_t a_sl  // a
163) {
164  const uint64_t nn = module->nn;
165  const uint64_t smin = res_size < a_size ? res_size : a_size;
166
167  int64_t* tres = (int64_t*)res;
168  for (uint64_t i = 0; i < smin; i++) {
169    q120_b_from_znx64_simple(nn, (q120b*)(tres + i * nn * 4), a + i * a_sl);
170    q120_ntt_bb_avx2(module->mod.q120.p_ntt, (q120b*)(tres + i * nn * 4));
171  }
172
173  // fill up remaining part with 0's
174  memset(tres + smin * nn * 4, 0, (res_size - smin) * nn * 4 * sizeof(int64_t));
175}
176
177EXPORT void ntt120_vec_znx_idft_avx(const MODULE* module,                       // N
178                                    VEC_ZNX_BIG* res, uint64_t res_size,        // res
179                                    const VEC_ZNX_DFT* a_dft, uint64_t a_size,  // a
180                                    uint8_t* tmp) {
181  const uint64_t nn = module->nn;
182  const uint64_t smin = res_size < a_size ? res_size : a_size;
183
184  __int128_t* const tres = (__int128_t*)res;
185  const int64_t* const ta = (int64_t*)a_dft;
186  for (uint64_t i = 0; i < smin; i++) {
187    memcpy(tmp, ta + i * nn * 4, nn * 4 * sizeof(uint64_t));
188    q120_intt_bb_avx2(module->mod.q120.p_intt, (q120b*)tmp);
189    q120_b_to_znx128_simple(nn, tres + i * nn, (q120b*)tmp);
190  }
191
192  // fill up remaining part with 0's
193  memset(tres + smin * nn, 0, (res_size - smin) * nn * sizeof(*tres));
194}
195
196EXPORT uint64_t ntt120_vec_znx_idft_tmp_bytes_avx(const MODULE* module, uint64_t nn) { return nn * 4 * sizeof(uint64_t); }
197
198EXPORT void ntt120_vec_znx_idft_tmp_a_avx(const MODULE* module,                 // N
199                                          VEC_ZNX_BIG* res, uint64_t res_size,  // res
200                                          VEC_ZNX_DFT* a_dft, uint64_t a_size   // a is overwritten
201) {
202  const uint64_t nn = module->nn;
203  const uint64_t smin = res_size < a_size ? res_size : a_size;
204
205  __int128_t* const tres = (__int128_t*)res;
206  int64_t* const ta = (int64_t*)a_dft;
207  for (uint64_t i = 0; i < smin; i++) {
208    q120_intt_bb_avx2(module->mod.q120.p_intt, (q120b*)(ta + i * nn * 4));
209    q120_b_to_znx128_simple(nn, tres + i * nn, (q120b*)(ta + i * nn * 4));
210  }
211
212  // fill up remaining part with 0's
213  memset(tres + smin * nn, 0, (res_size - smin) * nn * sizeof(*tres));
214}