1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#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;
}
|