aboutsummaryrefslogtreecommitdiffstats
path: root/rstest.c
diff options
context:
space:
mode:
Diffstat (limited to 'rstest.c')
-rw-r--r--rstest.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/rstest.c b/rstest.c
new file mode 100644
index 0000000..539b40a
--- /dev/null
+++ b/rstest.c
@@ -0,0 +1,296 @@
+/* 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;
+}