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