gr-satnogs/lib/libfec/rstest.c

325 lines
7.9 KiB
C

/* Test the Reed-Solomon codecs
* for various block sizes and with random data and random error patterns
*
* Copyright 2002 Phil Karn, KA9Q
* May be used under the terms of the GNU Lesser General Public License (LGPL)
*/
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>
#include "fec.h"
struct etab {
int symsize;
int genpoly;
int fcs;
int prim;
int nroots;
int ntrials;
} Tab[] = {
{2, 0x7, 1, 1, 1, 10 },
{3, 0xb, 1, 1, 2, 10 },
{4, 0x13, 1, 1, 4, 10 },
{5, 0x25, 1, 1, 6, 10 },
{6, 0x43, 1, 1, 8, 10 },
{7, 0x89, 1, 1, 10, 10 },
{8, 0x11d, 1, 1, 32, 10 },
{8, 0x187, 112, 11, 32, 10 }, /* Duplicates CCSDS codec */
{9, 0x211, 1, 1, 32, 10 },
{10, 0x409, 1, 1, 32, 10 },
{11, 0x805, 1, 1, 32, 10 },
{12, 0x1053, 1, 1, 32, 5 },
{13, 0x201b, 1, 1, 32, 2 },
{14, 0x4443, 1, 1, 32, 1 },
{15, 0x8003, 1, 1, 32, 1 },
{16, 0x1100b, 1, 1, 32, 1 },
{0, 0, 0, 0, 0},
};
int exercise_char(struct etab *e);
int exercise_int(struct etab *e);
int exercise_8(void);
int main()
{
int i;
srandom(time(NULL));
printf("Testing fixed CCSDS encoder...\n");
exercise_8();
for (i = 0; Tab[i].symsize != 0; i++) {
int nn, kk;
nn = (1 << Tab[i].symsize) - 1;
kk = nn - Tab[i].nroots;
printf("Testing (%d,%d) code...\n", nn, kk);
if (Tab[i].symsize <= 8) {
exercise_char(&Tab[i]);
}
else {
exercise_int(&Tab[i]);
}
}
exit(0);
}
int exercise_8(void)
{
int nn = 255;
unsigned char block[nn], tblock[nn];
int errlocs[nn], derrlocs[nn];
int i;
int errors;
int derrors, kk;
int errval, errloc;
int erasures;
int decoder_errors = 0;
/* Compute code parameters */
kk = 223;
/* Test up to the error correction capacity of the code */
for (errors = 0; errors <= (nn - kk) / 2; errors++) {
/* Load block with random data and encode */
for (i = 0; i < kk; i++) {
block[i] = random() & nn;
}
memcpy(tblock, block, sizeof(block));
encode_rs_8(block, &block[kk], 0);
/* Make temp copy, seed with errors */
memcpy(tblock, block, sizeof(block));
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 */
derrors = decode_rs_8(tblock, derrlocs, erasures, 0);
if (derrors != errors) {
printf("(%d,%d) decoder says %d errors, true number is %d\n", nn, kk, derrors,
errors);
decoder_errors++;
}
for (i = 0; i < derrors; i++) {
if (errlocs[derrlocs[i]] == 0) {
printf("(%d,%d) decoder indicates error in location %d without error\n", nn, kk,
derrlocs[i]);
decoder_errors++;
}
}
if (memcmp(tblock, block, sizeof(tblock)) != 0) {
printf("(%d,%d) decoder uncorrected errors! output ^ input:", nn, kk);
decoder_errors++;
for (i = 0; i < nn; i++) {
printf(" %02x", tblock[i] ^ block[i]);
}
printf("\n");
}
}
return decoder_errors;
}
int exercise_char(struct etab *e)
{
int nn = (1 << e->symsize) - 1;
unsigned char block[nn], tblock[nn];
int errlocs[nn], derrlocs[nn];
int i;
int errors;
int derrors, kk;
int errval, errloc;
int erasures;
int decoder_errors = 0;
void *rs;
if (e->symsize > 8) {
return -1;
}
/* Compute code parameters */
kk = nn - e->nroots;
rs = init_rs_char(e->symsize, e->genpoly, e->fcs, e->prim, e->nroots, 0);
if (rs == NULL) {
printf("init_rs_char failed!\n");
return -1;
}
/* Test up to the error correction capacity of the code */
for (errors = 0; errors <= e->nroots / 2; errors++) {
/* Load block with random data and encode */
for (i = 0; i < kk; i++) {
block[i] = random() & nn;
}
memcpy(tblock, block, sizeof(block));
encode_rs_char(rs, block, &block[kk]);
/* Make temp copy, seed with errors */
memcpy(tblock, block, sizeof(block));
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 */
derrors = decode_rs_char(rs, tblock, derrlocs, erasures);
if (derrors != errors) {
printf("(%d,%d) decoder says %d errors, true number is %d\n", nn, kk, derrors,
errors);
decoder_errors++;
}
for (i = 0; i < derrors; i++) {
if (errlocs[derrlocs[i]] == 0) {
printf("(%d,%d) decoder indicates error in location %d without error\n", nn, kk,
derrlocs[i]);
decoder_errors++;
}
}
if (memcmp(tblock, block, sizeof(tblock)) != 0) {
printf("(%d,%d) decoder uncorrected errors! output ^ input:", nn, kk);
decoder_errors++;
for (i = 0; i < nn; i++) {
printf(" %02x", tblock[i] ^ block[i]);
}
printf("\n");
}
}
free_rs_char(rs);
return 0;
}
int exercise_int(struct etab *e)
{
int nn = (1 << e->symsize) - 1;
int block[nn], tblock[nn];
int errlocs[nn], derrlocs[nn];
int i;
int errors;
int derrors, kk;
int errval, errloc;
int erasures;
int decoder_errors = 0;
void *rs;
/* Compute code parameters */
kk = nn - e->nroots;
rs = init_rs_int(e->symsize, e->genpoly, e->fcs, e->prim, e->nroots, 0);
if (rs == NULL) {
printf("init_rs_int failed!\n");
return -1;
}
/* Test up to the error correction capacity of the code */
for (errors = 0; errors <= e->nroots / 2; errors++) {
/* Load block with random data and encode */
for (i = 0; i < kk; i++) {
block[i] = random() & nn;
}
memcpy(tblock, block, sizeof(block));
encode_rs_int(rs, block, &block[kk]);
/* Make temp copy, seed with errors */
memcpy(tblock, block, sizeof(block));
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 */
derrors = decode_rs_int(rs, tblock, derrlocs, erasures);
if (derrors != errors) {
printf("(%d,%d) decoder says %d errors, true number is %d\n", nn, kk, derrors,
errors);
decoder_errors++;
}
for (i = 0; i < derrors; i++) {
if (errlocs[derrlocs[i]] == 0) {
printf("(%d,%d) decoder indicates error in location %d without error\n", nn, kk,
derrlocs[i]);
decoder_errors++;
}
}
if (memcmp(tblock, block, sizeof(tblock)) != 0) {
printf("(%d,%d) decoder uncorrected errors! output ^ input:", nn, kk);
decoder_errors++;
for (i = 0; i < nn; i++) {
printf(" %02x", tblock[i] ^ block[i]);
}
printf("\n");
}
}
free_rs_int(rs);
return 0;
}