#include #include #include #include "erasure_code.h" #define MAX_CHECK 63 /* Size is limited by using uint64_t to represent subsets */ #define M_MAX 0x20 #define K_MAX 0x10 #define ROWS M_MAX #define COLS K_MAX static inline uint64_t min(const uint64_t a, const uint64_t b) { if (a <= b) return a; else return b; } 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) { uint64_t i, j, r, s; for (i = 0, r = 0; i < rows; i++) { if (!(row_indicator & ((uint64_t) 1 << i))) continue; for (j = 0, s = 0; j < cols; j++) { if (!(col_indicator & ((uint64_t) 1 << j))) continue; out_matrix[dim * r + s] = in_matrix[cols * i + j]; s++; } r++; } } /* Gosper's Hack */ uint64_t next_subset(uint64_t *subset, uint64_t element_count, uint64_t subsize) { uint64_t tmp1 = *subset & -*subset; uint64_t tmp2 = *subset + tmp1; *subset = (((*subset ^ tmp2) >> 2) / tmp1) | tmp2; if (*subset & (((uint64_t) 1 << element_count))) { /* Overflow on last subset */ *subset = ((uint64_t) 1 << subsize) - 1; return 1; } return 0; } int are_submatrices_singular(unsigned char *vmatrix, const uint64_t rows, const uint64_t cols) { unsigned char matrix[COLS * COLS]; unsigned char invert_matrix[COLS * COLS]; uint64_t subsize; /* Check all square subsize x subsize submatrices of the rows x cols * vmatrix for singularity*/ for (subsize = 1; subsize <= min(rows, cols); subsize++) { const uint64_t subset_init = (1ULL << subsize) - 1ULL; uint64_t col_indicator = subset_init; do { uint64_t row_indicator = subset_init; do { gen_sub_matrix(matrix, subsize, vmatrix, rows, cols, row_indicator, col_indicator); if (gf_invert_matrix(matrix, invert_matrix, (int) subsize)) return 1; } while (next_subset(&row_indicator, rows, subsize) == 0); } while (next_subset(&col_indicator, cols, subsize) == 0); } return 0; } int main(int argc, char **argv) { unsigned char vmatrix[(ROWS + COLS) * COLS]; uint64_t rows, cols; if (K_MAX > MAX_CHECK) { printf("K_MAX too large for this test\n"); return 0; } if (M_MAX > MAX_CHECK) { printf("M_MAX too large for this test\n"); return 0; } if (M_MAX < K_MAX) { printf("M_MAX must be smaller than K_MAX"); return 0; } printf("Checking gen_rs_matrix for k <= %d and m <= %d.\n", K_MAX, M_MAX); printf("gen_rs_matrix creates erasure codes for:\n"); for (cols = 1; cols <= K_MAX; cols++) { for (rows = 1; rows <= M_MAX - cols; rows++) { gf_gen_rs_matrix(vmatrix, rows + cols, cols); /* Verify the Vandermonde portion of vmatrix contains no * singular submatrix */ if (are_submatrices_singular(&vmatrix[cols * cols], rows, cols)) break; } printf(" k = %2u, m <= %2u \n", (unsigned) cols, (unsigned) (rows + cols - 1)); } return 0; }