2 * Copyright (c) 2014, James S. Plank and Kevin Greenan
5 * Jerasure - A C/C++ Library for a Variety of Reed-Solomon and RAID-6 Erasure
8 * Revision 2.0: Galois Field backend now links to GF-Complete
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * - Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * - Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
22 * - Neither the name of the University of Tennessee nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
33 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
34 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
36 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
40 /* Jerasure's authors:
42 Revision 2.x - 2014: James S. Plank and Kevin M. Greenan.
43 Revision 1.2 - 2008: James S. Plank, Scott Simmerman and Catherine D. Schuman.
44 Revision 1.0 - 2007: James S. Plank.
52 #define talloc(type, num) (type *) malloc(sizeof(type)*(num))
54 static void usage(char *s)
56 fprintf(stderr, "usage: jerasure_03 k w - Creates a kxk Cauchy matrix in GF(2^w). \n\n");
57 fprintf(stderr, " k must be < 2^w. Element i,j is 1/(i+(2^w-j-1)). (If that is\n");
58 fprintf(stderr, " If that is 1/0, then it sets it to zero). \n");
59 fprintf(stderr, " It then tests whether that matrix is invertible.\n");
60 fprintf(stderr, " If it is invertible, then it prints out the inverse.\n");
61 fprintf(stderr, " Finally, it prints the product of the matrix and its inverse.\n");
62 fprintf(stderr, " \n");
63 fprintf(stderr, "This demonstrates: jerasure_print_matrix()\n");
64 fprintf(stderr, " jerasure_invertible_matrix()\n");
65 fprintf(stderr, " jerasure_invert_matrix()\n");
66 fprintf(stderr, " jerasure_matrix_multiply().\n");
67 if (s != NULL) fprintf(stderr, "%s\n", s);
72 typedef unsigned long mylong;
73 #define LLUI (long long unsigned int)
76 void display(mylong *mat, int r, int c) {
77 for(int i=0;i<r;i++) {
78 for(int j=0;j<c;j++) {
79 printf("%016llu ",LLUI mat[i*c+j]);
86 mylong *matrix_multiply(gf_t *gf, mylong *m1, mylong *m2, int r1, int c1, int r2, int c2, int w)
91 product = (mylong *) malloc(sizeof(mylong)*r1*c2);
92 for (i = 0; i < r1*c2; i++) product[i] = 0;
94 for (i = 0; i < r1; i++) {
95 for (j = 0; j < c2; j++) {
96 for (k = 0; k < r2; k++) {
97 product[i*c2+j] ^= gf->multiply.w64(gf,m1[i*c1+k], m2[k*c2+j]);
106 int invert_matrix(gf_t *gf, mylong *mat, mylong *inv, int rows)
108 int cols, i, j, k, x, rs2;
115 for (i = 0; i < rows; i++) {
116 for (j = 0; j < cols; j++) {
117 inv[k] = (i == j) ? 1 : 0;
121 // display(inv, rows, rows);
124 /* First -- convert into upper triangular */
125 for (i = 0; i < cols; i++) {
128 /* Swap rows if we ave a zero i,i element. If we can't swap, then the
129 matrix was not invertible */
131 if (mat[row_start+i] == 0) {
132 for (j = i+1; j < rows && mat[cols*j+i] == 0; j++) ;
133 if (j == rows) return -1;
135 for (k = 0; k < cols; k++) {
136 tmp = mat[row_start+k];
137 mat[row_start+k] = mat[rs2+k];
139 tmp = inv[row_start+k];
140 inv[row_start+k] = inv[rs2+k];
145 /* Multiply the row by 1/element i,i */
146 tmp = mat[row_start+i];
148 inverse = gf->divide.w64(gf,1, tmp);
149 for (j = 0; j < cols; j++) {
150 mat[row_start+j] = gf->multiply.w64(gf,mat[row_start+j], inverse);
151 inv[row_start+j] = gf->multiply.w64(gf,inv[row_start+j], inverse);
155 /* Now for each j>i, add A_ji*Ai to Aj */
157 for (j = i+1; j != cols; j++) {
162 for (x = 0; x < cols; x++) {
163 mat[rs2+x] ^= mat[row_start+x];
164 inv[rs2+x] ^= inv[row_start+x];
169 for (x = 0; x < cols; x++) {
170 mat[rs2+x] ^= gf->multiply.w64(gf,tmp, mat[row_start+x]);
171 inv[rs2+x] ^= gf->multiply.w64(gf,tmp, inv[row_start+x]);
178 /* Now the matrix is upper triangular. Start at the top and multiply down */
180 for (i = rows-1; i >= 0; i--) {
182 for (j = 0; j < i; j++) {
184 if (mat[rs2+i] != 0) {
187 for (k = 0; k < cols; k++) {
188 inv[rs2+k] ^= gf->multiply.w64(gf,tmp, inv[row_start+k]);
195 display(mat, rows, rows);
198 display(inv, rows, rows);
207 int invertible_matrix(gf_t *gf, int *mat, int rows, int w)
209 int cols, i, j, k, x, rs2;
215 /* First -- convert into upper triangular */
216 for (i = 0; i < cols; i++) {
219 /* Swap rows if we ave a zero i,i element. If we can't swap, then the
220 matrix was not invertible */
222 if (mat[row_start+i] == 0) {
223 for (j = i+1; j < rows && mat[cols*j+i] == 0; j++) ;
224 if (j == rows) return 0;
226 for (k = 0; k < cols; k++) {
227 tmp = mat[row_start+k];
228 mat[row_start+k] = mat[rs2+k];
233 /* Multiply the row by 1/element i,i */
234 tmp = mat[row_start+i];
236 inverse = gf->divide.w64(gf,1, tmp);
237 for (j = 0; j < cols; j++) {
238 mat[row_start+j] = gf->multiply.w64(gf,mat[row_start+j], inverse);
242 /* Now for each j>i, add A_ji*Ai to Aj */
244 for (j = i+1; j != cols; j++) {
249 for (x = 0; x < cols; x++) {
250 mat[rs2+x] ^= mat[row_start+x];
255 for (x = 0; x < cols; x++) {
256 mat[rs2+x] ^= gf->multiply.w64(gf,tmp,mat[row_start+x]);
267 int main(int argc, char **argv)
269 unsigned int k, w, i, j, n;
277 // if (argc != 2) usage(NULL);
278 //if (sscanf(argv[1], "%d", &k) == 0 || k <= 0) usage("Bad k");
279 /* if (sscanf(argv[2], "%d", &w) == 0 || w <= 0 || w > 31) usage("Bad w");
280 if (k >= (1 << w)) usage("K too big");
285 matrix = malloc(sizeof(mylong)*k*k);
286 matrix_copy = malloc(sizeof(mylong)* k*k);
287 inverse = malloc(sizeof(mylong)* k*k);
289 /*for (i = 0; i < k; i++) {
290 for (j = 0; j < k; j++) {
291 n = i ^ ((1 << w)-1-j);
292 matrix[i*k+j] = (n == 0) ? 0 : galois_single_divide(1, n, w);
298 for(int j=0;j<k;j++) {
300 matrix[i*k+j]=lrand48()<<32|lrand48();//k*k-(j*k+i);
310 gf_init_easy(&gf, w);
313 /* printf("<HTML><TITLE>jerasure_03");
314 for (i = 1; i < argc; i++) printf(" %s", argv[i]);
315 printf("</TITLE>\n");
316 printf("<h3>jerasure_03");
317 for (i = 1; i < argc; i++) printf(" %s", argv[i]);
322 //jerasure_print_matrix(matrix, k, k, w);
323 display(matrix, k, k);
325 memcpy(matrix_copy, matrix, sizeof(mylong)*k*k);
327 //jerasure_invertible_matrix(matrix_copy, k, w);
328 invertible_matrix(&gf,matrix_copy, k, w);
329 printf("\nInvertible: %s\n", (i == 1) ? "Yes" : "No");
331 printf("\nInverse:\n");
332 memcpy(matrix_copy, matrix, sizeof(mylong)*k*k);
333 // i = jerasure_invert_matrix(matrix_copy, inverse, k, w);
335 invert_matrix(&gf, matrix_copy, inverse, k);
337 //jerasure_print_matrix(inverse, k, k, w);
338 display(inverse, k, k);
340 //identity = jerasure_matrix_multiply(inverse, matrix, k, k, k, k, w);
341 identity=matrix_multiply(&gf, inverse, matrix, k, k, k, k, w);
342 printf("\nInverse times matrix (should be identity):\n");
343 display(identity, k, k);
344 //jerasure_print_matrix(identity, k, k, w);