C
/*
* File: bch3121.c
* Author: Robert Morelos-Zaragoza
*
* %%%%%%%%%%% Encoder/Decoder for a (31,21,5) binary BCH code %%%%%%%%%%%%%
*
* This code is used in the POCSAG protocol specification for pagers.
*
* In this specific case, there is no need to use the Berlekamp-Massey
* algorithm, since the error locator polynomial is of at most degree 2.
* Instead, we simply solve by hand two simultaneous equations to give
* the coefficients of the error locator polynomial in the case of two
* errors. In the case of one error, the location is given by the first
* syndrome.
*
* This program derivates from the original bch2.c, which was written
* to simulate the encoding/decoding of primitive binary BCH codes.
* Part of this program is adapted from a Reed-Solomon encoder/decoder
* program, 'rs.c', to the binary case.
*
* rs.c by Simon Rockliff, University of Adelaide, 21/9/89
* bch2.c by Robert Morelos-Zaragoza, University of Hawaii, 5/19/92
*
* COPYRIGHT NOTICE: This computer program is free for non-commercial purposes.
* You may implement this program for any non-commercial application. You may
* also implement this program for commercial purposes, provided that you
* obtain my written permission. Any modification of this program is covered
* by this copyright.
*
* %%%% Copyright 1994 (c) Robert Morelos-Zaragoza. All rights reserved. %%%%%
*
* m = order of the field GF(2**5) = 5
* n = 2**5 - 1 = 31 = length
* t = 2 = error correcting capability
* d = 2*t + 1 = 5 = designed minimum distance
* k = n - deg(g(x)) = 21 = dimension
* p[] = coefficients of primitive polynomial used to generate GF(2**5)
* g[] = coefficients of generator polynomial, g(x)
* alpha_to [] = log table of GF(2**5)
* index_of[] = antilog table of GF(2**5)
* data[] = coefficients of data polynomial, i(x)
* bb[] = coefficients of redundancy polynomial ( x**(10) i(x) ) modulo g(x)
* numerr = number of errors
* errpos[] = error positions
* recd[] = coefficients of received polynomial
* decerror = number of decoding errors (in MESSAGE positions)
*
*/
#include <math.h>
#include <stdio.h>
int m = 5, n = 31, k = 21, t = 2, d = 5;
int length = 31;
int p[6]; /* irreducible polynomial */
int alpha_to[32], index_of[32], g[11];
int recd[31], data[21], bb[11];
int numerr, errpos[32], decerror = 0;
int seed;
void
read_p()
/* Primitive polynomial of degree 5 */
{
register int i;
p[0] = p[2] = p[5] = 1; p[1] = p[3] = p[4] =0;
}
void
generate_gf()
/*
* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
* lookup tables: index->polynomial form alpha_to[] contains j=alpha**i;
* polynomial form -> index form index_of[j=alpha**i] = i alpha=2 is the
* primitive element of GF(2**m)
*/
{
register int i, mask;
mask = 1;
alpha_to[m] = 0;
for (i = 0; i < m; i++) {
alpha_to[i] = mask;
index_of[alpha_to[i]] = i;
if (p[i] != 0)
alpha_to[m] ^= mask;
mask <<= 1;
}
index_of[alpha_to[m]] = m;
mask >>= 1;
for (i = m + 1; i < n; i++) {
if (alpha_to[i - 1] >= mask)
alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1);
else
alpha_to[i] = alpha_to[i - 1] << 1;
index_of[alpha_to[i]] = i;
}
index_of[0] = -1;
}
void
gen_poly()
/*
* Compute generator polynomial of BCH code of length = 31, redundancy = 10
* (OK, this is not very efficient, but we only do it once, right? :)
*/
{
register int ii, jj, ll, kaux;
int test, aux, nocycles, root, noterms, rdncy;
int cycle[15][6], size[15], min[11], zeros[11];
/* Generate cycle sets modulo 31 */
cycle[0][0] = 0; size[0] = 1;
cycle[1][0] = 1; size[1] = 1;
jj = 1; /* cycle set index */
do {
/* Generate the jj-th cycle set */
ii = 0;
do {
ii++;
cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % n;
size[jj]++;
aux = (cycle[jj][ii] * 2) % n;
} while (aux != cycle[jj][0]);
/* Next cycle set representative */
ll = 0;
do {
ll++;
test = 0;
for (ii = 1; ((ii <= jj) && (!test)); ii++)
/* Examine previous cycle sets */
for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++)
if (ll == cycle[ii][kaux])
test = 1;
} while ((test) && (ll < (n - 1)));
if (!(test)) {
jj++; /* next cycle set index */
cycle[jj][0] = ll;
size[jj] = 1;
}
} while (ll < (n - 1));
nocycles = jj; /* number of cycle sets modulo n */
/* Search for roots 1, 2, ..., d-1 in cycle sets */
kaux = 0;
rdncy = 0;
for (ii = 1; ii <= nocycles; ii++) {
min[kaux] = 0;
for (jj = 0; jj < size[ii]; jj++)
for (root = 1; root < d; root++)
if (root == cycle[ii][jj])
min[kaux] = ii;
if (min[kaux]) {
rdncy += size[min[kaux]];
kaux++;
}
}
noterms = kaux;
kaux = 1;
for (ii = 0; ii < noterms; ii++)
for (jj = 0; jj < size[min[ii]]; jj++) {
zeros[kaux] = cycle[min[ii]][jj];
kaux++;
}
printf("This is a (%d, %d, %d) binary BCH code\n", length, k, d);
/* Compute generator polynomial */
g[0] = alpha_to[zeros[1]];
g[1] = 1; /* g(x) = (X + zeros[1]) initially */
for (ii = 2; ii <= rdncy; ii++) {
g[ii] = 1;
for (jj = ii - 1; jj > 0; jj--)
if (g[jj] != 0)
g[jj] = g[jj - 1] ^ alpha_to[(index_of[g[jj]] + zeros[ii]) % n];
else
g[jj] = g[jj - 1];
g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % n];
}
printf("g(x) = ");
for (ii = 0; ii <= rdncy; ii++) {
printf("%d", g[ii]);
if (ii && ((ii % 70) == 0))
printf("\n");
}
printf("\n");
}
void
encode_bch()
/*
* Calculate redundant bits bb[], codeword is c(X) = data(X)*X**(n-k)+ bb(X)
*/
{
register int i, j;
register int feedback;
for (i = 0; i < length - k; i++)
bb[i] = 0;
for (i = k - 1; i >= 0; i--) {
feedback = data[i] ^ bb[length - k - 1];
if (feedback != 0) {
for (j = length - k - 1; j > 0; j--)
if (g[j] != 0)
bb[j] = bb[j - 1] ^ feedback;
else
bb[j] = bb[j - 1];
bb[0] = g[0] && feedback;
} else {
for (j = length - k - 1; j > 0; j--)
bb[j] = bb[j - 1];
bb[0] = 0;
};
};
};
void
decode_bch()
/*
* We do not need the Berlekamp algorithm to decode.
* We solve before hand two equations in two variables.
*/
{
register int i, j, q;
int elp[3], s[5], s3;
int count = 0, syn_error = 0;
int loc[3], err[3], reg[3];
int aux;
/* first form the syndromes */
printf("s[] = (");
for (i = 1; i <= 4; i++) {
s[i] = 0;
for (j = 0; j < length; j++)
if (recd[j] != 0)
s[i] ^= alpha_to[(i * j) % n];
if (s[i] != 0)
syn_error = 1; /* set flag if non-zero syndrome */
/* NOTE: If only error detection is needed,
* then exit the program here...
*/
/* convert syndrome from polynomial form to index form */
s[i] = index_of[s[i]];
printf("%3d ", s[i]);
};
printf(")\n");
if (syn_error) { /* If there are errors, try to correct them */
if (s[1] != -1) {
s3 = (s[1] * 3) % n;
if ( s[3] == s3 ) /* Was it a single error ? */
{
printf("One error at %d\n", s[1]);
recd[s[1]] ^= 1; /* Yes: Correct it */
}
else { /* Assume two errors occurred and solve
* for the coefficients of sigma(x), the
* error locator polynomail
*/
if (s[3] != -1)
aux = alpha_to[s3] ^ alpha_to[s[3]];
else
aux = alpha_to[s3];
elp[0] = 0;
elp[1] = (s[2] - index_of[aux] + n) % n;
elp[2] = (s[1] - index_of[aux] + n) % n;
printf("sigma(x) = ");
for (i = 0; i <= 2; i++)
printf("%3d ", elp[i]);
printf("\n");
printf("Roots: ");
/* find roots of the error location polynomial */
for (i = 1; i <= 2; i++)
reg[i] = elp[i];
count = 0;
for (i = 1; i <= n; i++) { /* Chien search */
q = 1;
for (j = 1; j <= 2; j++)
if (reg[j] != -1) {
reg[j] = (reg[j] + j) % n;
q ^= alpha_to[reg[j]];
}
if (!q) { /* store error location number indices */
loc[count] = i % n;
count++;
printf("%3d ", (i%n));
}
}
printf("\n");
if (count == 2)
/* no. roots = degree of elp hence 2 errors */
for (i = 0; i < 2; i++)
recd[loc[i]] ^= 1;
else /* Cannot solve: Error detection */
printf("incomplete decoding\n");
}
}
else if (s[2] != -1) /* Error detection */
printf("incomplete decoding\n");
}
}
main()
{
int i;
read_p(); /* read generator polynomial g(x) */
generate_gf(); /* generate the Galois Field GF(2**m) */
gen_poly(); /* Compute the generator polynomial of BCH code */
seed = 1;
srandom(seed);
/* Randomly generate DATA */
for (i = 0; i < k; i++)
data[i] = (random() & 67108864) >> 26;
/* ENCODE */
encode_bch(); /* encode data */
for (i = 0; i < length - k; i++)
recd[i] = bb[i]; /* first (length-k) bits are redundancy */
for (i = 0; i < k; i++)
recd[i + length - k] = data[i]; /* last k bits are data */
printf("c(x) = ");
for (i = 0; i < length; i++) {
printf("%1d", recd[i]);
if (i && ((i % 70) == 0))
printf("\n");
}
printf("\n");
/* ERRORS */
printf("Enter the number of errors and their positions: ");
scanf("%d", &numerr);
for (i = 0; i < numerr; i++)
{
scanf("%d", &errpos[i]);
recd[errpos[i]] ^= 1;
}
printf("r(x) = ");
for (i = 0; i < length; i++)
printf("%1d", recd[i]);
printf("\n");
/* DECODE */
decode_bch();
/*
* print out original and decoded data
*/
printf("Results:\n");
printf("original data = ");
for (i = 0; i < k; i++)
printf("%1d", data[i]);
printf("\nrecovered data = ");
for (i = length - k; i < length; i++)
printf("%1d", recd[i]);
printf("\n");
/* decoding errors: we compare only the data portion */
for (i = length - k; i < length; i++)
if (data[i - length + k] != recd[i])
decerror++;
if (decerror)
printf("%d message decoding errors\n", decerror);
else
printf("Succesful decoding\n");
}
Java
package com.zeph.j2se.bch;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;
public class BCH_32_21_5 {
int m = 5, n = 31, k = 21, t = 2, d = 5;
int length = 31;
int p[] = new int[6];
int alpha_to[] = new int[32];
int index_of[] = new int[32];
int g[] = new int[11];
int recd[] = new int[31];
int data[] = new int[21];
int bb[] = new int[11];
int numerr, decerror = 0;
int errpos[] = new int[32];
int seed;
void read_p() {
p[0] = p[2] = p[5] = 1;
p[1] = p[3] = p[4] = 0;
}
void generate_gf() {
int i, mask;
mask = 1;
alpha_to[m] = 0;
for (i = 0; i < m; i++) {
alpha_to[i] = mask;
index_of[alpha_to[i]] = i;
if (p[i] != 0)
alpha_to[m] ^= mask;
mask <<= 1;
}
index_of[alpha_to[m]] = m;
mask >>= 1;
for (i = m + 1; i < n; i++) {
if (alpha_to[i - 1] >= mask)
alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1);
else
alpha_to[i] = alpha_to[i - 1] << 1;
index_of[alpha_to[i]] = i;
}
index_of[0] = -1;
}
void gen_poly() {
int ii, jj, ll, kaux;
int test, aux, nocycles, root, noterms, rdncy;
int cycle[][] = new int[15][6];
int size[] = new int[15];
int min[] = new int[11];
int zeros[] = new int[11];
cycle[0][0] = 0;
size[0] = 1;
cycle[1][0] = 1;
size[1] = 1;
jj = 1;
do {
ii = 0;
do {
ii++;
cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % n;
size[jj]++;
aux = (cycle[jj][ii] * 2) % n;
} while (aux != cycle[jj][0]);
ll = 0;
do {
ll++;
test = 0;
// (!test)
for (ii = 1; ((ii <= jj) && (test == 0)); ii++)
// (!test)
for (kaux = 0; ((kaux < size[ii]) && (test == 0)); kaux++)
if (ll == cycle[ii][kaux])
test = 1;
} while ((test != 0) && (ll < (n - 1)));// test
if (test == 0) {// (!test)
jj++; /* next cycle set index */
cycle[jj][0] = ll;
size[jj] = 1;
}
} while (ll < (n - 1));
nocycles = jj; /* number of cycle sets modulo n */
kaux = 0;
rdncy = 0;
for (ii = 1; ii <= nocycles; ii++) {
min[kaux] = 0;
for (jj = 0; jj < size[ii]; jj++)
for (root = 1; root < d; root++)
if (root == cycle[ii][jj])
min[kaux] = ii;
if (min[kaux] != 0) {
rdncy += size[min[kaux]];
kaux++;
}
}
noterms = kaux;
kaux = 1;
for (ii = 0; ii < noterms; ii++)
for (jj = 0; jj < size[min[ii]]; jj++) {
zeros[kaux] = cycle[min[ii]][jj];
kaux++;
}
System.out.printf("This is a (%d, %d, %d) binary BCH code\n", length,
k, d);
g[0] = alpha_to[zeros[1]];
g[1] = 1; /* g(x) = (X + zeros[1]) initially */
for (ii = 2; ii <= rdncy; ii++) {
g[ii] = 1;
for (jj = ii - 1; jj > 0; jj--)
if (g[jj] != 0)
g[jj] = g[jj - 1]
^ alpha_to[(index_of[g[jj]] + zeros[ii]) % n];
else
g[jj] = g[jj - 1];
g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % n];
}
System.out.printf("g(x) = ");
for (ii = 0; ii <= rdncy; ii++) {
System.out.printf("%d", g[ii]);
if ((ii != 0) && ((ii % 70) == 0))
System.out.printf("\n");
}
System.out.printf("\n");
}
void encode_bch() {
int i, j;
int feedback;
for (i = 0; i < length - k; i++)
bb[i] = 0;
for (i = k - 1; i >= 0; i--) {
feedback = data[i] ^ bb[length - k - 1];
if (feedback != 0) {
for (j = length - k - 1; j > 0; j--)
if (g[j] != 0)
bb[j] = bb[j - 1] ^ feedback;
else
bb[j] = bb[j - 1];
bb[0] = g[0] & feedback;// g[0] && feedback
} else {
for (j = length - k - 1; j > 0; j--)
bb[j] = bb[j - 1];
bb[0] = 0;
}
}
}
void decode_bch() {
int i, j, q;
int elp[] = new int[3], s[] = new int[5], s3;
int count = 0, syn_error = 0;
int loc[] = new int[3], err[] = new int[3], reg[] = new int[3];
int aux;
/* first form the syndromes */
System.out.printf("s[] = (");
for (i = 1; i <= 4; i++) {
s[i] = 0;
for (j = 0; j < length; j++)
if (recd[j] != 0)
s[i] ^= alpha_to[(i * j) % n];
if (s[i] != 0)
syn_error = 1; /* set flag if non-zero syndrome */
/*
* NOTE: If only error detection is needed, then exit the program
* here...
*/
/* convert syndrome from polynomial form to index form */
s[i] = index_of[s[i]];
System.out.printf("%3d ", s[i]);
}
System.out.printf(")\n");
if (syn_error != 0) { /* If there are errors, try to correct them */
if (s[1] != -1) {
s3 = (s[1] * 3) % n;
if (s[3] == s3) /* Was it a single error ? */
{
System.out.printf("One error at %d\n", s[1]);
recd[s[1]] ^= 1; /* Yes: Correct it */
} else { /*
* Assume two errors occurred and solve for the
* coefficients of sigma(x), the error locator
* polynomail
*/
if (s[3] != -1)
aux = alpha_to[s3] ^ alpha_to[s[3]];
else
aux = alpha_to[s3];
elp[0] = 0;
elp[1] = (s[2] - index_of[aux] + n) % n;
elp[2] = (s[1] - index_of[aux] + n) % n;
System.out.printf("sigma(x) = ");
for (i = 0; i <= 2; i++)
System.out.printf("%3d ", elp[i]);
System.out.printf("\n");
System.out.printf("Roots: ");
/* find roots of the error location polynomial */
for (i = 1; i <= 2; i++)
reg[i] = elp[i];
count = 0;
for (i = 1; i <= n; i++) { /* Chien search */
q = 1;
for (j = 1; j <= 2; j++)
if (reg[j] != -1) {
reg[j] = (reg[j] + j) % n;
q ^= alpha_to[reg[j]];
}
if (q == 0) { /* store error location number indices */
loc[count] = i % n;
count++;
System.out.printf("%3d ", (i % n));
}
}
System.out.printf("\n");
if (count == 2)
/* no. roots = degree of elp hence 2 errors */
for (i = 0; i < 2; i++)
recd[loc[i]] ^= 1;
else
/* Cannot solve: Error detection */
System.out.printf("incomplete decoding\n");
}
} else if (s[2] != -1) /* Error detection */
System.out.printf("incomplete decoding\n");
}
}
public void run() {
int i;
read_p(); /* read generator polynomial g(x) */
generate_gf(); /* generate the Galois Field GF(2**m) */
gen_poly(); /* Compute the generator polynomial of BCH code */
seed = 1;
// srand(seed);
Random random = new Random(seed);
/* Randomly generate DATA */
for (i = 0; i < k; i++)
data[i] = (random.nextInt() & 67108864) >> 26;
/* ENCODE */
encode_bch(); /* encode data */
for (i = 0; i < length - k; i++)
recd[i] = bb[i]; /* first (length-k) bits are redundancy */
for (i = 0; i < k; i++)
recd[i + length - k] = data[i]; /* last k bits are data */
System.out.printf("c(x) = ");
for (i = 0; i < length; i++) {
System.out.printf("%1d", recd[i]);
if ((i != 0) && ((i % 70) == 0))
System.out.printf("\n");
}
System.out.printf("\n");
/* ERRORS */
System.out.printf("Enter the number of errors and their positions: ");
BufferedReader wt = new BufferedReader(new InputStreamReader(System.in));
String numerrStr = null;
try {
numerrStr = wt.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
numerr = Integer.valueOf(numerrStr);
for (i = 0; i < numerr; i++) {
String errposStr = null;
try {
errposStr = wt.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
errpos[i] = Integer.valueOf(errposStr);
recd[errpos[i]] ^= 1;
}
System.out.printf("r(x) = ");
for (i = 0; i < length; i++)
System.out.printf("%1d", recd[i]);
System.out.printf("\n");
/* DECODE */
decode_bch();
/*
* print out original and decoded data
*/
System.out.printf("Results:\n");
System.out.printf("original data = ");
for (i = 0; i < k; i++)
System.out.printf("%1d", data[i]);
System.out.printf("\nrecovered data = ");
for (i = length - k; i < length; i++)
System.out.printf("%1d", recd[i]);
System.out.printf("\n");
/* decoding errors: we compare only the data portion */
for (i = length - k; i < length; i++)
if (data[i - length + k] != recd[i])
decerror++;
if (decerror != 0)
System.out.printf("%d message decoding errors\n", decerror);
else
System.out.printf("Succesful decoding\n");
}
public static void main(String[] args) {
BCH_32_21_5 bch_32_21_5 = new BCH_32_21_5();
bch_32_21_5.run();
}
}