gen_rs_matrix_limits.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. #include <string.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include "erasure_code.h"
  5. #define MAX_CHECK 63 /* Size is limited by using uint64_t to represent subsets */
  6. #define M_MAX 0x20
  7. #define K_MAX 0x10
  8. #define ROWS M_MAX
  9. #define COLS K_MAX
  10. static inline uint64_t min(const uint64_t a, const uint64_t b)
  11. {
  12. if (a <= b)
  13. return a;
  14. else
  15. return b;
  16. }
  17. void gen_sub_matrix(unsigned char *out_matrix, const uint64_t dim, unsigned char *in_matrix,
  18. const uint64_t rows, const uint64_t cols, const uint64_t row_indicator,
  19. const uint64_t col_indicator)
  20. {
  21. uint64_t i, j, r, s;
  22. for (i = 0, r = 0; i < rows; i++) {
  23. if (!(row_indicator & ((uint64_t) 1 << i)))
  24. continue;
  25. for (j = 0, s = 0; j < cols; j++) {
  26. if (!(col_indicator & ((uint64_t) 1 << j)))
  27. continue;
  28. out_matrix[dim * r + s] = in_matrix[cols * i + j];
  29. s++;
  30. }
  31. r++;
  32. }
  33. }
  34. /* Gosper's Hack */
  35. uint64_t next_subset(uint64_t * subset, uint64_t element_count, uint64_t subsize)
  36. {
  37. uint64_t tmp1 = *subset & -*subset;
  38. uint64_t tmp2 = *subset + tmp1;
  39. *subset = (((*subset ^ tmp2) >> 2) / tmp1) | tmp2;
  40. if (*subset & (((uint64_t) 1 << element_count))) {
  41. /* Overflow on last subset */
  42. *subset = ((uint64_t) 1 << subsize) - 1;
  43. return 1;
  44. }
  45. return 0;
  46. }
  47. int are_submatrices_singular(unsigned char *vmatrix, const uint64_t rows, const uint64_t cols)
  48. {
  49. unsigned char matrix[COLS * COLS];
  50. unsigned char invert_matrix[COLS * COLS];
  51. uint64_t subsize;
  52. /* Check all square subsize x subsize submatrices of the rows x cols
  53. * vmatrix for singularity*/
  54. for (subsize = 1; subsize <= min(rows, cols); subsize++) {
  55. const uint64_t subset_init = (1ULL << subsize) - 1ULL;
  56. uint64_t col_indicator = subset_init;
  57. do {
  58. uint64_t row_indicator = subset_init;
  59. do {
  60. gen_sub_matrix(matrix, subsize, vmatrix, rows,
  61. cols, row_indicator, col_indicator);
  62. if (gf_invert_matrix(matrix, invert_matrix, (int)subsize))
  63. return 1;
  64. } while (next_subset(&row_indicator, rows, subsize) == 0);
  65. } while (next_subset(&col_indicator, cols, subsize) == 0);
  66. }
  67. return 0;
  68. }
  69. int main(int argc, char **argv)
  70. {
  71. unsigned char vmatrix[(ROWS + COLS) * COLS];
  72. uint64_t rows, cols;
  73. if (K_MAX > MAX_CHECK) {
  74. printf("K_MAX too large for this test\n");
  75. return 0;
  76. }
  77. if (M_MAX > MAX_CHECK) {
  78. printf("M_MAX too large for this test\n");
  79. return 0;
  80. }
  81. if (M_MAX < K_MAX) {
  82. printf("M_MAX must be smaller than K_MAX");
  83. return 0;
  84. }
  85. printf("Checking gen_rs_matrix for k <= %d and m <= %d.\n", K_MAX, M_MAX);
  86. printf("gen_rs_matrix creates erasure codes for:\n");
  87. for (cols = 1; cols <= K_MAX; cols++) {
  88. for (rows = 1; rows <= M_MAX - cols; rows++) {
  89. gf_gen_rs_matrix(vmatrix, rows + cols, cols);
  90. /* Verify the Vandermonde portion of vmatrix contains no
  91. * singular submatrix */
  92. if (are_submatrices_singular(&vmatrix[cols * cols], rows, cols))
  93. break;
  94. }
  95. printf(" k = %2u, m <= %2u \n", (unsigned)cols, (unsigned)(rows + cols - 1));
  96. }
  97. return 0;
  98. }