xref: /isa-l/erasure_code/gf_inverse_test.c (revision 300260a4d902423a8a69f0f7d74e6abaa33ded27)
1 /**********************************************************************
2   Copyright(c) 2011-2015 Intel Corporation All rights reserved.
3 
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions
6   are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in
11       the documentation and/or other materials provided with the
12       distribution.
13     * Neither the name of Intel Corporation nor the names of its
14       contributors may be used to endorse or promote products derived
15       from this software without specific prior written permission.
16 
17   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 **********************************************************************/
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h> // for memset, memcmp
33 #include <assert.h>
34 
35 #include "erasure_code.h"
36 
37 #define TEST_LEN 8192
38 
39 #ifndef TEST_SOURCES
40 #define TEST_SOURCES 128
41 #endif
42 #ifndef RANDOMS
43 #define RANDOMS 200
44 #endif
45 
46 #define KMAX TEST_SOURCES
47 
48 typedef unsigned char u8;
49 
50 void
matrix_mult(u8 * a,u8 * b,u8 * c,int n)51 matrix_mult(u8 *a, u8 *b, u8 *c, int n)
52 {
53         int i, j, k;
54         u8 d;
55 
56         for (i = 0; i < n; i++) {
57                 for (j = 0; j < n; j++) {
58                         d = 0;
59                         for (k = 0; k < n; k++) {
60                                 d ^= gf_mul(a[n * i + k], b[n * k + j]);
61                         }
62                         c[i * n + j] = d;
63                 }
64         }
65 }
66 
67 void
print_matrix(u8 * a,int n)68 print_matrix(u8 *a, int n)
69 {
70         int i, j;
71 
72         for (i = 0; i < n; i++) {
73                 for (j = 0; j < n; j++) {
74                         printf(" %2x", a[i * n + j]);
75                 }
76                 printf("\n");
77         }
78         printf("\n");
79 }
80 
81 int
is_ident(u8 * a,const int n)82 is_ident(u8 *a, const int n)
83 {
84         int i, j;
85         u8 c;
86         for (i = 0; i < n; i++) {
87                 for (j = 0; j < n; j++) {
88                         c = *a++;
89                         if (i == j)
90                                 c--;
91                         if (c != 0)
92                                 return -1;
93                 }
94         }
95         return 0;
96 }
97 
98 int
inv_test(u8 * in,u8 * inv,u8 * sav,int n)99 inv_test(u8 *in, u8 *inv, u8 *sav, int n)
100 {
101         memcpy(sav, in, n * n);
102 
103         if (gf_invert_matrix(in, inv, n)) {
104                 printf("Given singular matrix\n");
105                 print_matrix(sav, n);
106                 return -1;
107         }
108 
109         matrix_mult(inv, sav, in, n);
110 
111         if (is_ident(in, n)) {
112                 printf("fail\n");
113                 print_matrix(sav, n);
114                 print_matrix(inv, n);
115                 print_matrix(in, n);
116                 return -1;
117         }
118 #ifdef TEST_VERBOSE
119         putchar('.');
120 #endif
121 
122         return 0;
123 }
124 
125 int
main(int argc,char * argv[])126 main(int argc, char *argv[])
127 {
128         int i, k, t;
129         u8 *test_mat = NULL, *save_mat = NULL, *invr_mat = NULL;
130         int ret = -1;
131 
132         u8 test1[] = { 1, 1, 6, 1, 1, 1, 7, 1, 9 };
133 
134         u8 test2[] = { 0, 1, 6, 1, 0, 1, 0, 1, 9 };
135 
136         u8 test3[] = { 0, 0, 1, 1, 0, 0, 0, 1, 1 };
137 
138         u8 test4[] = { 0, 1, 6, 7, 1, 1, 0, 0, 0, 1, 2, 3, 3, 2, 2, 3 }; // = row3+3*row2
139 
140         printf("gf_inverse_test: max=%d ", KMAX);
141 
142         test_mat = malloc(KMAX * KMAX);
143         save_mat = malloc(KMAX * KMAX);
144         invr_mat = malloc(KMAX * KMAX);
145 
146         if (NULL == test_mat || NULL == save_mat || NULL == invr_mat)
147                 goto exit;
148 
149         // Test with lots of leading 1's
150         k = 3;
151         memcpy(test_mat, test1, k * k);
152         if (inv_test(test_mat, invr_mat, save_mat, k))
153                 goto exit;
154 
155         // Test with leading zeros
156         k = 3;
157         memcpy(test_mat, test2, k * k);
158         if (inv_test(test_mat, invr_mat, save_mat, k))
159                 goto exit;
160 
161         // Test 3
162         k = 3;
163         memcpy(test_mat, test3, k * k);
164         if (inv_test(test_mat, invr_mat, save_mat, k))
165                 goto exit;
166 
167         // Test 4 - try a singular matrix
168         k = 4;
169         memcpy(test_mat, test4, k * k);
170         if (!gf_invert_matrix(test_mat, invr_mat, k)) {
171                 printf("Fail: didn't catch singular matrix\n");
172                 print_matrix(test4, 4);
173                 goto exit;
174         }
175         // Do random test of size KMAX
176         k = KMAX;
177 
178         for (i = 0; i < k * k; i++)
179                 test_mat[i] = save_mat[i] = rand();
180 
181         if (gf_invert_matrix(test_mat, invr_mat, k)) {
182                 printf("rand picked a singular matrix, try again\n");
183                 goto exit;
184         }
185 
186         matrix_mult(invr_mat, save_mat, test_mat, k);
187 
188         if (is_ident(test_mat, k)) {
189                 printf("fail\n");
190                 print_matrix(save_mat, k);
191                 print_matrix(invr_mat, k);
192                 print_matrix(test_mat, k);
193                 goto exit;
194         }
195         // Do Randoms.  Random size and coefficients
196         for (t = 0; t < RANDOMS; t++) {
197                 k = rand() % KMAX;
198 
199                 for (i = 0; i < k * k; i++)
200                         test_mat[i] = save_mat[i] = rand();
201 
202                 if (gf_invert_matrix(test_mat, invr_mat, k))
203                         continue;
204 
205                 matrix_mult(invr_mat, save_mat, test_mat, k);
206 
207                 if (is_ident(test_mat, k)) {
208                         printf("fail rand k=%d\n", k);
209                         print_matrix(save_mat, k);
210                         print_matrix(invr_mat, k);
211                         print_matrix(test_mat, k);
212                         goto exit;
213                 }
214 #ifdef TEST_VERBOSE
215                 if (0 == (t % 8))
216                         putchar('.');
217 #endif
218         }
219 
220         printf(" Pass\n");
221 
222         ret = 0;
223 
224 exit:
225         free(test_mat);
226         free(save_mat);
227         free(invr_mat);
228 
229         return ret;
230 }
231