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