arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/spqlios/lib/test/spqlios_vec_rnx_conversions_test.cpp
spqlios/lib/test/spqlios_vec_rnx_conversions_test.cppRaw
  1#include <gtest/gtest.h>
  2#include <spqlios/arithmetic/vec_rnx_arithmetic_private.h>
  3
  4#include "testlib/test_commons.h"
  5
  6template <typename SRC_T, typename DST_T>
  7static void test_conv(void (*conv_f)(const MOD_RNX*,                                   //
  8                                     DST_T* res, uint64_t res_size, uint64_t res_sl,   //
  9                                     const SRC_T* a, uint64_t a_size, uint64_t a_sl),  //
 10                      DST_T (*ideal_conv_f)(SRC_T x),                                  //
 11                      SRC_T (*random_f)()                                              //
 12) {
 13  for (uint64_t nn : {2, 4, 16, 64}) {
 14    MOD_RNX* module = new_rnx_module_info(nn, FFT64);
 15    for (uint64_t a_size : {0, 1, 2, 5}) {
 16      for (uint64_t res_size : {0, 1, 3, 5}) {
 17        for (uint64_t trials = 0; trials < 20; ++trials) {
 18          uint64_t a_sl = nn + uniform_u64_bits(2);
 19          uint64_t res_sl = nn + uniform_u64_bits(2);
 20          std::vector<SRC_T> a(a_sl * a_size);
 21          std::vector<DST_T> res(res_sl * res_size);
 22          uint64_t msize = std::min(a_size, res_size);
 23          for (uint64_t i = 0; i < a_size; ++i) {
 24            for (uint64_t j = 0; j < nn; ++j) {
 25              a[i * a_sl + j] = random_f();
 26            }
 27          }
 28          conv_f(module, res.data(), res_size, res_sl, a.data(), a_size, a_sl);
 29          for (uint64_t i = 0; i < msize; ++i) {
 30            for (uint64_t j = 0; j < nn; ++j) {
 31              SRC_T aij = a[i * a_sl + j];
 32              DST_T expect = ideal_conv_f(aij);
 33              DST_T actual = res[i * res_sl + j];
 34              ASSERT_EQ(expect, actual);
 35            }
 36          }
 37          for (uint64_t i = msize; i < res_size; ++i) {
 38            DST_T expect = 0;
 39            for (uint64_t j = 0; j < nn; ++j) {
 40              SRC_T actual = res[i * res_sl + j];
 41              ASSERT_EQ(expect, actual);
 42            }
 43          }
 44        }
 45      }
 46    }
 47    delete_rnx_module_info(module);
 48  }
 49}
 50
 51static int32_t ideal_dbl_to_tn32(double a) {
 52  double _2p32 = INT64_C(1) << 32;
 53  double a_mod_1 = a - rint(a);
 54  int64_t t = rint(a_mod_1 * _2p32);
 55  return int32_t(t);
 56}
 57
 58static double random_f64_10() { return uniform_f64_bounds(-10, 10); }
 59
 60static void test_vec_rnx_to_tnx32(VEC_RNX_TO_TNX32_F vec_rnx_to_tnx32_f) {
 61  test_conv(vec_rnx_to_tnx32_f, ideal_dbl_to_tn32, random_f64_10);
 62}
 63
 64TEST(vec_rnx_arithmetic, vec_rnx_to_tnx32) { test_vec_rnx_to_tnx32(vec_rnx_to_tnx32); }
 65TEST(vec_rnx_arithmetic, vec_rnx_to_tnx32_ref) { test_vec_rnx_to_tnx32(vec_rnx_to_tnx32_ref); }
 66
 67static double ideal_tn32_to_dbl(int32_t a) {
 68  const double _2p32 = INT64_C(1) << 32;
 69  return double(a) / _2p32;
 70}
 71
 72static int32_t random_t32() { return uniform_i64_bits(32); }
 73
 74static void test_vec_rnx_from_tnx32(VEC_RNX_FROM_TNX32_F vec_rnx_from_tnx32_f) {
 75  test_conv(vec_rnx_from_tnx32_f, ideal_tn32_to_dbl, random_t32);
 76}
 77
 78TEST(vec_rnx_arithmetic, vec_rnx_from_tnx32) { test_vec_rnx_from_tnx32(vec_rnx_from_tnx32); }
 79TEST(vec_rnx_arithmetic, vec_rnx_from_tnx32_ref) { test_vec_rnx_from_tnx32(vec_rnx_from_tnx32_ref); }
 80
 81static int32_t ideal_dbl_round_to_i32(double a) { return int32_t(rint(a)); }
 82
 83static double random_dbl_explaw_18() { return uniform_f64_bounds(-1., 1.) * pow(2., uniform_u64_bits(6) % 19); }
 84
 85static void test_vec_rnx_to_znx32(VEC_RNX_TO_ZNX32_F vec_rnx_to_znx32_f) {
 86  test_conv(vec_rnx_to_znx32_f, ideal_dbl_round_to_i32, random_dbl_explaw_18);
 87}
 88
 89TEST(zn_arithmetic, vec_rnx_to_znx32) { test_vec_rnx_to_znx32(vec_rnx_to_znx32); }
 90TEST(zn_arithmetic, vec_rnx_to_znx32_ref) { test_vec_rnx_to_znx32(vec_rnx_to_znx32_ref); }
 91
 92static double ideal_i32_to_dbl(int32_t a) { return double(a); }
 93
 94static int32_t random_i32_explaw_18() { return uniform_i64_bits(uniform_u64_bits(6) % 19); }
 95
 96static void test_vec_rnx_from_znx32(VEC_RNX_FROM_ZNX32_F vec_rnx_from_znx32_f) {
 97  test_conv(vec_rnx_from_znx32_f, ideal_i32_to_dbl, random_i32_explaw_18);
 98}
 99
100TEST(zn_arithmetic, vec_rnx_from_znx32) { test_vec_rnx_from_znx32(vec_rnx_from_znx32); }
101TEST(zn_arithmetic, vec_rnx_from_znx32_ref) { test_vec_rnx_from_znx32(vec_rnx_from_znx32_ref); }
102
103static double ideal_dbl_to_tndbl(double a) { return a - rint(a); }
104
105static void test_vec_rnx_to_tnxdbl(VEC_RNX_TO_TNXDBL_F vec_rnx_to_tnxdbl_f) {
106  test_conv(vec_rnx_to_tnxdbl_f, ideal_dbl_to_tndbl, random_f64_10);
107}
108
109TEST(zn_arithmetic, vec_rnx_to_tnxdbl) { test_vec_rnx_to_tnxdbl(vec_rnx_to_tnxdbl); }
110TEST(zn_arithmetic, vec_rnx_to_tnxdbl_ref) { test_vec_rnx_to_tnxdbl(vec_rnx_to_tnxdbl_ref); }
111
112#if 0
113static int64_t ideal_dbl_round_to_i64(double a) { return rint(a); }
114
115static double random_dbl_explaw_50() { return uniform_f64_bounds(-1., 1.) * pow(2., uniform_u64_bits(7) % 51); }
116
117static void test_dbl_round_to_i64(DBL_ROUND_TO_I64_F dbl_round_to_i64_f) {
118  test_conv(dbl_round_to_i64_f, ideal_dbl_round_to_i64, random_dbl_explaw_50);
119}
120
121TEST(zn_arithmetic, dbl_round_to_i64) { test_dbl_round_to_i64(dbl_round_to_i64); }
122TEST(zn_arithmetic, dbl_round_to_i64_ref) { test_dbl_round_to_i64(dbl_round_to_i64_ref); }
123
124static double ideal_i64_to_dbl(int64_t a) { return double(a); }
125
126static int64_t random_i64_explaw_50() { return uniform_i64_bits(uniform_u64_bits(7) % 51); }
127
128static void test_i64_to_dbl(I64_TO_DBL_F i64_to_dbl_f) {
129  test_conv(i64_to_dbl_f, ideal_i64_to_dbl, random_i64_explaw_50);
130}
131
132TEST(zn_arithmetic, i64_to_dbl) { test_i64_to_dbl(i64_to_dbl); }
133TEST(zn_arithmetic, i64_to_dbl_ref) { test_i64_to_dbl(i64_to_dbl_ref); }
134#endif