|
| 1 | +/* |
| 2 | + * File: bch3.c |
| 3 | + * Title: Encoder/decoder for binary BCH codes in C (Version 3.1) |
| 4 | + * Author: Robert Morelos-Zaragoza |
| 5 | + * Date: August 1994 |
| 6 | + * Revised: June 13, 1997 |
| 7 | + * |
| 8 | + * =============== Encoder/Decoder for binary BCH codes in C ================= |
| 9 | + * |
| 10 | + * Version 1: Original program. The user provides the generator polynomial |
| 11 | + * of the code (cumbersome!). |
| 12 | + * Version 2: Computes the generator polynomial of the code. |
| 13 | + * Version 3: No need to input the coefficients of a primitive polynomial of |
| 14 | + * degree m, used to construct the Galois Field GF(2**m). The |
| 15 | + * program now works for any binary BCH code of length such that: |
| 16 | + * 2**(m-1) - 1 < length <= 2**m - 1 |
| 17 | + * |
| 18 | + * Note: You may have to change the size of the arrays to make it work. |
| 19 | + * |
| 20 | + * The encoding and decoding methods used in this program are based on the |
| 21 | + * book "Error Control Coding: Fundamentals and Applications", by Lin and |
| 22 | + * Costello, Prentice Hall, 1983. |
| 23 | + * |
| 24 | + * Thanks to Patrick Boyle (pboyle@era.com) for his observation that 'bch2.c' |
| 25 | + * did not work for lengths other than 2**m-1 which led to this new version. |
| 26 | + * Portions of this program are from 'rs.c', a Reed-Solomon encoder/decoder |
| 27 | + * in C, written by Simon Rockliff (simon@augean.ua.oz.au) on 21/9/89. The |
| 28 | + * previous version of the BCH encoder/decoder in C, 'bch2.c', was written by |
| 29 | + * Robert Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) on 5/19/92. |
| 30 | + * |
| 31 | + * NOTE: |
| 32 | + * The author is not responsible for any malfunctioning of |
| 33 | + * this program, nor for any damage caused by it. Please include the |
| 34 | + * original program along with these comments in any redistribution. |
| 35 | + * |
| 36 | + * For more information, suggestions, or other ideas on implementing error |
| 37 | + * correcting codes, please contact me at: |
| 38 | + * |
| 39 | + * Robert Morelos-Zaragoza |
| 40 | + * 5120 Woodway, Suite 7036 |
| 41 | + * Houston, Texas 77056 |
| 42 | + * |
| 43 | + * email: r.morelos-zaragoza@ieee.org |
| 44 | + * |
| 45 | + * COPYRIGHT NOTICE: This computer program is free for non-commercial purposes. |
| 46 | + * You may implement this program for any non-commercial application. You may |
| 47 | + * also implement this program for commercial purposes, provided that you |
| 48 | + * obtain my written permission. Any modification of this program is covered |
| 49 | + * by this copyright. |
| 50 | + * |
| 51 | + * == Copyright (c) 1994-7, Robert Morelos-Zaragoza. All rights reserved. == |
| 52 | + * |
| 53 | + * m = order of the Galois field GF(2**m) |
| 54 | + * n = 2**m - 1 = size of the multiplicative group of GF(2**m) |
| 55 | + * length = length of the BCH code |
| 56 | + * t = error correcting capability (max. no. of errors the code corrects) |
| 57 | + * d = 2*t + 1 = designed min. distance = no. of consecutive roots of g(x) + 1 |
| 58 | + * k = n - deg(g(x)) = dimension (no. of information bits/codeword) of the code |
| 59 | + * p[] = coefficients of a primitive polynomial used to generate GF(2**m) |
| 60 | + * g[] = coefficients of the generator polynomial, g(x) |
| 61 | + * alpha_to [] = log table of GF(2**m) |
| 62 | + * index_of[] = antilog table of GF(2**m) |
| 63 | + * data[] = information bits = coefficients of data polynomial, i(x) |
| 64 | + * bb[] = coefficients of redundancy polynomial x^(length-k) i(x) modulo g(x) |
| 65 | + * numerr = number of errors |
| 66 | + * errpos[] = error positions |
| 67 | + * recd[] = coefficients of the received polynomial |
| 68 | + * decerror = number of decoding errors (in _message_ positions) |
| 69 | + * |
| 70 | + */ |
| 71 | + |
| 72 | +#include <math.h> |
| 73 | +#include <stdio.h> |
| 74 | +#include <stdlib.h> |
| 75 | +#include <string.h> |
| 76 | + |
| 77 | +int m, n, length, k, t, d; |
| 78 | +int p[21]; |
| 79 | +int alpha_to[1048576], index_of[1048576], g[548576]; |
| 80 | +int recd[1048576], data[1048576], bb[548576]; |
| 81 | +int seed; |
| 82 | +int numerr, errpos[1024], decerror = 0; |
| 83 | + |
| 84 | +int real_data[][45] = { |
| 85 | + { 1,1,1,1,0,0,0,0, |
| 86 | + 0,1,0,1,1,0,1,0, |
| 87 | + 0,1,1,0,1,0,1,0, |
| 88 | + 0,1,1,0,1,0,1,0, |
| 89 | + 0,0,0,0,0,0,0,1, |
| 90 | + 0,1,1,0,0}, |
| 91 | + |
| 92 | +// 0=f0 1=81 2=52 3=6b 4=71 5=a5 6=63 7=08 |
| 93 | + { 1,1,1,1,0,0,0,0, |
| 94 | + 1,0,0,0,0,0,0,1, |
| 95 | + 0,1,0,1,0,0,1,0, |
| 96 | + 0,1,1,0,1,0,1,1, |
| 97 | + 0,1,1,1,0,0,0,1, |
| 98 | + 1,0,1,0,0}, |
| 99 | + |
| 100 | +// 0=f0 1=85 2=50 3=6a 4=01 5=e5 6=6e 7=84 |
| 101 | + { 1,1,1,1,0,0,0,0, |
| 102 | + 1,0,0,0,0,1,0,1, |
| 103 | + 0,1,0,1,0,0,0,0, |
| 104 | + 0,1,1,0,1,0,1,0, |
| 105 | + 0,0,0,0,0,0,0,1, |
| 106 | + 1,1,1,0,0}, |
| 107 | + |
| 108 | +// 0=f0 1=85 2=59 3=5a 4=01 5=e5 6=6e 7=84 |
| 109 | + { 1,1,1,1,0,0,0,0, |
| 110 | + 1,0,0,0,0,1,0,1, |
| 111 | + 0,1,0,1,1,0,1,0, |
| 112 | + 0,0,0,0,0,0,0,1, |
| 113 | + 1,1,1,0,0}, |
| 114 | + |
| 115 | +// 0=f1 1=34 2=50 3=1a 4=01 5=e5 6=66 7=fe |
| 116 | + { 1,1,1,1,0,0,0,1, |
| 117 | + 0,0,1,1,0,1,0,0, |
| 118 | + 0,1,0,1,0,0,0,0, |
| 119 | + 0,0,0,1,1,0,1,0, |
| 120 | + 0,0,0,0,0,0,0,1, |
| 121 | + 1,1,1,0,0}, |
| 122 | +// 0=f0 1=eb 2=10 3=ea 4=01 5=6e 6=54 7=1c |
| 123 | + { 1,1,1,1,0,0,0,0, |
| 124 | + 1,1,1,0,1,0,1,1, |
| 125 | + 0,0,0,1,0,0,0,0, |
| 126 | + 1,1,1,0,1,0,1,0, |
| 127 | + 0,0,0,0,0,0,0,1, |
| 128 | + 0,1,1,0,1}, |
| 129 | + |
| 130 | +// 0=f0 1=ea 2=5c 3=ea 4=01 5=6e 6=55 7=0e |
| 131 | + { 1,1,1,1,0,0,0,0, |
| 132 | + 1,1,1,0,1,0,1,0, |
| 133 | + 0,1,0,1,1,1,0,0, |
| 134 | + 1,1,1,0,1,0,1,0, |
| 135 | + 0,0,0,0,0,0,0,1, |
| 136 | + 0,1,1,0,1}, |
| 137 | +}; |
| 138 | + |
| 139 | +int expected[][18] = { |
| 140 | + { 0,1,1, 0,0,1,1, 0,0,1,1, 1,1,0,1, 0,0,0 }, |
| 141 | + { 1,0,1, 0,1,1,0, 0,0,1,1, 0,0,0,0, 1,0,0 }, |
| 142 | +//orig { 1,0,1, 0,1,1,0, 1,1,1,0, 1,0,0,0, 0,1,0 }, |
| 143 | + { 1,0,1, 0,0,0,0, 0,1,1,0, 1,0,0,0, 0,1,0 }, // CORRECTED |
| 144 | + { 1,0,1, 0,1,1,0, 1,1,1,0, 1,0,0,0, 0,1,0 }, |
| 145 | + { 1,0,1, 0,1,1,0, 0,1,1,0, 1,1,1,1, 1,1,1 }, |
| 146 | + { 1,1,0, 0,1,0,1, 0,1,0,0, 0,0,0,1, 1,1,0 }, |
| 147 | + { 1,1,0, 0,1,0,1, 0,1,0,1, 0,0,0,0, 1,1,1 }, |
| 148 | +}; |
| 149 | + |
| 150 | +void |
| 151 | +read_p() |
| 152 | +/* |
| 153 | + * Read m, the degree of a primitive polynomial p(x) used to compute the |
| 154 | + * Galois field GF(2**m). Get precomputed coefficients p[] of p(x). Read |
| 155 | + * the code length. |
| 156 | + */ |
| 157 | +{ |
| 158 | + int i, ninf; |
| 159 | + |
| 160 | + printf("bch3: An encoder/decoder for binary BCH codes\n"); |
| 161 | + printf("Copyright (c) 1994-7. Robert Morelos-Zaragoza.\n"); |
| 162 | + printf("This program is free, please read first the copyright notice.\n"); |
| 163 | + printf("\nFirst, enter a value of m such that the code length is\n"); |
| 164 | + printf("2**(m-1) - 1 < length <= 2**m - 1\n\n"); |
| 165 | + do { |
| 166 | + printf("Enter m (between 2 and 20): "); |
| 167 | + scanf("%d", &m); |
| 168 | + } while ( !(m>1) || !(m<21) ); |
| 169 | + for (i=1; i<m; i++) |
| 170 | + p[i] = 0; |
| 171 | + p[0] = p[m] = 1; |
| 172 | + if (m == 2) p[1] = 1; |
| 173 | + else if (m == 3) p[1] = 1; |
| 174 | + else if (m == 4) p[1] = 1; |
| 175 | + else if (m == 5) p[2] = 1; |
| 176 | + else if (m == 6) p[1] = 1; |
| 177 | + else if (m == 7) p[1] = 1; |
| 178 | + else if (m == 8) p[4] = p[5] = p[6] = 1; |
| 179 | + else if (m == 9) p[4] = 1; |
| 180 | + else if (m == 10) p[3] = 1; |
| 181 | + else if (m == 11) p[2] = 1; |
| 182 | + else if (m == 12) p[3] = p[4] = p[7] = 1; |
| 183 | + else if (m == 13) p[1] = p[3] = p[4] = 1; |
| 184 | + else if (m == 14) p[1] = p[11] = p[12] = 1; |
| 185 | + else if (m == 15) p[1] = 1; |
| 186 | + else if (m == 16) p[2] = p[3] = p[5] = 1; |
| 187 | + else if (m == 17) p[3] = 1; |
| 188 | + else if (m == 18) p[7] = 1; |
| 189 | + else if (m == 19) p[1] = p[5] = p[6] = 1; |
| 190 | + else if (m == 20) p[3] = 1; |
| 191 | + printf("p(x) = "); |
| 192 | + n = 1; |
| 193 | + for (i = 0; i <= m; i++) { |
| 194 | + n *= 2; |
| 195 | + printf("%1d", p[i]); |
| 196 | + } |
| 197 | + printf("\n"); |
| 198 | + n = n / 2 - 1; |
| 199 | + ninf = (n + 1) / 2 - 1; |
| 200 | + do { |
| 201 | + printf("Enter code length (%d < length <= %d): ", ninf, n); |
| 202 | + scanf("%d", &length); |
| 203 | + } while ( !((length <= n)&&(length>ninf)) ); |
| 204 | +} |
| 205 | + |
| 206 | + |
| 207 | +void |
| 208 | +generate_gf() |
| 209 | +/* |
| 210 | + * Generate field GF(2**m) from the irreducible polynomial p(X) with |
| 211 | + * coefficients in p[0]..p[m]. |
| 212 | + * |
| 213 | + * Lookup tables: |
| 214 | + * index->polynomial form: alpha_to[] contains j=alpha^i; |
| 215 | + * polynomial form -> index form: index_of[j=alpha^i] = i |
| 216 | + * |
| 217 | + * alpha=2 is the primitive element of GF(2**m) |
| 218 | + */ |
| 219 | +{ |
| 220 | + register int i, mask; |
| 221 | + |
| 222 | + mask = 1; |
| 223 | + alpha_to[m] = 0; |
| 224 | + for (i = 0; i < m; i++) { |
| 225 | + alpha_to[i] = mask; |
| 226 | + index_of[alpha_to[i]] = i; |
| 227 | + if (p[i] != 0) |
| 228 | + alpha_to[m] ^= mask; |
| 229 | + mask <<= 1; |
| 230 | + } |
| 231 | + index_of[alpha_to[m]] = m; |
| 232 | + mask >>= 1; |
| 233 | + for (i = m + 1; i < n; i++) { |
| 234 | + if (alpha_to[i - 1] >= mask) |
| 235 | + alpha_to[i] = alpha_to[m] ^ ((alpha_to[i - 1] ^ mask) << 1); |
| 236 | + else |
| 237 | + alpha_to[i] = alpha_to[i - 1] << 1; |
| 238 | + index_of[alpha_to[i]] = i; |
| 239 | + } |
| 240 | + index_of[0] = -1; |
| 241 | +} |
| 242 | + |
| 243 | + |
| 244 | +void |
| 245 | +gen_poly() |
| 246 | +/* |
| 247 | + * Compute the generator polynomial of a binary BCH code. Fist generate the |
| 248 | + * cycle sets modulo 2**m - 1, cycle[][] = (i, 2*i, 4*i, ..., 2^l*i). Then |
| 249 | + * determine those cycle sets that contain integers in the set of (d-1) |
| 250 | + * consecutive integers {1..(d-1)}. The generator polynomial is calculated |
| 251 | + * as the product of linear factors of the form (x+alpha^i), for every i in |
| 252 | + * the above cycle sets. |
| 253 | + */ |
| 254 | +{ |
| 255 | + register int ii, jj, ll, kaux; |
| 256 | + register int test, aux, nocycles, root, noterms, rdncy; |
| 257 | + int cycle[1024][21], size[1024], min[1024], zeros[1024]; |
| 258 | + |
| 259 | + /* Generate cycle sets modulo n, n = 2**m - 1 */ |
| 260 | + cycle[0][0] = 0; |
| 261 | + size[0] = 1; |
| 262 | + cycle[1][0] = 1; |
| 263 | + size[1] = 1; |
| 264 | + jj = 1; /* cycle set index */ |
| 265 | + if (m > 9) { |
| 266 | + printf("Computing cycle sets modulo %d\n", n); |
| 267 | + printf("(This may take some time)...\n"); |
| 268 | + } |
| 269 | + do { |
| 270 | + /* Generate the jj-th cycle set */ |
| 271 | + ii = 0; |
| 272 | + do { |
| 273 | + ii++; |
| 274 | + cycle[jj][ii] = (cycle[jj][ii - 1] * 2) % n; |
| 275 | + size[jj]++; |
| 276 | + aux = (cycle[jj][ii] * 2) % n; |
| 277 | + } while (aux != cycle[jj][0]); |
| 278 | + /* Next cycle set representative */ |
| 279 | + ll = 0; |
| 280 | + do { |
| 281 | + ll++; |
| 282 | + test = 0; |
| 283 | + for (ii = 1; ((ii <= jj) && (!test)); ii++) |
| 284 | + /* Examine previous cycle sets */ |
| 285 | + for (kaux = 0; ((kaux < size[ii]) && (!test)); kaux++) |
| 286 | + if (ll == cycle[ii][kaux]) |
| 287 | + test = 1; |
| 288 | + } while ((test) && (ll < (n - 1))); |
| 289 | + if (!(test)) { |
| 290 | + jj++; /* next cycle set index */ |
| 291 | + cycle[jj][0] = ll; |
| 292 | + size[jj] = 1; |
| 293 | + } |
| 294 | + } while (ll < (n - 1)); |
| 295 | + nocycles = jj; /* number of cycle sets modulo n */ |
| 296 | + |
| 297 | + printf("Enter the error correcting capability, t: "); |
| 298 | + scanf("%d", &t); |
| 299 | + |
| 300 | + d = 2 * t + 1; |
| 301 | + |
| 302 | + /* Search for roots 1, 2, ..., d-1 in cycle sets */ |
| 303 | + kaux = 0; |
| 304 | + rdncy = 0; |
| 305 | + for (ii = 1; ii <= nocycles; ii++) { |
| 306 | + min[kaux] = 0; |
| 307 | + test = 0; |
| 308 | + for (jj = 0; ((jj < size[ii]) && (!test)); jj++) |
| 309 | + for (root = 1; ((root < d) && (!test)); root++) |
| 310 | + if (root == cycle[ii][jj]) { |
| 311 | + test = 1; |
| 312 | + min[kaux] = ii; |
| 313 | + } |
| 314 | + if (min[kaux]) { |
| 315 | + rdncy += size[min[kaux]]; |
| 316 | + kaux++; |
| 317 | + } |
| 318 | + } |
| 319 | + noterms = kaux; |
| 320 | + kaux = 1; |
| 321 | + for (ii = 0; ii < noterms; ii++) |
| 322 | + for (jj = 0; jj < size[min[ii]]; jj++) { |
| 323 | + zeros[kaux] = cycle[min[ii]][jj]; |
| 324 | + kaux++; |
| 325 | + } |
| 326 | + |
| 327 | + k = length - rdncy; |
| 328 | + |
| 329 | + if (k<0) |
| 330 | + { |
| 331 | + printf("Parameters invalid!\n"); |
| 332 | + exit(0); |
| 333 | + } |
| 334 | + |
| 335 | + printf("This is a (%d, %d, %d) binary BCH code\n", length, k, d); |
| 336 | + |
| 337 | + /* Compute the generator polynomial */ |
| 338 | + g[0] = alpha_to[zeros[1]]; |
| 339 | + g[1] = 1; /* g(x) = (X + zeros[1]) initially */ |
| 340 | + for (ii = 2; ii <= rdncy; ii++) { |
| 341 | + g[ii] = 1; |
| 342 | + for (jj = ii - 1; jj > 0; jj--) |
| 343 | + if (g[jj] != 0) |
| 344 | + g[jj] = g[jj - 1] ^ alpha_to[(index_of[g[jj]] + zeros[ii]) % n]; |
| 345 | + else |
| 346 | + g[jj] = g[jj - 1]; |
| 347 | + g[0] = alpha_to[(index_of[g[0]] + zeros[ii]) % n]; |
| 348 | + } |
| 349 | + printf("Generator polynomial:\ng(x) = "); |
| 350 | + for (ii = 0; ii <= rdncy; ii++) { |
| 351 | + printf("%d", g[ii]); |
| 352 | + if (ii && ((ii % 50) == 0)) |
| 353 | + printf("\n"); |
| 354 | + } |
| 355 | + printf("\n"); |
| 356 | +} |
| 357 | + |
| 358 | + |
| 359 | +void |
| 360 | +encode_bch() |
| 361 | +/* |
| 362 | + * Compute redundacy bb[], the coefficients of b(x). The redundancy |
| 363 | + * polynomial b(x) is the remainder after dividing x^(length-k)*data(x) |
| 364 | + * by the generator polynomial g(x). |
| 365 | + */ |
| 366 | +{ |
| 367 | + register int i, j; |
| 368 | + register int feedback; |
| 369 | + |
| 370 | + for (i = 0; i < length - k; i++) |
| 371 | + bb[i] = 0; |
| 372 | + for (i = k - 1; i >= 0; i--) { |
| 373 | + feedback = data[i] ^ bb[length - k - 1]; |
| 374 | + if (feedback != 0) { |
| 375 | + for (j = length - k - 1; j > 0; j--) |
| 376 | + if (g[j] != 0) |
| 377 | + bb[j] = bb[j - 1] ^ feedback; |
| 378 | + else |
| 379 | + bb[j] = bb[j - 1]; |
| 380 | + bb[0] = g[0] && feedback; |
| 381 | + } else { |
| 382 | + for (j = length - k - 1; j > 0; j--) |
| 383 | + bb[j] = bb[j - 1]; |
| 384 | + bb[0] = 0; |
| 385 | + } |
| 386 | + } |
| 387 | +} |
| 388 | + |
| 389 | + |
| 390 | +void |
| 391 | +decode_bch() |
| 392 | +/* |
| 393 | + * Simon Rockliff's implementation of Berlekamp's algorithm. |
| 394 | + * |
| 395 | + * Assume we have received bits in recd[i], i=0..(n-1). |
| 396 | + * |
| 397 | + * Compute the 2*t syndromes by substituting alpha^i into rec(X) and |
| 398 | + * evaluating, storing the syndromes in s[i], i=1..2t (leave s[0] zero) . |
| 399 | + * Then we use the Berlekamp algorithm to find the error location polynomial |
| 400 | + * elp[i]. |
| 401 | + * |
| 402 | + * If the degree of the elp is >t, then we cannot correct all the errors, and |
| 403 | + * we have detected an uncorrectable error pattern. We output the information |
| 404 | + * bits uncorrected. |
| 405 | + * |
| 406 | + * If the degree of elp is <=t, we substitute alpha^i , i=1..n into the elp |
| 407 | + * to get the roots, hence the inverse roots, the error location numbers. |
| 408 | + * This step is usually called "Chien's search". |
| 409 | + * |
| 410 | + * If the number of errors located is not equal the degree of the elp, then |
| 411 | + * the decoder assumes that there are more than t errors and cannot correct |
| 412 | + * them, only detect them. We output the information bits uncorrected. |
| 413 | + */ |
| 414 | +{ |
| 415 | + register int i, j, u, q, t2, count = 0, syn_error = 0; |
| 416 | + int elp[1026][1024], d[1026], l[1026], u_lu[1026], s[1025]; |
| 417 | + int root[200], loc[200], err[1024], reg[201]; |
| 418 | + |
| 419 | + t2 = 2 * t; |
| 420 | + |
| 421 | + /* first form the syndromes */ |
| 422 | + printf("S(x) = "); |
| 423 | + for (i = 1; i <= t2; i++) { |
| 424 | + s[i] = 0; |
| 425 | + for (j = 0; j < length; j++) |
| 426 | + if (recd[j] != 0) |
| 427 | + s[i] ^= alpha_to[(i * j) % n]; |
| 428 | + if (s[i] != 0) |
| 429 | + syn_error = 1; /* set error flag if non-zero syndrome */ |
| 430 | +/* |
| 431 | + * Note: If the code is used only for ERROR DETECTION, then |
| 432 | + * exit program here indicating the presence of errors. |
| 433 | + */ |
| 434 | + /* convert syndrome from polynomial form to index form */ |
| 435 | + s[i] = index_of[s[i]]; |
| 436 | + printf("%3d ", s[i]); |
| 437 | + } |
| 438 | + printf("\n"); |
| 439 | + |
| 440 | + if (syn_error) { /* if there are errors, try to correct them */ |
| 441 | + /* |
| 442 | + * Compute the error location polynomial via the Berlekamp |
| 443 | + * iterative algorithm. Following the terminology of Lin and |
| 444 | + * Costello's book : d[u] is the 'mu'th discrepancy, where |
| 445 | + * u='mu'+1 and 'mu' (the Greek letter!) is the step number |
| 446 | + * ranging from -1 to 2*t (see L&C), l[u] is the degree of |
| 447 | + * the elp at that step, and u_l[u] is the difference between |
| 448 | + * the step number and the degree of the elp. |
| 449 | + */ |
| 450 | + /* initialise table entries */ |
| 451 | + d[0] = 0; /* index form */ |
| 452 | + d[1] = s[1]; /* index form */ |
| 453 | + elp[0][0] = 0; /* index form */ |
| 454 | + elp[1][0] = 1; /* polynomial form */ |
| 455 | + for (i = 1; i < t2; i++) { |
| 456 | + elp[0][i] = -1; /* index form */ |
| 457 | + elp[1][i] = 0; /* polynomial form */ |
| 458 | + } |
| 459 | + l[0] = 0; |
| 460 | + l[1] = 0; |
| 461 | + u_lu[0] = -1; |
| 462 | + u_lu[1] = 0; |
| 463 | + u = 0; |
| 464 | + |
| 465 | + do { |
| 466 | + u++; |
| 467 | + if (d[u] == -1) { |
| 468 | + l[u + 1] = l[u]; |
| 469 | + for (i = 0; i <= l[u]; i++) { |
| 470 | + elp[u + 1][i] = elp[u][i]; |
| 471 | + elp[u][i] = index_of[elp[u][i]]; |
| 472 | + } |
| 473 | + } else |
| 474 | + /* |
| 475 | + * search for words with greatest u_lu[q] for |
| 476 | + * which d[q]!=0 |
| 477 | + */ |
| 478 | + { |
| 479 | + q = u - 1; |
| 480 | + while ((d[q] == -1) && (q > 0)) |
| 481 | + q--; |
| 482 | + /* have found first non-zero d[q] */ |
| 483 | + if (q > 0) { |
| 484 | + j = q; |
| 485 | + do { |
| 486 | + j--; |
| 487 | + if ((d[j] != -1) && (u_lu[q] < u_lu[j])) |
| 488 | + q = j; |
| 489 | + } while (j > 0); |
| 490 | + } |
| 491 | + |
| 492 | + /* |
| 493 | + * have now found q such that d[u]!=0 and |
| 494 | + * u_lu[q] is maximum |
| 495 | + */ |
| 496 | + /* store degree of new elp polynomial */ |
| 497 | + if (l[u] > l[q] + u - q) |
| 498 | + l[u + 1] = l[u]; |
| 499 | + else |
| 500 | + l[u + 1] = l[q] + u - q; |
| 501 | + |
| 502 | + /* form new elp(x) */ |
| 503 | + for (i = 0; i < t2; i++) |
| 504 | + elp[u + 1][i] = 0; |
| 505 | + for (i = 0; i <= l[q]; i++) |
| 506 | + if (elp[q][i] != -1) |
| 507 | + elp[u + 1][i + u - q] = |
| 508 | + alpha_to[(d[u] + n - d[q] + elp[q][i]) % n]; |
| 509 | + for (i = 0; i <= l[u]; i++) { |
| 510 | + elp[u + 1][i] ^= elp[u][i]; |
| 511 | + elp[u][i] = index_of[elp[u][i]]; |
| 512 | + } |
| 513 | + } |
| 514 | + u_lu[u + 1] = u - l[u + 1]; |
| 515 | + |
| 516 | + /* form (u+1)th discrepancy */ |
| 517 | + if (u < t2) { |
| 518 | + /* no discrepancy computed on last iteration */ |
| 519 | + if (s[u + 1] != -1) |
| 520 | + d[u + 1] = alpha_to[s[u + 1]]; |
| 521 | + else |
| 522 | + d[u + 1] = 0; |
| 523 | + for (i = 1; i <= l[u + 1]; i++) |
| 524 | + if ((s[u + 1 - i] != -1) && (elp[u + 1][i] != 0)) |
| 525 | + d[u + 1] ^= alpha_to[(s[u + 1 - i] |
| 526 | + + index_of[elp[u + 1][i]]) % n]; |
| 527 | + /* put d[u+1] into index form */ |
| 528 | + d[u + 1] = index_of[d[u + 1]]; |
| 529 | + } |
| 530 | + } while ((u < t2) && (l[u + 1] <= t)); |
| 531 | + |
| 532 | + u++; |
| 533 | + if (l[u] <= t) {/* Can correct errors */ |
| 534 | + /* put elp into index form */ |
| 535 | + for (i = 0; i <= l[u]; i++) |
| 536 | + elp[u][i] = index_of[elp[u][i]]; |
| 537 | + |
| 538 | + printf("sigma(x) = "); |
| 539 | + for (i = 0; i <= l[u]; i++) |
| 540 | + printf("%3d ", elp[u][i]); |
| 541 | + printf("\n"); |
| 542 | + printf("Roots: "); |
| 543 | + |
| 544 | + /* Chien search: find roots of the error location polynomial */ |
| 545 | + for (i = 1; i <= l[u]; i++) |
| 546 | + reg[i] = elp[u][i]; |
| 547 | + count = 0; |
| 548 | + for (i = 1; i <= n; i++) { |
| 549 | + q = 1; |
| 550 | + for (j = 1; j <= l[u]; j++) |
| 551 | + if (reg[j] != -1) { |
| 552 | + reg[j] = (reg[j] + j) % n; |
| 553 | + q ^= alpha_to[reg[j]]; |
| 554 | + } |
| 555 | + if (!q) { /* store root and error |
| 556 | + * location number indices */ |
| 557 | + root[count] = i; |
| 558 | + loc[count] = n - i; |
| 559 | + count++; |
| 560 | + printf("%3d ", n - i); |
| 561 | + } |
| 562 | + } |
| 563 | + printf("\n"); |
| 564 | + if (count == l[u]) |
| 565 | + /* no. roots = degree of elp hence <= t errors */ |
| 566 | + for (i = 0; i < l[u]; i++) |
| 567 | + recd[loc[i]] ^= 1; |
| 568 | + else /* elp has degree >t hence cannot solve */ |
| 569 | + printf("Incomplete decoding: errors detected\n"); |
| 570 | + } |
| 571 | + } |
| 572 | +} |
| 573 | + |
| 574 | + |
| 575 | + |
| 576 | +int main() |
| 577 | +{ |
| 578 | + int i; |
| 579 | + |
| 580 | + read_p(); /* Read m */ |
| 581 | + generate_gf(); /* Construct the Galois Field GF(2**m) */ |
| 582 | + gen_poly(); /* Compute the generator polynomial of BCH code */ |
| 583 | + |
| 584 | +#ifdef TEST |
| 585 | +for (int count = 0; count < sizeof(real_data) / sizeof(*real_data); count++) { |
| 586 | + memcpy(data, real_data[count], sizeof(*real_data)); |
| 587 | +#else |
| 588 | + /* Randomly generate DATA */ |
| 589 | + seed = 131073; |
| 590 | + srandom(seed); |
| 591 | + for (i = 0; i < k; i++) |
| 592 | + data[i] = ( random() & 65536 ) >> 16; |
| 593 | +#endif |
| 594 | + encode_bch(); /* encode data */ |
| 595 | + |
| 596 | + /* |
| 597 | + * recd[] are the coefficients of c(x) = x**(length-k)*data(x) + b(x) |
| 598 | + */ |
| 599 | + for (i = 0; i < length - k; i++) |
| 600 | + recd[i] = bb[i]; |
| 601 | + for (i = 0; i < k; i++) |
| 602 | + recd[i + length - k] = data[i]; |
| 603 | + printf("Code polynomial:\nc(x) = "); |
| 604 | + for (i = 0; i < length; i++) { |
| 605 | + printf("%1d", recd[i]); |
| 606 | + if (i && ((i % 50) == 0)) |
| 607 | + printf("\n"); |
| 608 | + } |
| 609 | + printf("\n"); |
| 610 | + |
| 611 | + printf("Enter the number of errors:\n"); |
| 612 | + scanf("%d", &numerr); /* CHANNEL errors */ |
| 613 | + printf("Enter error locations (integers between"); |
| 614 | + printf(" 0 and %d): ", length-1); |
| 615 | + /* |
| 616 | + * recd[] are the coefficients of r(x) = c(x) + e(x) |
| 617 | + */ |
| 618 | + for (i = 0; i < numerr; i++) |
| 619 | + scanf("%d", &errpos[i]); |
| 620 | + if (numerr) |
| 621 | + for (i = 0; i < numerr; i++) |
| 622 | + recd[errpos[i]] ^= 1; |
| 623 | + printf("r(x) = "); |
| 624 | + for (i = 0; i < length; i++) { |
| 625 | + printf("%1d", recd[i]); |
| 626 | +if (i == length - k - 1) printf(" "); |
| 627 | + //if (i && ((i % 50) == 0)) |
| 628 | + //printf("\n"); |
| 629 | + } |
| 630 | + printf("\n"); |
| 631 | + |
| 632 | + decode_bch(); /* DECODE received codeword recv[] */ |
| 633 | + |
| 634 | + /* |
| 635 | + * print out original and decoded data |
| 636 | + */ |
| 637 | + printf("Results:\n"); |
| 638 | + printf("original data = "); |
| 639 | + for (i = 0; i < k; i++) { |
| 640 | + printf("%1d", data[i]); |
| 641 | + if (i && ((i % 50) == 0)) |
| 642 | + printf("\n"); |
| 643 | + } |
| 644 | + printf("\nrecovered data = "); |
| 645 | + for (i = length - k; i < length; i++) { |
| 646 | + printf("%1d", recd[i]); |
| 647 | + if ((i-length+k) && (((i-length+k) % 50) == 0)) |
| 648 | + printf("\n"); |
| 649 | + } |
| 650 | + printf("\n"); |
| 651 | + |
| 652 | + int flag = 0; |
| 653 | +printf("n=%d, k=%d, length=%d\n", n, k, length); |
| 654 | +#ifdef TEST |
| 655 | + for (int jj = 0; jj < n - k; jj++) { |
| 656 | + if (expected[count][jj] != recd[jj]) { |
| 657 | + printf("bit %d: expected %d calc: %d\n", jj, expected[count][jj], recd[jj]); |
| 658 | + flag++; |
| 659 | + } |
| 660 | + } |
| 661 | + printf("%d ERRORS.\n", flag); |
| 662 | +#endif |
| 663 | + |
| 664 | + /* |
| 665 | + * DECODING ERRORS? we compare only the data portion |
| 666 | + */ |
| 667 | + for (i = length - k; i < length; i++) |
| 668 | + if (data[i - length + k] != recd[i]) |
| 669 | + decerror++; |
| 670 | + if (decerror) |
| 671 | + printf("There were %d decoding errors in message positions\n", decerror); |
| 672 | + else |
| 673 | + printf("Succesful decoding\n"); |
| 674 | +#ifdef TEST |
| 675 | + } |
| 676 | +#endif |
| 677 | +} |
0 commit comments