summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib/reed-solomon/exercise.c
blob: 987fe1aebaef25bd7997cc0925c3b0defb600fbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Exercise an RS codec a specified number of times using random
 * data and error patterns
 *
 * Copyright 2002 Phil Karn, KA9Q
 * May be used under the terms of the GNU General Public License (GPL)
 */
#define FLAG_ERASURE 1 /* Randomly flag 50% of errors as erasures */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef FIXED
#include "fixed.h"
#define EXERCISE exercise_8
#elif defined(CCSDS)
#include "fixed.h"
#include "ccsds.h"
#define EXERCISE exercise_ccsds
#elif defined(BIGSYM)
#include "int.h"
#define EXERCISE exercise_int
#else
#include "char.h"
#define EXERCISE exercise_char
#endif

#ifdef FIXED
#define PRINTPARM printf("(255,223):");
#elif defined(CCSDS)
#define PRINTPARM printf("CCSDS (255,223):");
#else
#define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots);
#endif

/* Exercise the RS codec passed as an argument */
int EXERCISE(
#if !defined(CCSDS) && !defined(FIXED)
void *p,
#endif
int trials){
#if !defined(CCSDS) && !defined(FIXED)
  struct rs *rs = (struct rs *)p;
#endif
#if MAX_ARRAY
  DTYPE block[MAX_ARRAY],tblock[MAX_ARRAY];
  int i;
  int errors;
  int errlocs[MAX_ARRAY];
  int derrlocs[MAX_ARRAY];
#else
  DTYPE block[NN],tblock[NN];
  int i;
  int errors;
  int errlocs[NN];
  int derrlocs[NROOTS];
#endif
  int derrors;
  int errval,errloc;
  int erasures;
  int decoder_errors = 0;

  while(trials-- != 0){
    /* Test up to the error correction capacity of the code */
    for(errors=0;errors <= NROOTS/2;errors++){

      /* Load block with random data and encode */
      for(i=0;i<NN-NROOTS;i++)
	block[i] = random() & NN;
      
#if defined(CCSDS) || defined(FIXED)
      ENCODE_RS(&block[0],&block[NN-NROOTS]);
#else
      ENCODE_RS(rs,&block[0],&block[NN-NROOTS]);
#endif

      /* Make temp copy, seed with errors */
      memcpy(tblock,block,sizeof(tblock));
      memset(errlocs,0,sizeof(errlocs));
      memset(derrlocs,0,sizeof(derrlocs));
      erasures=0;
      for(i=0;i<errors;i++){
	do {
	  errval = random() & NN;
	} while(errval == 0); /* Error value must be nonzero */

	do {
	  errloc = random() % NN;
	} while(errlocs[errloc] != 0); /* Must not choose the same location twice */

	errlocs[errloc] = 1;

#if FLAG_ERASURE
	if(random() & 1) /* 50-50 chance */
	  derrlocs[erasures++] = errloc;
#endif
	tblock[errloc] ^= errval;
      }

      /* Decode the errored block */
#if defined(CCSDS) || defined(FIXED)
      derrors = DECODE_RS(tblock,derrlocs,erasures);
#else
      derrors = DECODE_RS(rs,tblock,derrlocs,erasures);
#endif

      if(derrors != errors){
	PRINTPARM
	printf(" decoder says %d errors, true number is %d\n",derrors,errors);
	decoder_errors++;
      }
      for(i=0;i<derrors;i++){
	if(errlocs[derrlocs[i]] == 0){
	  PRINTPARM
	  printf(" decoder indicates error in location %d without error\n",i);
	  decoder_errors++;
	}
      }
      if(memcmp(tblock,block,sizeof(tblock)) != 0){
	PRINTPARM
	printf(" uncorrected errors! output ^ input:");
	decoder_errors++;
	for(i=0;i<NN;i++)
	  printf(" %02x",tblock[i] ^ block[i]);
	printf("\n");
      }
    }
  }
  return decoder_errors;
}