arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/spqlios/lib/test/spqlios_vec_rnx_ppol_test.cpp
spqlios/lib/test/spqlios_vec_rnx_ppol_test.cppRaw
 1#include <gtest/gtest.h>
 2
 3#include "spqlios/arithmetic/vec_rnx_arithmetic_private.h"
 4#include "spqlios/reim/reim_fft.h"
 5#include "test/testlib/vec_rnx_layout.h"
 6
 7static void test_vec_rnx_svp_prepare(RNX_SVP_PREPARE_F* rnx_svp_prepare, BYTES_OF_RNX_SVP_PPOL_F* tmp_bytes) {
 8  for (uint64_t n : {2, 4, 8, 64}) {
 9    MOD_RNX* mod = new_rnx_module_info(n, FFT64);
10    const double invm = 1. / mod->m;
11
12    rnx_f64 in = rnx_f64::random_log2bound(n, 40);
13    rnx_f64 in_divide_by_m = rnx_f64::zero(n);
14    for (uint64_t i = 0; i < n; ++i) {
15      in_divide_by_m.set_coeff(i, in.get_coeff(i) * invm);
16    }
17    fft64_rnx_svp_ppol_layout out(n);
18    reim_fft64vec expect = simple_fft64(in_divide_by_m);
19    rnx_svp_prepare(mod, out.data, in.data());
20    const double* ed = (double*)expect.data();
21    const double* ac = (double*)out.data;
22    for (uint64_t i = 0; i < n; ++i) {
23      ASSERT_LE(abs(ed[i] - ac[i]), 1e-10) << i << n;
24    }
25    delete_rnx_module_info(mod);
26  }
27}
28TEST(vec_rnx, vec_rnx_svp_prepare) { test_vec_rnx_svp_prepare(rnx_svp_prepare, bytes_of_rnx_svp_ppol); }
29TEST(vec_rnx, vec_rnx_svp_prepare_ref) {
30  test_vec_rnx_svp_prepare(fft64_rnx_svp_prepare_ref, fft64_bytes_of_rnx_svp_ppol);
31}
32
33static void test_vec_rnx_svp_apply(RNX_SVP_APPLY_F* apply) {
34  for (uint64_t n : {2, 4, 8, 64, 128}) {
35    MOD_RNX* mod = new_rnx_module_info(n, FFT64);
36
37    // poly 1 to multiply - create and prepare
38    fft64_rnx_svp_ppol_layout ppol(n);
39    ppol.fill_random(1.);
40    for (uint64_t sa : {3, 5, 8}) {
41      for (uint64_t sr : {3, 5, 8}) {
42        uint64_t a_sl = n + uniform_u64_bits(2);
43        uint64_t r_sl = n + uniform_u64_bits(2);
44        // poly 2 to multiply
45        rnx_vec_f64_layout a(n, sa, a_sl);
46        a.fill_random(19);
47
48        // original operation result
49        rnx_vec_f64_layout res(n, sr, r_sl);
50        thash hash_a_before = a.content_hash();
51        thash hash_ppol_before = ppol.content_hash();
52        apply(mod, res.data(), sr, r_sl, ppol.data, a.data(), sa, a_sl);
53        ASSERT_EQ(a.content_hash(), hash_a_before);
54        ASSERT_EQ(ppol.content_hash(), hash_ppol_before);
55        // create expected value
56        reim_fft64vec ppo = ppol.get_copy();
57        std::vector<rnx_f64> expect(sr);
58        for (uint64_t i = 0; i < sr; ++i) {
59          expect[i] = simple_ifft64(ppo * simple_fft64(a.get_copy_zext(i)));
60        }
61        // this is the largest precision we can safely expect
62        double prec_expect = n * pow(2., 19 - 50);
63        for (uint64_t i = 0; i < sr; ++i) {
64          rnx_f64 actual = res.get_copy_zext(i);
65          ASSERT_LE(infty_dist(actual, expect[i]), prec_expect);
66        }
67      }
68    }
69    delete_rnx_module_info(mod);
70  }
71}
72TEST(vec_rnx, vec_rnx_svp_apply) { test_vec_rnx_svp_apply(rnx_svp_apply); }
73TEST(vec_rnx, vec_rnx_svp_apply_ref) { test_vec_rnx_svp_apply(fft64_rnx_svp_apply_ref); }