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