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