arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/spqlios/lib/test/spqlios_vmp_product_test.cpp
spqlios/lib/test/spqlios_vmp_product_test.cppRaw
  1#include <gtest/gtest.h>
  2
  3#include "../spqlios/arithmetic/vec_znx_arithmetic_private.h"
  4#include "testlib/fft64_layouts.h"
  5#include "testlib/polynomial_vector.h"
  6
  7static void test_vmp_prepare_contiguous(VMP_PREPARE_CONTIGUOUS_F* prepare_contiguous,
  8                                        VMP_PREPARE_CONTIGUOUS_TMP_BYTES_F* tmp_bytes) {
  9  // tests when n < 8
 10  for (uint64_t nn : {2, 4}) {
 11    MODULE* module = new_module_info(nn, FFT64);
 12    for (uint64_t nrows : {1, 2, 5}) {
 13      for (uint64_t ncols : {2, 6, 7}) {
 14        znx_vec_i64_layout mat(nn, nrows * ncols, nn);
 15        fft64_vmp_pmat_layout pmat(nn, nrows, ncols);
 16        mat.fill_random(30);
 17        std::vector<uint8_t> tmp_space(fft64_vmp_prepare_contiguous_tmp_bytes(module, nrows, ncols));
 18        thash hash_before = mat.content_hash();
 19        prepare_contiguous(module, pmat.data, mat.data(), nrows, ncols, tmp_space.data());
 20        ASSERT_EQ(mat.content_hash(), hash_before);
 21        for (uint64_t row = 0; row < nrows; ++row) {
 22          for (uint64_t col = 0; col < ncols; ++col) {
 23            const double* pmatv = (double*)pmat.data + (col * nrows + row) * nn;
 24            reim_fft64vec tmp = simple_fft64(mat.get_copy(row * ncols + col));
 25            const double* tmpv = tmp.data();
 26            for (uint64_t i = 0; i < nn; ++i) {
 27              ASSERT_LE(abs(pmatv[i] - tmpv[i]), 1e-10);
 28            }
 29          }
 30        }
 31      }
 32    }
 33    delete_module_info(module);
 34  }
 35  // tests when n >= 8
 36  for (uint64_t nn : {8, 32}) {
 37    MODULE* module = new_module_info(nn, FFT64);
 38    uint64_t nblk = nn / 8;
 39    for (uint64_t nrows : {1, 2, 5}) {
 40      for (uint64_t ncols : {2, 6, 7}) {
 41        znx_vec_i64_layout mat(nn, nrows * ncols, nn);
 42        fft64_vmp_pmat_layout pmat(nn, nrows, ncols);
 43        mat.fill_random(30);
 44        std::vector<uint8_t> tmp_space(tmp_bytes(module, nrows, ncols));
 45        thash hash_before = mat.content_hash();
 46        prepare_contiguous(module, pmat.data, mat.data(), nrows, ncols, tmp_space.data());
 47        ASSERT_EQ(mat.content_hash(), hash_before);
 48        for (uint64_t row = 0; row < nrows; ++row) {
 49          for (uint64_t col = 0; col < ncols; ++col) {
 50            reim_fft64vec tmp = simple_fft64(mat.get_copy(row * ncols + col));
 51            for (uint64_t blk = 0; blk < nblk; ++blk) {
 52              reim4_elem expect = tmp.get_blk(blk);
 53              reim4_elem actual = pmat.get(row, col, blk);
 54              ASSERT_LE(infty_dist(actual, expect), 1e-10);
 55            }
 56          }
 57        }
 58      }
 59    }
 60    delete_module_info(module);
 61  }
 62}
 63
 64TEST(vec_znx, vmp_prepare_contiguous) {
 65  test_vmp_prepare_contiguous(vmp_prepare_contiguous, vmp_prepare_contiguous_tmp_bytes);
 66}
 67TEST(vec_znx, fft64_vmp_prepare_contiguous_ref) {
 68  test_vmp_prepare_contiguous(fft64_vmp_prepare_contiguous_ref, fft64_vmp_prepare_contiguous_tmp_bytes);
 69}
 70#ifdef __x86_64__
 71TEST(vec_znx, fft64_vmp_prepare_contiguous_avx) {
 72  test_vmp_prepare_contiguous(fft64_vmp_prepare_contiguous_avx, fft64_vmp_prepare_contiguous_tmp_bytes);
 73}
 74#endif
 75
 76static void test_vmp_apply(VMP_APPLY_DFT_TO_DFT_F* apply, VMP_APPLY_DFT_TO_DFT_TMP_BYTES_F* tmp_bytes) {
 77  for (uint64_t nn : {2, 4, 8, 64}) {
 78    MODULE* module = new_module_info(nn, FFT64);
 79    for (uint64_t mat_nrows : {1, 4, 7}) {
 80      for (uint64_t mat_ncols : {1, 2, 5}) {
 81        for (uint64_t in_size : {1, 4, 7}) {
 82          for (uint64_t out_size : {1, 2, 5}) {
 83            fft64_vec_znx_dft_layout in(nn, in_size);
 84            fft64_vmp_pmat_layout pmat(nn, mat_nrows, mat_ncols);
 85            fft64_vec_znx_dft_layout out(nn, out_size);
 86            in.fill_random(0);
 87            pmat.fill_random(0);
 88            // naive computation of the product
 89            std::vector<reim_fft64vec> expect(out_size, reim_fft64vec(nn));
 90            for (uint64_t col = 0; col < out_size; ++col) {
 91              reim_fft64vec ex = reim_fft64vec::zero(nn);
 92              for (uint64_t row = 0; row < std::min(mat_nrows, in_size); ++row) {
 93                ex += pmat.get_zext(row, col) * in.get_copy_zext(row);
 94              }
 95              expect[col] = ex;
 96            }
 97            // apply the product
 98            std::vector<uint8_t> tmp(tmp_bytes(module, out_size, in_size, mat_nrows, mat_ncols));
 99            apply(module, out.data, out_size, in.data, in_size, pmat.data, mat_nrows, mat_ncols, tmp.data());
100            // check that the output is close from the expectation
101            for (uint64_t col = 0; col < out_size; ++col) {
102              reim_fft64vec actual = out.get_copy_zext(col);
103              ASSERT_LE(infty_dist(actual, expect[col]), 1e-10);
104            }
105          }
106        }
107      }
108    }
109    delete_module_info(module);
110  }
111}
112
113TEST(vec_znx, vmp_apply_to_dft) { test_vmp_apply(vmp_apply_dft_to_dft, vmp_apply_dft_to_dft_tmp_bytes); }
114TEST(vec_znx, fft64_vmp_apply_dft_to_dft_ref) {
115  test_vmp_apply(fft64_vmp_apply_dft_to_dft_ref, fft64_vmp_apply_dft_to_dft_tmp_bytes);
116}
117#ifdef __x86_64__
118TEST(vec_znx, fft64_vmp_apply_dft_to_dft_avx) {
119  test_vmp_apply(fft64_vmp_apply_dft_to_dft_avx, fft64_vmp_apply_dft_to_dft_tmp_bytes);
120}
121#endif