/* 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;
}