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