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 #include <gf_complete.h>
57 #define talloc(type, num) (type *) malloc(sizeof(type)*(num))
59 int *reed_sol_r6_coding_matrix(int k, int w)
64 if (w != 8 && w != 16 && w != 32) return NULL;
66 matrix = talloc(int, 2*k);
67 if (matrix == NULL) return NULL;
69 for (i = 0; i < k; i++) matrix[i] = 1;
72 for (i = 1; i < k; i++) {
73 tmp = galois_single_multiply(tmp, 2, w);
79 int *reed_sol_vandermonde_coding_matrix(int k, int m, int w)
84 vdm = reed_sol_big_vandermonde_distribution_matrix(k+m, k, w);
85 if (vdm == NULL) return NULL;
86 dist = talloc(int, m*k);
93 for (j = 0; j < m*k; j++) {
101 static int prim08 = -1;
104 void reed_sol_galois_w08_region_multby_2(char *region, int nbytes)
107 prim08 = galois_single_multiply((1 << 7), 2, 8);
108 if (!gf_init_hard(&GF08, 8, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT,
109 prim08, 0, 0, NULL, NULL)) {
110 fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w08_region_multby_2\n");
114 GF08.multiply_region.w32(&GF08, region, region, 2, nbytes, 0);
117 static int prim16 = -1;
120 void reed_sol_galois_w16_region_multby_2(char *region, int nbytes)
123 prim16 = galois_single_multiply((1 << 15), 2, 16);
124 if (!gf_init_hard(&GF16, 16, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT,
125 prim16, 0, 0, NULL, NULL)) {
126 fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w16_region_multby_2\n");
130 GF16.multiply_region.w32(&GF16, region, region, 2, nbytes, 0);
133 static int prim32 = -1;
136 void reed_sol_galois_w32_region_multby_2(char *region, int nbytes)
139 prim32 = galois_single_multiply(((gf_val_32_t)1 << 31), 2, 32);
140 if (!gf_init_hard(&GF32, 32, GF_MULT_BYTWO_b, GF_REGION_DEFAULT, GF_DIVIDE_DEFAULT,
141 prim32, 0, 0, NULL, NULL)) {
142 fprintf(stderr, "Error: Can't initialize the GF for reed_sol_galois_w32_region_multby_2\n");
146 GF32.multiply_region.w32(&GF32, region, region, 2, nbytes, 0);
149 int reed_sol_r6_encode(int k, int w, char **data_ptrs, char **coding_ptrs, int size)
153 /* First, put the XOR into coding region 0 */
155 memcpy(coding_ptrs[0], data_ptrs[0], size);
157 for (i = 1; i < k; i++) galois_region_xor(data_ptrs[i], coding_ptrs[0], size);
159 /* Next, put the sum of (2^j)*Dj into coding region 1 */
161 memcpy(coding_ptrs[1], data_ptrs[k-1], size);
163 for (i = k-2; i >= 0; i--) {
165 case 8: reed_sol_galois_w08_region_multby_2(coding_ptrs[1], size); break;
166 case 16: reed_sol_galois_w16_region_multby_2(coding_ptrs[1], size); break;
167 case 32: reed_sol_galois_w32_region_multby_2(coding_ptrs[1], size); break;
171 galois_region_xor(data_ptrs[i], coding_ptrs[1], size);
176 int *reed_sol_extended_vandermonde_matrix(int rows, int cols, int w)
181 if (w < 30 && (1 << w) < rows) return NULL;
182 if (w < 30 && (1 << w) < cols) return NULL;
184 vdm = talloc(int, rows*cols);
185 if (vdm == NULL) { return NULL; }
188 for (j = 1; j < cols; j++) vdm[j] = 0;
189 if (rows == 1) return vdm;
192 for (j = 0; j < cols-1; j++) vdm[i+j] = 0;
194 if (rows == 2) return vdm;
196 for (i = 1; i < rows-1; i++) {
198 for (j = 0; j < cols; j++) {
200 k = galois_single_multiply(k, i, w);
206 int *reed_sol_big_vandermonde_distribution_matrix(int rows, int cols, int w)
210 int sindex, srindex, siindex, tmp;
212 if (cols >= rows) return NULL;
214 dist = reed_sol_extended_vandermonde_matrix(rows, cols, w);
215 if (dist == NULL) return NULL;
218 for (i = 1; i < cols; i++) {
221 /* Find an appropriate row -- where i,i != 0 */
223 for (j = i; j < rows && dist[srindex] == 0; j++) srindex += cols;
224 if (j >= rows) { /* This should never happen if rows/w are correct */
225 fprintf(stderr, "reed_sol_big_vandermonde_distribution_matrix(%d,%d,%d) - couldn't make matrix\n",
230 /* If necessary, swap rows */
233 for (k = 0; k < cols; k++) {
234 tmp = dist[srindex+k];
235 dist[srindex+k] = dist[sindex+k];
236 dist[sindex+k] = tmp;
240 /* If Element i,i is not equal to 1, multiply the column by 1/i */
242 if (dist[sindex+i] != 1) {
243 tmp = galois_single_divide(1, dist[sindex+i], w);
245 for (j = 0; j < rows; j++) {
246 dist[srindex] = galois_single_multiply(tmp, dist[srindex], w);
251 /* Now, for each element in row i that is not in column 1, you need
252 to make it zero. Suppose that this is column j, and the element
253 at i,j = e. Then you want to replace all of column j with
254 (col-j + col-i*e). Note, that in row i, col-i = 1 and col-j = e.
255 So (e + 1e) = 0, which is indeed what we want. */
257 for (j = 0; j < cols; j++) {
258 tmp = dist[sindex+j];
259 if (j != i && tmp != 0) {
262 for (k = 0; k < rows; k++) {
263 dist[srindex] = dist[srindex] ^ galois_single_multiply(tmp, dist[siindex], w);
270 /* We desire to have row k be all ones. To do that, multiply
271 the entire column j by 1/dist[k,j]. Then row j by 1/dist[j,j]. */
274 for (j = 0; j < cols; j++) {
277 tmp = galois_single_divide(1, tmp, w);
279 for (i = cols; i < rows; i++) {
280 dist[srindex] = galois_single_multiply(tmp, dist[srindex], w);
287 /* Finally, we'd like the first column of each row to be all ones. To
288 do that, we multiply the row by the inverse of the first element. */
290 sindex = cols*(cols+1);
291 for (i = cols+1; i < rows; i++) {
294 tmp = galois_single_divide(1, tmp, w);
295 for (j = 0; j < cols; j++) dist[sindex+j] = galois_single_multiply(dist[sindex+j], tmp, w);