xref: /aosp_15_r20/external/fec/rstest.c (revision 638691a093b4f9473cd6ee8f3e0139deef159a86)
1*638691a0SAndroid Build Coastguard Worker /* Test the Reed-Solomon codecs
2*638691a0SAndroid Build Coastguard Worker  * for various block sizes and with random data and random error patterns
3*638691a0SAndroid Build Coastguard Worker  *
4*638691a0SAndroid Build Coastguard Worker  * Copyright 2002 Phil Karn, KA9Q
5*638691a0SAndroid Build Coastguard Worker  * May be used under the terms of the GNU Lesser General Public License (LGPL)
6*638691a0SAndroid Build Coastguard Worker  */
7*638691a0SAndroid Build Coastguard Worker 
8*638691a0SAndroid Build Coastguard Worker #include <stdio.h>
9*638691a0SAndroid Build Coastguard Worker #include <stdlib.h>
10*638691a0SAndroid Build Coastguard Worker #include <memory.h>
11*638691a0SAndroid Build Coastguard Worker #include <time.h>
12*638691a0SAndroid Build Coastguard Worker #include "fec.h"
13*638691a0SAndroid Build Coastguard Worker 
14*638691a0SAndroid Build Coastguard Worker 
15*638691a0SAndroid Build Coastguard Worker struct etab {
16*638691a0SAndroid Build Coastguard Worker   int symsize;
17*638691a0SAndroid Build Coastguard Worker   int genpoly;
18*638691a0SAndroid Build Coastguard Worker   int fcs;
19*638691a0SAndroid Build Coastguard Worker   int prim;
20*638691a0SAndroid Build Coastguard Worker   int nroots;
21*638691a0SAndroid Build Coastguard Worker   int ntrials;
22*638691a0SAndroid Build Coastguard Worker } Tab[] = {
23*638691a0SAndroid Build Coastguard Worker   {2, 0x7,     1,   1, 1, 10 },
24*638691a0SAndroid Build Coastguard Worker   {3, 0xb,     1,   1, 2, 10 },
25*638691a0SAndroid Build Coastguard Worker   {4, 0x13,    1,   1, 4, 10 },
26*638691a0SAndroid Build Coastguard Worker   {5, 0x25,    1,   1, 6, 10 },
27*638691a0SAndroid Build Coastguard Worker   {6, 0x43,    1,   1, 8, 10 },
28*638691a0SAndroid Build Coastguard Worker   {7, 0x89,    1,   1, 10, 10 },
29*638691a0SAndroid Build Coastguard Worker   {8, 0x11d,   1,   1, 32, 10 },
30*638691a0SAndroid Build Coastguard Worker   {8, 0x187,   112,11, 32, 10 }, /* Duplicates CCSDS codec */
31*638691a0SAndroid Build Coastguard Worker   {9, 0x211,   1,   1, 32, 10 },
32*638691a0SAndroid Build Coastguard Worker   {10,0x409,   1,   1, 32, 10 },
33*638691a0SAndroid Build Coastguard Worker   {11,0x805,   1,   1, 32, 10 },
34*638691a0SAndroid Build Coastguard Worker   {12,0x1053,  1,   1, 32, 5 },
35*638691a0SAndroid Build Coastguard Worker   {13,0x201b,  1,   1, 32, 2 },
36*638691a0SAndroid Build Coastguard Worker   {14,0x4443,  1,   1, 32, 1 },
37*638691a0SAndroid Build Coastguard Worker   {15,0x8003,  1,   1, 32, 1 },
38*638691a0SAndroid Build Coastguard Worker   {16,0x1100b, 1,   1, 32, 1 },
39*638691a0SAndroid Build Coastguard Worker   {0, 0, 0, 0, 0},
40*638691a0SAndroid Build Coastguard Worker };
41*638691a0SAndroid Build Coastguard Worker 
42*638691a0SAndroid Build Coastguard Worker int exercise_char(struct etab *e);
43*638691a0SAndroid Build Coastguard Worker int exercise_int(struct etab *e);
44*638691a0SAndroid Build Coastguard Worker int exercise_8(void);
45*638691a0SAndroid Build Coastguard Worker 
main()46*638691a0SAndroid Build Coastguard Worker int main(){
47*638691a0SAndroid Build Coastguard Worker   int i;
48*638691a0SAndroid Build Coastguard Worker 
49*638691a0SAndroid Build Coastguard Worker   srandom(time(NULL));
50*638691a0SAndroid Build Coastguard Worker 
51*638691a0SAndroid Build Coastguard Worker   printf("Testing fixed CCSDS encoder...\n");
52*638691a0SAndroid Build Coastguard Worker   exercise_8();
53*638691a0SAndroid Build Coastguard Worker   for(i=0;Tab[i].symsize != 0;i++){
54*638691a0SAndroid Build Coastguard Worker     int nn,kk;
55*638691a0SAndroid Build Coastguard Worker 
56*638691a0SAndroid Build Coastguard Worker     nn = (1<<Tab[i].symsize) - 1;
57*638691a0SAndroid Build Coastguard Worker     kk = nn - Tab[i].nroots;
58*638691a0SAndroid Build Coastguard Worker     printf("Testing (%d,%d) code...\n",nn,kk);
59*638691a0SAndroid Build Coastguard Worker     if(Tab[i].symsize <= 8)
60*638691a0SAndroid Build Coastguard Worker       exercise_char(&Tab[i]);
61*638691a0SAndroid Build Coastguard Worker     else
62*638691a0SAndroid Build Coastguard Worker       exercise_int(&Tab[i]);
63*638691a0SAndroid Build Coastguard Worker   }
64*638691a0SAndroid Build Coastguard Worker   exit(0);
65*638691a0SAndroid Build Coastguard Worker }
66*638691a0SAndroid Build Coastguard Worker 
exercise_8(void)67*638691a0SAndroid Build Coastguard Worker int exercise_8(void){
68*638691a0SAndroid Build Coastguard Worker   int nn = 255;
69*638691a0SAndroid Build Coastguard Worker   unsigned char block[nn],tblock[nn];
70*638691a0SAndroid Build Coastguard Worker   int errlocs[nn],derrlocs[nn];
71*638691a0SAndroid Build Coastguard Worker   int i;
72*638691a0SAndroid Build Coastguard Worker   int errors;
73*638691a0SAndroid Build Coastguard Worker   int derrors,kk;
74*638691a0SAndroid Build Coastguard Worker   int errval,errloc;
75*638691a0SAndroid Build Coastguard Worker   int erasures;
76*638691a0SAndroid Build Coastguard Worker   int decoder_errors = 0;
77*638691a0SAndroid Build Coastguard Worker 
78*638691a0SAndroid Build Coastguard Worker   /* Compute code parameters */
79*638691a0SAndroid Build Coastguard Worker   kk = 223;
80*638691a0SAndroid Build Coastguard Worker 
81*638691a0SAndroid Build Coastguard Worker 
82*638691a0SAndroid Build Coastguard Worker   /* Test up to the error correction capacity of the code */
83*638691a0SAndroid Build Coastguard Worker   for(errors=0;errors<=(nn-kk)/2;errors++){
84*638691a0SAndroid Build Coastguard Worker 
85*638691a0SAndroid Build Coastguard Worker     /* Load block with random data and encode */
86*638691a0SAndroid Build Coastguard Worker     for(i=0;i<kk;i++)
87*638691a0SAndroid Build Coastguard Worker       block[i] = random() & nn;
88*638691a0SAndroid Build Coastguard Worker     memcpy(tblock,block,sizeof(block));
89*638691a0SAndroid Build Coastguard Worker     encode_rs_8(block,&block[kk],0);
90*638691a0SAndroid Build Coastguard Worker 
91*638691a0SAndroid Build Coastguard Worker     /* Make temp copy, seed with errors */
92*638691a0SAndroid Build Coastguard Worker     memcpy(tblock,block,sizeof(block));
93*638691a0SAndroid Build Coastguard Worker     memset(errlocs,0,sizeof(errlocs));
94*638691a0SAndroid Build Coastguard Worker     memset(derrlocs,0,sizeof(derrlocs));
95*638691a0SAndroid Build Coastguard Worker     erasures=0;
96*638691a0SAndroid Build Coastguard Worker     for(i=0;i<errors;i++){
97*638691a0SAndroid Build Coastguard Worker       do {
98*638691a0SAndroid Build Coastguard Worker 	errval = random() & nn;
99*638691a0SAndroid Build Coastguard Worker       } while(errval == 0); /* Error value must be nonzero */
100*638691a0SAndroid Build Coastguard Worker 
101*638691a0SAndroid Build Coastguard Worker       do {
102*638691a0SAndroid Build Coastguard Worker 	errloc = random() % nn;
103*638691a0SAndroid Build Coastguard Worker       } while(errlocs[errloc] != 0); /* Must not choose the same location twice */
104*638691a0SAndroid Build Coastguard Worker 
105*638691a0SAndroid Build Coastguard Worker       errlocs[errloc] = 1;
106*638691a0SAndroid Build Coastguard Worker 
107*638691a0SAndroid Build Coastguard Worker #if FLAG_ERASURE
108*638691a0SAndroid Build Coastguard Worker       if(random() & 1) /* 50-50 chance */
109*638691a0SAndroid Build Coastguard Worker 	derrlocs[erasures++] = errloc;
110*638691a0SAndroid Build Coastguard Worker #endif
111*638691a0SAndroid Build Coastguard Worker       tblock[errloc] ^= errval;
112*638691a0SAndroid Build Coastguard Worker     }
113*638691a0SAndroid Build Coastguard Worker 
114*638691a0SAndroid Build Coastguard Worker     /* Decode the errored block */
115*638691a0SAndroid Build Coastguard Worker     derrors = decode_rs_8(tblock,derrlocs,erasures,0);
116*638691a0SAndroid Build Coastguard Worker 
117*638691a0SAndroid Build Coastguard Worker     if(derrors != errors){
118*638691a0SAndroid Build Coastguard Worker 	printf("(%d,%d) decoder says %d errors, true number is %d\n",nn,kk,derrors,errors);
119*638691a0SAndroid Build Coastguard Worker 	decoder_errors++;
120*638691a0SAndroid Build Coastguard Worker     }
121*638691a0SAndroid Build Coastguard Worker     for(i=0;i<derrors;i++){
122*638691a0SAndroid Build Coastguard Worker       if(errlocs[derrlocs[i]] == 0){
123*638691a0SAndroid Build Coastguard Worker 	printf("(%d,%d) decoder indicates error in location %d without error\n",nn,kk,derrlocs[i]);
124*638691a0SAndroid Build Coastguard Worker 	decoder_errors++;
125*638691a0SAndroid Build Coastguard Worker       }
126*638691a0SAndroid Build Coastguard Worker     }
127*638691a0SAndroid Build Coastguard Worker     if(memcmp(tblock,block,sizeof(tblock)) != 0){
128*638691a0SAndroid Build Coastguard Worker       printf("(%d,%d) decoder uncorrected errors! output ^ input:",nn,kk);
129*638691a0SAndroid Build Coastguard Worker       decoder_errors++;
130*638691a0SAndroid Build Coastguard Worker       for(i=0;i<nn;i++)
131*638691a0SAndroid Build Coastguard Worker 	printf(" %02x",tblock[i] ^ block[i]);
132*638691a0SAndroid Build Coastguard Worker       printf("\n");
133*638691a0SAndroid Build Coastguard Worker     }
134*638691a0SAndroid Build Coastguard Worker   }
135*638691a0SAndroid Build Coastguard Worker   return decoder_errors;
136*638691a0SAndroid Build Coastguard Worker }
137*638691a0SAndroid Build Coastguard Worker 
138*638691a0SAndroid Build Coastguard Worker 
exercise_char(struct etab * e)139*638691a0SAndroid Build Coastguard Worker int exercise_char(struct etab *e){
140*638691a0SAndroid Build Coastguard Worker   int nn = (1<<e->symsize) - 1;
141*638691a0SAndroid Build Coastguard Worker   unsigned char block[nn],tblock[nn];
142*638691a0SAndroid Build Coastguard Worker   int errlocs[nn],derrlocs[nn];
143*638691a0SAndroid Build Coastguard Worker   int i;
144*638691a0SAndroid Build Coastguard Worker   int errors;
145*638691a0SAndroid Build Coastguard Worker   int derrors,kk;
146*638691a0SAndroid Build Coastguard Worker   int errval,errloc;
147*638691a0SAndroid Build Coastguard Worker   int erasures;
148*638691a0SAndroid Build Coastguard Worker   int decoder_errors = 0;
149*638691a0SAndroid Build Coastguard Worker   void *rs;
150*638691a0SAndroid Build Coastguard Worker 
151*638691a0SAndroid Build Coastguard Worker   if(e->symsize > 8)
152*638691a0SAndroid Build Coastguard Worker     return -1;
153*638691a0SAndroid Build Coastguard Worker 
154*638691a0SAndroid Build Coastguard Worker   /* Compute code parameters */
155*638691a0SAndroid Build Coastguard Worker   kk = nn - e->nroots;
156*638691a0SAndroid Build Coastguard Worker 
157*638691a0SAndroid Build Coastguard Worker   rs = init_rs_char(e->symsize,e->genpoly,e->fcs,e->prim,e->nroots,0);
158*638691a0SAndroid Build Coastguard Worker   if(rs == NULL){
159*638691a0SAndroid Build Coastguard Worker     printf("init_rs_char failed!\n");
160*638691a0SAndroid Build Coastguard Worker     return -1;
161*638691a0SAndroid Build Coastguard Worker   }
162*638691a0SAndroid Build Coastguard Worker   /* Test up to the error correction capacity of the code */
163*638691a0SAndroid Build Coastguard Worker   for(errors=0;errors <= e->nroots/2;errors++){
164*638691a0SAndroid Build Coastguard Worker 
165*638691a0SAndroid Build Coastguard Worker     /* Load block with random data and encode */
166*638691a0SAndroid Build Coastguard Worker     for(i=0;i<kk;i++)
167*638691a0SAndroid Build Coastguard Worker       block[i] = random() & nn;
168*638691a0SAndroid Build Coastguard Worker     memcpy(tblock,block,sizeof(block));
169*638691a0SAndroid Build Coastguard Worker     encode_rs_char(rs,block,&block[kk]);
170*638691a0SAndroid Build Coastguard Worker 
171*638691a0SAndroid Build Coastguard Worker     /* Make temp copy, seed with errors */
172*638691a0SAndroid Build Coastguard Worker     memcpy(tblock,block,sizeof(block));
173*638691a0SAndroid Build Coastguard Worker     memset(errlocs,0,sizeof(errlocs));
174*638691a0SAndroid Build Coastguard Worker     memset(derrlocs,0,sizeof(derrlocs));
175*638691a0SAndroid Build Coastguard Worker     erasures=0;
176*638691a0SAndroid Build Coastguard Worker     for(i=0;i<errors;i++){
177*638691a0SAndroid Build Coastguard Worker       do {
178*638691a0SAndroid Build Coastguard Worker 	errval = random() & nn;
179*638691a0SAndroid Build Coastguard Worker       } while(errval == 0); /* Error value must be nonzero */
180*638691a0SAndroid Build Coastguard Worker 
181*638691a0SAndroid Build Coastguard Worker       do {
182*638691a0SAndroid Build Coastguard Worker 	errloc = random() % nn;
183*638691a0SAndroid Build Coastguard Worker       } while(errlocs[errloc] != 0); /* Must not choose the same location twice */
184*638691a0SAndroid Build Coastguard Worker 
185*638691a0SAndroid Build Coastguard Worker       errlocs[errloc] = 1;
186*638691a0SAndroid Build Coastguard Worker 
187*638691a0SAndroid Build Coastguard Worker #if FLAG_ERASURE
188*638691a0SAndroid Build Coastguard Worker       if(random() & 1) /* 50-50 chance */
189*638691a0SAndroid Build Coastguard Worker 	derrlocs[erasures++] = errloc;
190*638691a0SAndroid Build Coastguard Worker #endif
191*638691a0SAndroid Build Coastguard Worker       tblock[errloc] ^= errval;
192*638691a0SAndroid Build Coastguard Worker     }
193*638691a0SAndroid Build Coastguard Worker 
194*638691a0SAndroid Build Coastguard Worker     /* Decode the errored block */
195*638691a0SAndroid Build Coastguard Worker     derrors = decode_rs_char(rs,tblock,derrlocs,erasures);
196*638691a0SAndroid Build Coastguard Worker 
197*638691a0SAndroid Build Coastguard Worker     if(derrors != errors){
198*638691a0SAndroid Build Coastguard Worker 	printf("(%d,%d) decoder says %d errors, true number is %d\n",nn,kk,derrors,errors);
199*638691a0SAndroid Build Coastguard Worker 	decoder_errors++;
200*638691a0SAndroid Build Coastguard Worker     }
201*638691a0SAndroid Build Coastguard Worker     for(i=0;i<derrors;i++){
202*638691a0SAndroid Build Coastguard Worker       if(errlocs[derrlocs[i]] == 0){
203*638691a0SAndroid Build Coastguard Worker 	printf("(%d,%d) decoder indicates error in location %d without error\n",nn,kk,derrlocs[i]);
204*638691a0SAndroid Build Coastguard Worker 	decoder_errors++;
205*638691a0SAndroid Build Coastguard Worker       }
206*638691a0SAndroid Build Coastguard Worker     }
207*638691a0SAndroid Build Coastguard Worker     if(memcmp(tblock,block,sizeof(tblock)) != 0){
208*638691a0SAndroid Build Coastguard Worker       printf("(%d,%d) decoder uncorrected errors! output ^ input:",nn,kk);
209*638691a0SAndroid Build Coastguard Worker       decoder_errors++;
210*638691a0SAndroid Build Coastguard Worker       for(i=0;i<nn;i++)
211*638691a0SAndroid Build Coastguard Worker 	printf(" %02x",tblock[i] ^ block[i]);
212*638691a0SAndroid Build Coastguard Worker       printf("\n");
213*638691a0SAndroid Build Coastguard Worker     }
214*638691a0SAndroid Build Coastguard Worker   }
215*638691a0SAndroid Build Coastguard Worker 
216*638691a0SAndroid Build Coastguard Worker   free_rs_char(rs);
217*638691a0SAndroid Build Coastguard Worker   return 0;
218*638691a0SAndroid Build Coastguard Worker }
219*638691a0SAndroid Build Coastguard Worker 
exercise_int(struct etab * e)220*638691a0SAndroid Build Coastguard Worker int exercise_int(struct etab *e){
221*638691a0SAndroid Build Coastguard Worker   int nn = (1<<e->symsize) - 1;
222*638691a0SAndroid Build Coastguard Worker   int block[nn],tblock[nn];
223*638691a0SAndroid Build Coastguard Worker   int errlocs[nn],derrlocs[nn];
224*638691a0SAndroid Build Coastguard Worker   int i;
225*638691a0SAndroid Build Coastguard Worker   int errors;
226*638691a0SAndroid Build Coastguard Worker   int derrors,kk;
227*638691a0SAndroid Build Coastguard Worker   int errval,errloc;
228*638691a0SAndroid Build Coastguard Worker   int erasures;
229*638691a0SAndroid Build Coastguard Worker   int decoder_errors = 0;
230*638691a0SAndroid Build Coastguard Worker   void *rs;
231*638691a0SAndroid Build Coastguard Worker 
232*638691a0SAndroid Build Coastguard Worker   /* Compute code parameters */
233*638691a0SAndroid Build Coastguard Worker   kk = nn - e->nroots;
234*638691a0SAndroid Build Coastguard Worker 
235*638691a0SAndroid Build Coastguard Worker   rs = init_rs_int(e->symsize,e->genpoly,e->fcs,e->prim,e->nroots,0);
236*638691a0SAndroid Build Coastguard Worker   if(rs == NULL){
237*638691a0SAndroid Build Coastguard Worker     printf("init_rs_int failed!\n");
238*638691a0SAndroid Build Coastguard Worker     return -1;
239*638691a0SAndroid Build Coastguard Worker   }
240*638691a0SAndroid Build Coastguard Worker   /* Test up to the error correction capacity of the code */
241*638691a0SAndroid Build Coastguard Worker   for(errors=0;errors <= e->nroots/2;errors++){
242*638691a0SAndroid Build Coastguard Worker 
243*638691a0SAndroid Build Coastguard Worker     /* Load block with random data and encode */
244*638691a0SAndroid Build Coastguard Worker     for(i=0;i<kk;i++)
245*638691a0SAndroid Build Coastguard Worker       block[i] = random() & nn;
246*638691a0SAndroid Build Coastguard Worker     memcpy(tblock,block,sizeof(block));
247*638691a0SAndroid Build Coastguard Worker     encode_rs_int(rs,block,&block[kk]);
248*638691a0SAndroid Build Coastguard Worker 
249*638691a0SAndroid Build Coastguard Worker     /* Make temp copy, seed with errors */
250*638691a0SAndroid Build Coastguard Worker     memcpy(tblock,block,sizeof(block));
251*638691a0SAndroid Build Coastguard Worker     memset(errlocs,0,sizeof(errlocs));
252*638691a0SAndroid Build Coastguard Worker     memset(derrlocs,0,sizeof(derrlocs));
253*638691a0SAndroid Build Coastguard Worker     erasures=0;
254*638691a0SAndroid Build Coastguard Worker     for(i=0;i<errors;i++){
255*638691a0SAndroid Build Coastguard Worker       do {
256*638691a0SAndroid Build Coastguard Worker 	errval = random() & nn;
257*638691a0SAndroid Build Coastguard Worker       } while(errval == 0); /* Error value must be nonzero */
258*638691a0SAndroid Build Coastguard Worker 
259*638691a0SAndroid Build Coastguard Worker       do {
260*638691a0SAndroid Build Coastguard Worker 	errloc = random() % nn;
261*638691a0SAndroid Build Coastguard Worker       } while(errlocs[errloc] != 0); /* Must not choose the same location twice */
262*638691a0SAndroid Build Coastguard Worker 
263*638691a0SAndroid Build Coastguard Worker       errlocs[errloc] = 1;
264*638691a0SAndroid Build Coastguard Worker 
265*638691a0SAndroid Build Coastguard Worker #if FLAG_ERASURE
266*638691a0SAndroid Build Coastguard Worker       if(random() & 1) /* 50-50 chance */
267*638691a0SAndroid Build Coastguard Worker 	derrlocs[erasures++] = errloc;
268*638691a0SAndroid Build Coastguard Worker #endif
269*638691a0SAndroid Build Coastguard Worker       tblock[errloc] ^= errval;
270*638691a0SAndroid Build Coastguard Worker     }
271*638691a0SAndroid Build Coastguard Worker 
272*638691a0SAndroid Build Coastguard Worker     /* Decode the errored block */
273*638691a0SAndroid Build Coastguard Worker     derrors = decode_rs_int(rs,tblock,derrlocs,erasures);
274*638691a0SAndroid Build Coastguard Worker 
275*638691a0SAndroid Build Coastguard Worker     if(derrors != errors){
276*638691a0SAndroid Build Coastguard Worker 	printf("(%d,%d) decoder says %d errors, true number is %d\n",nn,kk,derrors,errors);
277*638691a0SAndroid Build Coastguard Worker 	decoder_errors++;
278*638691a0SAndroid Build Coastguard Worker     }
279*638691a0SAndroid Build Coastguard Worker     for(i=0;i<derrors;i++){
280*638691a0SAndroid Build Coastguard Worker       if(errlocs[derrlocs[i]] == 0){
281*638691a0SAndroid Build Coastguard Worker 	printf("(%d,%d) decoder indicates error in location %d without error\n",nn,kk,derrlocs[i]);
282*638691a0SAndroid Build Coastguard Worker 	decoder_errors++;
283*638691a0SAndroid Build Coastguard Worker       }
284*638691a0SAndroid Build Coastguard Worker     }
285*638691a0SAndroid Build Coastguard Worker     if(memcmp(tblock,block,sizeof(tblock)) != 0){
286*638691a0SAndroid Build Coastguard Worker       printf("(%d,%d) decoder uncorrected errors! output ^ input:",nn,kk);
287*638691a0SAndroid Build Coastguard Worker       decoder_errors++;
288*638691a0SAndroid Build Coastguard Worker       for(i=0;i<nn;i++)
289*638691a0SAndroid Build Coastguard Worker 	printf(" %02x",tblock[i] ^ block[i]);
290*638691a0SAndroid Build Coastguard Worker       printf("\n");
291*638691a0SAndroid Build Coastguard Worker     }
292*638691a0SAndroid Build Coastguard Worker   }
293*638691a0SAndroid Build Coastguard Worker 
294*638691a0SAndroid Build Coastguard Worker   free_rs_int(rs);
295*638691a0SAndroid Build Coastguard Worker   return 0;
296*638691a0SAndroid Build Coastguard Worker }
297