Bill Yi | 4e213d5 | 2015-06-23 13:53:11 -0700 | [diff] [blame] | 1 | /* Exercise an RS codec a specified number of times using random |
| 2 | * data and error patterns |
| 3 | * |
| 4 | * Copyright 2002 Phil Karn, KA9Q |
| 5 | * May be used under the terms of the GNU Lesser General Public License (LGPL) |
| 6 | */ |
| 7 | #define FLAG_ERASURE 1 /* Randomly flag 50% of errors as erasures */ |
| 8 | |
| 9 | #include <stdio.h> |
| 10 | #include <stdlib.h> |
| 11 | #include <string.h> |
| 12 | |
| 13 | #ifdef FIXED |
| 14 | #include "fixed.h" |
| 15 | #define EXERCISE exercise_8 |
| 16 | #elif defined(CCSDS) |
| 17 | #include "fixed.h" |
| 18 | #include "ccsds.h" |
| 19 | #define EXERCISE exercise_ccsds |
| 20 | #elif defined(BIGSYM) |
| 21 | #include "int.h" |
| 22 | #define EXERCISE exercise_int |
| 23 | #else |
| 24 | #include "char.h" |
| 25 | #define EXERCISE exercise_char |
| 26 | #endif |
| 27 | |
| 28 | #ifdef FIXED |
| 29 | #define PRINTPARM printf("(255,223):"); |
| 30 | #elif defined(CCSDS) |
| 31 | #define PRINTPARM printf("CCSDS (255,223):"); |
| 32 | #else |
| 33 | #define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots); |
| 34 | #endif |
| 35 | |
| 36 | /* Exercise the RS codec passed as an argument */ |
| 37 | int EXERCISE( |
| 38 | #if !defined(CCSDS) && !defined(FIXED) |
| 39 | void *p, |
| 40 | #endif |
| 41 | int trials){ |
| 42 | #if !defined(CCSDS) && !defined(FIXED) |
| 43 | struct rs *rs = (struct rs *)p; |
| 44 | #endif |
| 45 | data_t block[NN],tblock[NN]; |
| 46 | int i; |
| 47 | int errors; |
| 48 | int errlocs[NN]; |
| 49 | int derrlocs[NROOTS]; |
| 50 | int derrors; |
| 51 | int errval,errloc; |
| 52 | int erasures; |
| 53 | int decoder_errors = 0; |
| 54 | |
| 55 | while(trials-- != 0){ |
| 56 | /* Test up to the error correction capacity of the code */ |
| 57 | for(errors=0;errors <= NROOTS/2;errors++){ |
| 58 | |
| 59 | /* Load block with random data and encode */ |
| 60 | for(i=0;i<NN-NROOTS;i++) |
| 61 | block[i] = random() & NN; |
| 62 | |
| 63 | #if defined(CCSDS) || defined(FIXED) |
| 64 | ENCODE_RS(&block[0],&block[NN-NROOTS],0); |
| 65 | #else |
| 66 | ENCODE_RS(rs,&block[0],&block[NN-NROOTS]); |
| 67 | #endif |
| 68 | |
| 69 | /* Make temp copy, seed with errors */ |
| 70 | memcpy(tblock,block,sizeof(tblock)); |
| 71 | memset(errlocs,0,sizeof(errlocs)); |
| 72 | memset(derrlocs,0,sizeof(derrlocs)); |
| 73 | erasures=0; |
| 74 | for(i=0;i<errors;i++){ |
| 75 | do { |
| 76 | errval = random() & NN; |
| 77 | } while(errval == 0); /* Error value must be nonzero */ |
| 78 | |
| 79 | do { |
| 80 | errloc = random() % NN; |
| 81 | } while(errlocs[errloc] != 0); /* Must not choose the same location twice */ |
| 82 | |
| 83 | errlocs[errloc] = 1; |
| 84 | |
| 85 | #if FLAG_ERASURE |
| 86 | if(random() & 1) /* 50-50 chance */ |
| 87 | derrlocs[erasures++] = errloc; |
| 88 | #endif |
| 89 | tblock[errloc] ^= errval; |
| 90 | } |
| 91 | |
| 92 | /* Decode the errored block */ |
| 93 | #if defined(CCSDS) || defined(FIXED) |
| 94 | derrors = DECODE_RS(tblock,derrlocs,erasures,0); |
| 95 | #else |
| 96 | derrors = DECODE_RS(rs,tblock,derrlocs,erasures); |
| 97 | #endif |
| 98 | |
| 99 | if(derrors != errors){ |
| 100 | PRINTPARM |
| 101 | printf(" decoder says %d errors, true number is %d\n",derrors,errors); |
| 102 | decoder_errors++; |
| 103 | } |
| 104 | for(i=0;i<derrors;i++){ |
| 105 | if(errlocs[derrlocs[i]] == 0){ |
| 106 | PRINTPARM |
| 107 | printf(" decoder indicates error in location %d without error\n",derrlocs[i]); |
| 108 | decoder_errors++; |
| 109 | } |
| 110 | } |
| 111 | if(memcmp(tblock,block,sizeof(tblock)) != 0){ |
| 112 | PRINTPARM |
| 113 | printf(" uncorrected errors! output ^ input:"); |
| 114 | decoder_errors++; |
| 115 | for(i=0;i<NN;i++) |
| 116 | printf(" %02x",tblock[i] ^ block[i]); |
| 117 | printf("\n"); |
| 118 | } |
| 119 | } |
| 120 | } |
| 121 | return decoder_errors; |
| 122 | } |