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