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