You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

153 rivejä
6.6 KiB

  1. /// @file blas_comm.c
  2. /// @brief The standard implementations for blas_comm.h
  3. ///
  4. #include "blas_comm.h"
  5. #include "blas.h"
  6. #include "gf.h"
  7. #include "rainbow_config.h"
  8. #include <stdint.h>
  9. #include <string.h>
  10. void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) {
  11. for (size_t i = 0; i < _num_byte; i++) {
  12. b[i] = 0;
  13. }
  14. }
  15. /// @brief get an element from GF(16) vector .
  16. ///
  17. /// @param[in] a - the input vector a.
  18. /// @param[in] i - the index in the vector a.
  19. /// @return the value of the element.
  20. ///
  21. uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i) {
  22. uint8_t r = a[i >> 1];
  23. uint8_t r0 = r & 0xf;
  24. uint8_t r1 = r >> 4;
  25. uint8_t m = (uint8_t)(-((int8_t)i & 1));
  26. return (uint8_t)((r1 & m) | ((~m) & r0));
  27. }
  28. /// @brief set an element for a GF(16) vector .
  29. ///
  30. /// @param[in,out] a - the vector a.
  31. /// @param[in] i - the index in the vector a.
  32. /// @param[in] v - the value for the i-th element in vector a.
  33. /// @return the value of the element.
  34. ///
  35. static uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_set_ele(uint8_t *a, unsigned int i, uint8_t v) {
  36. uint8_t m = (uint8_t)(0xf ^ (-((int8_t)i & 1))); /// 1--> 0xf0 , 0--> 0x0f
  37. uint8_t ai_remaining = (uint8_t)(a[i >> 1] & (~m)); /// erase
  38. a[i >> 1] = (uint8_t)(ai_remaining | (m & (v << 4)) | (m & v & 0xf)); /// set
  39. return v;
  40. }
  41. static void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) {
  42. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_A_vec_byte);
  43. for (unsigned int i = 0; i < n_A_width; i++) {
  44. uint8_t bb = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(b, i);
  45. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(c, matA, bb, n_A_vec_byte);
  46. matA += n_A_vec_byte;
  47. }
  48. }
  49. void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) {
  50. unsigned int n_vec_byte = (len_vec + 1) / 2;
  51. for (unsigned int k = 0; k < len_vec; k++) {
  52. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_vec_byte);
  53. const uint8_t *bk = b + n_vec_byte * k;
  54. for (unsigned int i = 0; i < len_vec; i++) {
  55. uint8_t bb = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(bk, i);
  56. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(c, a + n_vec_byte * i, bb, n_vec_byte);
  57. }
  58. c += n_vec_byte;
  59. }
  60. }
  61. static unsigned int gf16mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) {
  62. unsigned int n_w_byte = (w + 1) / 2;
  63. unsigned int r8 = 1;
  64. for (unsigned int i = 0; i < h; i++) {
  65. unsigned int offset_byte = i >> 1;
  66. uint8_t *ai = mat + n_w_byte * i;
  67. for (unsigned int j = i + 1; j < h; j++) {
  68. uint8_t *aj = mat + n_w_byte * j;
  69. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(ai + offset_byte, !PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_is_nonzero(PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(ai, i)), aj + offset_byte, n_w_byte - offset_byte);
  70. }
  71. uint8_t pivot = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(ai, i);
  72. r8 &= PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_is_nonzero(pivot);
  73. pivot = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_inv(pivot);
  74. offset_byte = (i + 1) >> 1;
  75. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_mul_scalar(ai + offset_byte, pivot, n_w_byte - offset_byte);
  76. for (unsigned int j = 0; j < h; j++) {
  77. if (i == j) {
  78. continue;
  79. }
  80. uint8_t *aj = mat + n_w_byte * j;
  81. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(aj + offset_byte, ai + offset_byte, PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(aj, i), n_w_byte - offset_byte);
  82. }
  83. }
  84. return r8;
  85. }
  86. static unsigned int gf16mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) {
  87. uint8_t mat[64 * 33];
  88. unsigned int n_byte = (n + 1) >> 1;
  89. for (unsigned int i = 0; i < n; i++) {
  90. memcpy(mat + i * (n_byte + 1), inp_mat + i * n_byte, n_byte);
  91. mat[i * (n_byte + 1) + n_byte] = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(c_terms, i);
  92. }
  93. unsigned int r8 = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(mat, n, n + 2);
  94. for (unsigned int i = 0; i < n; i++) {
  95. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_set_ele(sol, i, mat[i * (n_byte + 1) + n_byte]);
  96. }
  97. return r8;
  98. }
  99. static inline void gf16mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) {
  100. unsigned int n_byte_w1 = (w + 1) / 2;
  101. unsigned int n_byte_w2 = (w2 + 1) / 2;
  102. unsigned int st_2 = st / 2;
  103. for (unsigned int i = 0; i < h; i++) {
  104. for (unsigned int j = 0; j < n_byte_w2; j++) {
  105. mat2[i * n_byte_w2 + j] = mat[i * n_byte_w1 + st_2 + j];
  106. }
  107. }
  108. }
  109. unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) {
  110. unsigned int n_w_byte = (H + 1) / 2;
  111. uint8_t *aa = buffer;
  112. for (unsigned int i = 0; i < H; i++) {
  113. uint8_t *ai = aa + i * 2 * n_w_byte;
  114. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(ai, 2 * n_w_byte);
  115. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(ai, a + i * n_w_byte, n_w_byte);
  116. PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_set_ele(ai + n_w_byte, i, 1);
  117. }
  118. unsigned int r8 = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(aa, H, 2 * H);
  119. gf16mat_submat(inv_a, H, H, aa, 2 * H, H);
  120. return r8;
  121. }
  122. // choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE
  123. #define gf16mat_prod_impl gf16mat_prod_ref
  124. #define gf16mat_gauss_elim_impl gf16mat_gauss_elim_ref
  125. #define gf16mat_solve_linear_eq_impl gf16mat_solve_linear_eq_ref
  126. void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) {
  127. gf16mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b);
  128. }
  129. unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) {
  130. return gf16mat_gauss_elim_impl(mat, h, w);
  131. }
  132. unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) {
  133. return gf16mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n);
  134. }