poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/zn_conversions_ref.c
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/zn_conversions_ref.cRaw
1#include <memory.h>
2
3#include "zn_arithmetic_private.h"
4
5typedef union {
6 double dv;
7 int64_t s64v;
8 int32_t s32v;
9 uint64_t u64v;
10 uint32_t u32v;
11} di_t;
12
13/** reduction mod 1, output in torus32 space */
14EXPORT void dbl_to_tn32_ref(const MOD_Z* module, //
15 int32_t* res, uint64_t res_size, // res
16 const double* a, uint64_t a_size // a
17) {
18 static const double ADD_CST = 0.5 + (double)(INT64_C(3) << (51 - 32));
19 static const int32_t XOR_CST = (INT32_C(1) << 31);
20 const uint64_t msize = res_size < a_size ? res_size : a_size;
21 for (uint64_t i = 0; i < msize; ++i) {
22 di_t t = {.dv = a[i] + ADD_CST};
23 res[i] = t.s32v ^ XOR_CST;
24 }
25 memset(res + msize, 0, (res_size - msize) * sizeof(int32_t));
26}
27
28/** real centerlift mod 1, output in double space */
29EXPORT void tn32_to_dbl_ref(const MOD_Z* module, //
30 double* res, uint64_t res_size, // res
31 const int32_t* a, uint64_t a_size // a
32) {
33 static const uint32_t XOR_CST = (UINT32_C(1) << 31);
34 static const di_t OR_CST = {.dv = (double)(INT64_C(1) << (52 - 32))};
35 static const double SUB_CST = 0.5 + (double)(INT64_C(1) << (52 - 32));
36 const uint64_t msize = res_size < a_size ? res_size : a_size;
37 for (uint64_t i = 0; i < msize; ++i) {
38 uint32_t ai = a[i] ^ XOR_CST;
39 di_t t = {.u64v = OR_CST.u64v | (uint64_t)ai};
40 res[i] = t.dv - SUB_CST;
41 }
42 memset(res + msize, 0, (res_size - msize) * sizeof(double));
43}
44
45/** round to the nearest int, output in i32 space */
46EXPORT void dbl_round_to_i32_ref(const MOD_Z* module, //
47 int32_t* res, uint64_t res_size, // res
48 const double* a, uint64_t a_size // a
49) {
50 static const double ADD_CST = (double)((INT64_C(3) << (51)) + (INT64_C(1) << (31)));
51 static const int32_t XOR_CST = INT32_C(1) << 31;
52 const uint64_t msize = res_size < a_size ? res_size : a_size;
53 for (uint64_t i = 0; i < msize; ++i) {
54 di_t t = {.dv = a[i] + ADD_CST};
55 res[i] = t.s32v ^ XOR_CST;
56 }
57 memset(res + msize, 0, (res_size - msize) * sizeof(int32_t));
58}
59
60/** small int (int32 space) to double */
61EXPORT void i32_to_dbl_ref(const MOD_Z* module, //
62 double* res, uint64_t res_size, // res
63 const int32_t* a, uint64_t a_size // a
64) {
65 static const uint32_t XOR_CST = (UINT32_C(1) << 31);
66 static const di_t OR_CST = {.dv = (double)(INT64_C(1) << 52)};
67 static const double SUB_CST = (double)((INT64_C(1) << 52) + (INT64_C(1) << 31));
68 const uint64_t msize = res_size < a_size ? res_size : a_size;
69 for (uint64_t i = 0; i < msize; ++i) {
70 uint32_t ai = a[i] ^ XOR_CST;
71 di_t t = {.u64v = OR_CST.u64v | (uint64_t)ai};
72 res[i] = t.dv - SUB_CST;
73 }
74 memset(res + msize, 0, (res_size - msize) * sizeof(double));
75}
76
77/** round to the nearest int, output in int64 space */
78EXPORT void dbl_round_to_i64_ref(const MOD_Z* module, //
79 int64_t* res, uint64_t res_size, // res
80 const double* a, uint64_t a_size // a
81) {
82 static const double ADD_CST = (double)(INT64_C(3) << (51));
83 static const int64_t AND_CST = (INT64_C(1) << 52) - 1;
84 static const int64_t SUB_CST = INT64_C(1) << 51;
85 const uint64_t msize = res_size < a_size ? res_size : a_size;
86 for (uint64_t i = 0; i < msize; ++i) {
87 di_t t = {.dv = a[i] + ADD_CST};
88 res[i] = (t.s64v & AND_CST) - SUB_CST;
89 }
90 memset(res + msize, 0, (res_size - msize) * sizeof(int64_t));
91}
92
93/** small int (int64 space) to double */
94EXPORT void i64_to_dbl_ref(const MOD_Z* module, //
95 double* res, uint64_t res_size, // res
96 const int64_t* a, uint64_t a_size // a
97) {
98 static const uint64_t ADD_CST = UINT64_C(1) << 51;
99 static const uint64_t AND_CST = (UINT64_C(1) << 52) - 1;
100 static const di_t OR_CST = {.dv = (INT64_C(1) << 52)};
101 static const double SUB_CST = INT64_C(3) << 51;
102 const uint64_t msize = res_size < a_size ? res_size : a_size;
103 for (uint64_t i = 0; i < msize; ++i) {
104 di_t t = {.u64v = ((a[i] + ADD_CST) & AND_CST) | OR_CST.u64v};
105 res[i] = t.dv - SUB_CST;
106 }
107 memset(res + msize, 0, (res_size - msize) * sizeof(double));
108}