poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/zn_approxdecomp_ref.c
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/zn_approxdecomp_ref.cRaw
1#include <memory.h>
2
3#include "zn_arithmetic_private.h"
4
5EXPORT TNDBL_APPROXDECOMP_GADGET* new_tndbl_approxdecomp_gadget(const MOD_Z* module, //
6 uint64_t k, uint64_t ell) {
7 if (k * ell > 50) {
8 return spqlios_error("approx decomposition requested is too precise for doubles");
9 }
10 if (k < 1) {
11 return spqlios_error("approx decomposition supports k>=1");
12 }
13 TNDBL_APPROXDECOMP_GADGET* res = malloc(sizeof(TNDBL_APPROXDECOMP_GADGET));
14 memset(res, 0, sizeof(TNDBL_APPROXDECOMP_GADGET));
15 res->k = k;
16 res->ell = ell;
17 double add_cst = INT64_C(3) << (51 - k * ell);
18 for (uint64_t i = 0; i < ell; ++i) {
19 add_cst += pow(2., -(double)(i * k + 1));
20 }
21 res->add_cst = add_cst;
22 res->and_mask = (UINT64_C(1) << k) - 1;
23 res->sub_cst = UINT64_C(1) << (k - 1);
24 for (uint64_t i = 0; i < ell; ++i) res->rshifts[i] = (ell - 1 - i) * k;
25 return res;
26}
27EXPORT void delete_tndbl_approxdecomp_gadget(TNDBL_APPROXDECOMP_GADGET* ptr) { free(ptr); }
28
29EXPORT int default_init_tndbl_approxdecomp_gadget(const MOD_Z* module, //
30 TNDBL_APPROXDECOMP_GADGET* res, //
31 uint64_t k, uint64_t ell) {
32 return 0;
33}
34
35typedef union {
36 double dv;
37 uint64_t uv;
38} du_t;
39
40#define IMPL_ixx_approxdecomp_from_tndbl_ref(ITYPE) \
41 if (res_size != a_size * gadget->ell) NOT_IMPLEMENTED(); \
42 const uint64_t ell = gadget->ell; \
43 const double add_cst = gadget->add_cst; \
44 const uint8_t* const rshifts = gadget->rshifts; \
45 const ITYPE and_mask = gadget->and_mask; \
46 const ITYPE sub_cst = gadget->sub_cst; \
47 ITYPE* rr = res; \
48 const double* aa = a; \
49 const double* aaend = a + a_size; \
50 while (aa < aaend) { \
51 du_t t = {.dv = *aa + add_cst}; \
52 for (uint64_t i = 0; i < ell; ++i) { \
53 ITYPE v = (ITYPE)(t.uv >> rshifts[i]); \
54 *rr = (v & and_mask) - sub_cst; \
55 ++rr; \
56 } \
57 ++aa; \
58 }
59
60/** @brief sets res = gadget_decompose(a) (int8_t* output) */
61EXPORT void default_i8_approxdecomp_from_tndbl_ref(const MOD_Z* module, // N
62 const TNDBL_APPROXDECOMP_GADGET* gadget, // gadget
63 int8_t* res, uint64_t res_size, // res (in general, size ell.a_size)
64 const double* a, uint64_t a_size //
65){IMPL_ixx_approxdecomp_from_tndbl_ref(int8_t)}
66
67/** @brief sets res = gadget_decompose(a) (int16_t* output) */
68EXPORT void default_i16_approxdecomp_from_tndbl_ref(const MOD_Z* module, // N
69 const TNDBL_APPROXDECOMP_GADGET* gadget, // gadget
70 int16_t* res, uint64_t res_size, // res
71 const double* a, uint64_t a_size // a
72){IMPL_ixx_approxdecomp_from_tndbl_ref(int16_t)}
73
74/** @brief sets res = gadget_decompose(a) (int32_t* output) */
75EXPORT void default_i32_approxdecomp_from_tndbl_ref(const MOD_Z* module, // N
76 const TNDBL_APPROXDECOMP_GADGET* gadget, // gadget
77 int32_t* res, uint64_t res_size, // res
78 const double* a, uint64_t a_size // a
79) {
80 IMPL_ixx_approxdecomp_from_tndbl_ref(int32_t)
81}