| /* Exercise an RS codec a specified number of times using random |
| * data and error patterns |
| * |
| * Copyright 2002 Phil Karn, KA9Q |
| * May be used under the terms of the GNU Lesser General Public License (LGPL) |
| */ |
| #define FLAG_ERASURE 1 /* Randomly flag 50% of errors as erasures */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #ifdef FIXED |
| #include "fixed.h" |
| #define EXERCISE exercise_8 |
| #elif defined(CCSDS) |
| #include "fixed.h" |
| #include "ccsds.h" |
| #define EXERCISE exercise_ccsds |
| #elif defined(BIGSYM) |
| #include "int.h" |
| #define EXERCISE exercise_int |
| #else |
| #include "char.h" |
| #define EXERCISE exercise_char |
| #endif |
| |
| #ifdef FIXED |
| #define PRINTPARM printf("(255,223):"); |
| #elif defined(CCSDS) |
| #define PRINTPARM printf("CCSDS (255,223):"); |
| #else |
| #define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots); |
| #endif |
| |
| /* Exercise the RS codec passed as an argument */ |
| int EXERCISE( |
| #if !defined(CCSDS) && !defined(FIXED) |
| void *p, |
| #endif |
| int trials){ |
| #if !defined(CCSDS) && !defined(FIXED) |
| struct rs *rs = (struct rs *)p; |
| #endif |
| data_t block[NN],tblock[NN]; |
| int i; |
| int errors; |
| int errlocs[NN]; |
| int derrlocs[NROOTS]; |
| int derrors; |
| int errval,errloc; |
| int erasures; |
| int decoder_errors = 0; |
| |
| while(trials-- != 0){ |
| /* Test up to the error correction capacity of the code */ |
| for(errors=0;errors <= NROOTS/2;errors++){ |
| |
| /* Load block with random data and encode */ |
| for(i=0;i<NN-NROOTS;i++) |
| block[i] = random() & NN; |
| |
| #if defined(CCSDS) || defined(FIXED) |
| ENCODE_RS(&block[0],&block[NN-NROOTS],0); |
| #else |
| ENCODE_RS(rs,&block[0],&block[NN-NROOTS]); |
| #endif |
| |
| /* Make temp copy, seed with errors */ |
| memcpy(tblock,block,sizeof(tblock)); |
| 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 */ |
| #if defined(CCSDS) || defined(FIXED) |
| derrors = DECODE_RS(tblock,derrlocs,erasures,0); |
| #else |
| derrors = DECODE_RS(rs,tblock,derrlocs,erasures); |
| #endif |
| |
| if(derrors != errors){ |
| PRINTPARM |
| printf(" decoder says %d errors, true number is %d\n",derrors,errors); |
| decoder_errors++; |
| } |
| for(i=0;i<derrors;i++){ |
| if(errlocs[derrlocs[i]] == 0){ |
| PRINTPARM |
| printf(" decoder indicates error in location %d without error\n",derrlocs[i]); |
| decoder_errors++; |
| } |
| } |
| if(memcmp(tblock,block,sizeof(tblock)) != 0){ |
| PRINTPARM |
| printf(" uncorrected errors! output ^ input:"); |
| decoder_errors++; |
| for(i=0;i<NN;i++) |
| printf(" %02x",tblock[i] ^ block[i]); |
| printf("\n"); |
| } |
| } |
| } |
| return decoder_errors; |
| } |