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