gr-satnogs/lib/libfec/exercise.c

129 lines
3.2 KiB
C

/* 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 Lesser General Public License (LGPL)
*/
#define FLAG_ERASURE 1 /* Randomly flag 50% of errors as erasures */
#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
data_t block[NN], tblock[NN];
int i;
int errors;
int errlocs[NN];
int derrlocs[NROOTS];
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], 0);
#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, 0);
#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", derrlocs[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;
}