/* Test (255,223) RS code
* August 1997 Phil Karn
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "rs32.h"
/* uses rs32.c and rs32asm.s */
void
fill_eras(int eras_pos[],int n)
{
int i,j,t,work[NN];
for(i=0;i<NN;i++)
work[i] = i;
for(j=NN-1;j>0;j--){
i = random() % j; /* not really uniform, I know */
t = work[i];
work[i] = work[j];
work[j] = t;
}
for(i=0;i<n;i++)
eras_pos[i] = work[i];
}
/* Return non-zero random number in range 0 - NN (NN power of 2 minus 1) */
int
randomnz(void)
{
int i;
while((i = random() & NN) == 0)
;
return i;
}
int
main(int argc,char *argv[])
{
dtype data[NN];
dtype tdata[NN];
dtype ddata[NN];
int eras_pos[NN];
int i,trials,k;
long t;
int nerrors,nerase,ntrials,verbose,timetest;
int detfails,fails;
extern char *optarg;
nerrors = nerase = 0;
timetest = verbose = 0;
ntrials = 100;
while((i = getopt(argc,argv,"e:E:n:vt")) != EOF){
switch(i){
case 'e': /* Number of errors per block */
nerrors = atoi(optarg);
break;
case 'E': /* Number of erasures per block */
nerase = atoi(optarg);
break;
case 'n': /* Number of trials */
ntrials = atoi(optarg);
break;
case 'v': /* Be verbose */
verbose = 1;
break;
case 't': /* Repeatedly decode the same block */
timetest = 1;
break;
default:
printf("usage: %s [-v] [-t] [-e errors] [-E erasures] [-n ntrials]\n",argv[0]);
exit(1);
}
}
printf("Reed-Solomon code is (%d,%d) over GF(%d)\n",
NN,KK,NN+1);
printf("test erasures: %d errors %d\n",nerase,nerrors);
if(2*nerrors + nerase > NN-KK)
printf("Warning: %d errors and %d erasures exceeds the correction ability of the code\n",nerrors,nerase);
time(&t);
srandom(t);
init_rs();
if(timetest){
printf("Speed timing test (repeated decoding of same block)\n");
for(i=0;i<KK;i++)
data[i] = random() & NN;
rse32(data,&data[KK]);
fill_eras(eras_pos,nerase+nerrors);
if(verbose && nerase){
printf("erasing:");
for(i=0;i<nerase;i++)
printf(" %d",eras_pos[i]);
printf("\n");
}
if(verbose && nerrors){
printf("erroring:");
for(i=nerase;i<nerase+nerrors;i++)
printf(" %d",eras_pos[i]);
printf("\n");
}
memcpy(tdata,data,sizeof(data));
for(i=0;i<nerase+nerrors;i++)
tdata[eras_pos[i]] ^= randomnz();
for(k=0;k<ntrials;k++){
memcpy(ddata,tdata,sizeof(tdata));
rsd32(ddata,eras_pos,nerase);
}
exit(0);
}
fails = detfails = 0;
for(trials=0;trials < ntrials;trials++){
unsigned char nparity[32];
if(verbose)
printf("Trial %d:",trials);
for(i=0;i<KK;i++)
data[i] = random() & NN;
rse32(data,&data[KK]);
#ifdef printparity
printf("old parity:");
for(i=0;i<NN-KK;i++)
printf(" %02x",data[KK+i]);
printf("\n");
#endif
fill_eras(eras_pos,nerase+nerrors);
if(verbose && nerase){
printf(" erasing:");
for(i=0;i<nerase;i++)
printf(" %d",eras_pos[i]);
}
if(verbose && nerrors){
printf(" erroring:");
for(i=nerase;i<nerase+nerrors;i++)
printf(" %d",eras_pos[i]);
}
if(verbose)
printf("\n");
memcpy(ddata,data,sizeof(data));
for(i=0;i<nerase+nerrors;i++)
ddata[eras_pos[i]] ^= randomnz();
i = rsd32(ddata,eras_pos,nerase);
if(verbose){
printf("errs + erasures corrected: %d\n",i);
}
if(i == -1){
detfails++;
printf("RS decoder detected failure\n");
} else if(memcmp(ddata,data,NN) != 0){
fails++;
printf("Undetected decoding failure!\n");
for(i=0;i<NN;i++){
if(ddata[i] != data[i])
printf("[%d] %02x != %02x\n",
i,ddata[i],data[i]);
}
}
}
printf("Trials: %d decoding failures: %d; not detected by decoder: %d\n",
ntrials,detfails,fails);
return 0;
}