arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/zn_vmp_ref.c
poulpy-backend/src/cpu_spqlios/spqlios-arithmetic/spqlios/arithmetic/zn_vmp_ref.cRaw
  1#include <memory.h>
  2
  3#include "zn_arithmetic_private.h"
  4
  5/** @brief size in bytes of a prepared matrix (for custom allocation) */
  6EXPORT uint64_t bytes_of_zn32_vmp_pmat(const MOD_Z* module,            // N
  7                                       uint64_t nrows, uint64_t ncols  // dimensions
  8) {
  9  return (nrows * ncols + 7) * sizeof(int32_t);
 10}
 11
 12/** @brief allocates a prepared matrix (release with delete_zn32_vmp_pmat) */
 13EXPORT ZN32_VMP_PMAT* new_zn32_vmp_pmat(const MOD_Z* module,  // N
 14                                        uint64_t nrows, uint64_t ncols) {
 15  return (ZN32_VMP_PMAT*)spqlios_alloc(bytes_of_zn32_vmp_pmat(module, nrows, ncols));
 16}
 17
 18/** @brief deletes a prepared matrix (release with free) */
 19EXPORT void delete_zn32_vmp_pmat(ZN32_VMP_PMAT* ptr) { spqlios_free(ptr); }
 20
 21/** @brief prepares a vmp matrix (contiguous row-major version) */
 22EXPORT void default_zn32_vmp_prepare_contiguous_ref(  //
 23    const MOD_Z* module,
 24    ZN32_VMP_PMAT* pmat,                                // output
 25    const int32_t* mat, uint64_t nrows, uint64_t ncols  // a
 26) {
 27  int32_t* const out = (int32_t*)pmat;
 28  const uint64_t nblk = ncols >> 5;
 29  const uint64_t ncols_rem = ncols & 31;
 30  const uint64_t final_elems = (8 - nrows * ncols) & 7;
 31  for (uint64_t blk = 0; blk < nblk; ++blk) {
 32    int32_t* outblk = out + blk * nrows * 32;
 33    const int32_t* srcblk = mat + blk * 32;
 34    for (uint64_t row = 0; row < nrows; ++row) {
 35      int32_t* dest = outblk + row * 32;
 36      const int32_t* src = srcblk + row * ncols;
 37      for (uint64_t i = 0; i < 32; ++i) {
 38        dest[i] = src[i];
 39      }
 40    }
 41  }
 42  // copy the last block if any
 43  if (ncols_rem) {
 44    int32_t* outblk = out + nblk * nrows * 32;
 45    const int32_t* srcblk = mat + nblk * 32;
 46    for (uint64_t row = 0; row < nrows; ++row) {
 47      int32_t* dest = outblk + row * ncols_rem;
 48      const int32_t* src = srcblk + row * ncols;
 49      for (uint64_t i = 0; i < ncols_rem; ++i) {
 50        dest[i] = src[i];
 51      }
 52    }
 53  }
 54  // zero-out the final elements that may be accessed
 55  if (final_elems) {
 56    int32_t* f = out + nrows * ncols;
 57    for (uint64_t i = 0; i < final_elems; ++i) {
 58      f[i] = 0;
 59    }
 60  }
 61}
 62
 63/** @brief prepares a vmp matrix (mat[row]+col*N points to the item) */
 64EXPORT void default_zn32_vmp_prepare_dblptr_ref(  //
 65    const MOD_Z* module,
 66    ZN32_VMP_PMAT* pmat,                                 // output
 67    const int32_t** mat, uint64_t nrows, uint64_t ncols  // a
 68) {
 69  for (uint64_t row_i = 0; row_i < nrows; ++row_i) {
 70    default_zn32_vmp_prepare_row_ref(module, pmat, mat[row_i], row_i, nrows, ncols);
 71  }
 72}
 73
 74/** @brief prepares the ith-row of a vmp matrix with nrows and ncols */
 75EXPORT void default_zn32_vmp_prepare_row_ref(  //
 76    const MOD_Z* module,
 77    ZN32_VMP_PMAT* pmat,                                                // output
 78    const int32_t* row, uint64_t row_i, uint64_t nrows, uint64_t ncols  // a
 79) {
 80  int32_t* const out = (int32_t*)pmat;
 81  const uint64_t nblk = ncols >> 5;
 82  const uint64_t ncols_rem = ncols & 31;
 83  const uint64_t final_elems = (row_i == nrows - 1) && (8 - nrows * ncols) & 7;
 84  for (uint64_t blk = 0; blk < nblk; ++blk) {
 85    int32_t* outblk = out + blk * nrows * 32;
 86    int32_t* dest = outblk + row_i * 32;
 87    const int32_t* src = row + blk * 32;
 88    for (uint64_t i = 0; i < 32; ++i) {
 89      dest[i] = src[i];
 90    }
 91  }
 92  // copy the last block if any
 93  if (ncols_rem) {
 94    int32_t* outblk = out + nblk * nrows * 32;
 95    int32_t* dest = outblk + row_i * ncols_rem;
 96    const int32_t* src = row + nblk * 32;
 97    for (uint64_t i = 0; i < ncols_rem; ++i) {
 98      dest[i] = src[i];
 99    }
100  }
101  // zero-out the final elements that may be accessed
102  if (final_elems) {
103    int32_t* f = out + nrows * ncols;
104    for (uint64_t i = 0; i < final_elems; ++i) {
105      f[i] = 0;
106    }
107  }
108}
109
110#if 0
111
112#define IMPL_zn32_vec_ixxx_matyyycols_ref(NCOLS) \
113  memset(res, 0, NCOLS * sizeof(int32_t));       \
114  for (uint64_t row = 0; row < nrows; ++row) {   \
115    int32_t ai = a[row];                         \
116    const int32_t* bb = b + row * b_sl;          \
117    for (uint64_t i = 0; i < NCOLS; ++i) {       \
118      res[i] += ai * bb[i];                      \
119    }                                            \
120  }
121
122#define IMPL_zn32_vec_ixxx_mat8cols_ref() IMPL_zn32_vec_ixxx_matyyycols_ref(8)
123#define IMPL_zn32_vec_ixxx_mat16cols_ref() IMPL_zn32_vec_ixxx_matyyycols_ref(16)
124#define IMPL_zn32_vec_ixxx_mat24cols_ref() IMPL_zn32_vec_ixxx_matyyycols_ref(24)
125#define IMPL_zn32_vec_ixxx_mat32cols_ref() IMPL_zn32_vec_ixxx_matyyycols_ref(32)
126
127void zn32_vec_i8_mat32cols_ref(uint64_t nrows, int32_t* res, const int8_t* a, const int32_t* b, uint64_t b_sl) {
128  IMPL_zn32_vec_ixxx_mat32cols_ref()
129}
130void zn32_vec_i16_mat32cols_ref(uint64_t nrows, int32_t* res, const int16_t* a, const int32_t* b, uint64_t b_sl) {
131  IMPL_zn32_vec_ixxx_mat32cols_ref()
132}
133
134void zn32_vec_i32_mat32cols_ref(uint64_t nrows, int32_t* res, const int32_t* a, const int32_t* b, uint64_t b_sl) {
135  IMPL_zn32_vec_ixxx_mat32cols_ref()
136}
137void zn32_vec_i32_mat24cols_ref(uint64_t nrows, int32_t* res, const int32_t* a, const int32_t* b, uint64_t b_sl) {
138  IMPL_zn32_vec_ixxx_mat24cols_ref()
139}
140void zn32_vec_i32_mat16cols_ref(uint64_t nrows, int32_t* res, const int32_t* a, const int32_t* b, uint64_t b_sl) {
141  IMPL_zn32_vec_ixxx_mat16cols_ref()
142}
143void zn32_vec_i32_mat8cols_ref(uint64_t nrows, int32_t* res, const int32_t* a, const int32_t* b, uint64_t b_sl) {
144  IMPL_zn32_vec_ixxx_mat8cols_ref()
145}
146typedef void (*zn32_vec_i32_mat8kcols_ref_f)(uint64_t nrows,                  //
147                                             int32_t* res,                    //
148                                             const int32_t* a,                //
149                                             const int32_t* b, uint64_t b_sl  //
150);
151zn32_vec_i32_mat8kcols_ref_f zn32_vec_i32_mat8kcols_ref[4] = {  //
152    zn32_vec_i32_mat8cols_ref, zn32_vec_i32_mat16cols_ref,      //
153    zn32_vec_i32_mat24cols_ref, zn32_vec_i32_mat32cols_ref};
154
155/** @brief applies a vmp product (int32_t* input) */
156EXPORT void default_zn32_vmp_apply_i32_ref(const MOD_Z* module,                //
157                                           int32_t* res, uint64_t res_size,    //
158                                           const int32_t* a, uint64_t a_size,  //
159                                           const ZN32_VMP_PMAT* pmat, uint64_t nrows, uint64_t ncols) {
160  const uint64_t rows = a_size < nrows ? a_size : nrows;
161  const uint64_t cols = res_size < ncols ? res_size : ncols;
162  const uint64_t ncolblk = cols >> 5;
163  const uint64_t ncolrem = cols & 31;
164  // copy the first full blocks
165  const uint32_t full_blk_size = nrows * 32;
166  const int32_t* mat = (int32_t*)pmat;
167  int32_t* rr = res;
168  for (uint64_t blk = 0;  //
169       blk < ncolblk;     //
170       ++blk, mat += full_blk_size, rr += 32) {
171    zn32_vec_i32_mat32cols_ref(rows, rr, a, mat, 32);
172  }
173  // last block
174  if (ncolrem) {
175    uint64_t orig_rem = ncols - (ncolblk << 5);
176    uint64_t b_sl = orig_rem >= 32 ? 32 : orig_rem;
177    int32_t tmp[32];
178    zn32_vec_i32_mat8kcols_ref[(ncolrem - 1) >> 3](rows, tmp, a, mat, b_sl);
179    memcpy(rr, tmp, ncolrem * sizeof(int32_t));
180  }
181  // trailing bytes
182  memset(res + cols, 0, (res_size - cols) * sizeof(int32_t));
183}
184
185#endif