1 /* Exercise an RS codec a specified number of times using random
2  * data and error patterns
3  *
4  * Copyright 2002 Phil Karn, KA9Q
5  * May be used under the terms of the GNU General Public License (GPL)
6  */
7 #define FLAG_ERASURE 1 /* Randomly flag 50% of errors as erasures */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 
12 #ifdef FIXED
13 #include "fixed.h"
14 #define EXERCISE exercise_8
15 #elif defined(CCSDS)
16 #include "fixed.h"
17 #include "ccsds.h"
18 #define EXERCISE exercise_ccsds
19 #elif defined(BIGSYM)
20 #include "int.h"
21 #define EXERCISE exercise_int
22 #else
23 #include "char.h"
24 #define EXERCISE exercise_char
25 #endif
26 
27 #ifdef FIXED
28 #define PRINTPARM printf("(255,223):");
29 #elif defined(CCSDS)
30 #define PRINTPARM printf("CCSDS (255,223):");
31 #else
32 #define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots);
33 #endif
34 
35 /* Exercise the RS codec passed as an argument */
EXERCISE(void * p,int trials)36 int EXERCISE(
37 #if !defined(CCSDS) && !defined(FIXED)
38 void *p,
39 #endif
40 int trials){
41 #if !defined(CCSDS) && !defined(FIXED)
42   struct rs *rs = (struct rs *)p;
43 #endif
44   DTYPE block[NN],tblock[NN];
45   int i;
46   int errors;
47   int errlocs[NN];
48   int derrlocs[NROOTS];
49   int derrors;
50   int errval,errloc;
51   int erasures;
52   int decoder_errors = 0;
53 
54   while(trials-- != 0){
55     /* Test up to the error correction capacity of the code */
56     for(errors=0;errors <= NROOTS/2;errors++){
57 
58       /* Load block with random data and encode */
59       for(i=0;i<NN-NROOTS;i++)
60 	block[i] = random() & NN;
61 
62 #if defined(CCSDS) || defined(FIXED)
63       ENCODE_RS(&block[0],&block[NN-NROOTS],0);
64 #else
65       ENCODE_RS(rs,&block[0],&block[NN-NROOTS]);
66 #endif
67 
68       /* Make temp copy, seed with errors */
69       memcpy(tblock,block,sizeof(tblock));
70       memset(errlocs,0,sizeof(errlocs));
71       memset(derrlocs,0,sizeof(derrlocs));
72       erasures=0;
73       for(i=0;i<errors;i++){
74 	do {
75 	  errval = random() & NN;
76 	} while(errval == 0); /* Error value must be nonzero */
77 
78 	do {
79 	  errloc = random() % NN;
80 	} while(errlocs[errloc] != 0); /* Must not choose the same location twice */
81 
82 	errlocs[errloc] = 1;
83 
84 #if FLAG_ERASURE
85 	if(random() & 1) /* 50-50 chance */
86 	  derrlocs[erasures++] = errloc;
87 #endif
88 	tblock[errloc] ^= errval;
89       }
90 
91       /* Decode the errored block */
92 #if defined(CCSDS) || defined(FIXED)
93       derrors = DECODE_RS(tblock,derrlocs,erasures,0);
94 #else
95       derrors = DECODE_RS(rs,tblock,derrlocs,erasures);
96 #endif
97 
98       if(derrors != errors){
99 	PRINTPARM
100 	printf(" decoder says %d errors, true number is %d\n",derrors,errors);
101 	decoder_errors++;
102       }
103       for(i=0;i<derrors;i++){
104 	if(errlocs[derrlocs[i]] == 0){
105 	  PRINTPARM
106 	  printf(" decoder indicates error in location %d without error\n",derrlocs[i]);
107 	  decoder_errors++;
108 	}
109       }
110       if(memcmp(tblock,block,sizeof(tblock)) != 0){
111 	PRINTPARM
112 	printf(" uncorrected errors! output ^ input:");
113 	decoder_errors++;
114 	for(i=0;i<NN;i++)
115 	  printf(" %02x",tblock[i] ^ block[i]);
116 	printf("\n");
117       }
118     }
119   }
120   return decoder_errors;
121 }
122