JPWL version 1.0 by Universita' degli Studi di Perugia
[openjpeg.git] / jpwl / rs.c
1  /*\r
2  * Copyright (c) 2001-2003, David Janssens\r
3  * Copyright (c) 2002-2003, Yannick Verschueren\r
4  * Copyright (c) 2003-2005, Francois Devaux and Antonin Descampe\r
5  * Copyright (c) 2005, Herv� Drolon, FreeImage Team\r
6  * Copyright (c) 2002-2005, Communications and remote sensing Laboratory, Universite catholique de Louvain, Belgium\r
7  * Copyright (c) 2005-2006, Dept. of Electronic and Information Engineering, Universita' degli Studi di Perugia, Italy\r
8  * All rights reserved.\r
9  *\r
10  * Redistribution and use in source and binary forms, with or without\r
11  * modification, are permitted provided that the following conditions\r
12  * are met:\r
13  * 1. Redistributions of source code must retain the above copyright\r
14  *    notice, this list of conditions and the following disclaimer.\r
15  * 2. Redistributions in binary form must reproduce the above copyright\r
16  *    notice, this list of conditions and the following disclaimer in the\r
17  *    documentation and/or other materials provided with the distribution.\r
18  *\r
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'\r
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
29  * POSSIBILITY OF SUCH DAMAGE.\r
30  */\r
31 \r
32 #ifdef USE_JPWL\r
33 \r
34 /**\r
35 @file rs.c\r
36 @brief Functions used to compute the Reed-Solomon parity and check of byte arrays\r
37 \r
38 */\r
39 \r
40 /**\r
41  * Reed-Solomon coding and decoding\r
42  * Phil Karn (karn@ka9q.ampr.org) September 1996\r
43  * \r
44  * This file is derived from the program "new_rs_erasures.c" by Robert\r
45  * Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy\r
46  * (harit@spectra.eng.hawaii.edu), Aug 1995\r
47  *\r
48  * I've made changes to improve performance, clean up the code and make it\r
49  * easier to follow. Data is now passed to the encoding and decoding functions\r
50  * through arguments rather than in global arrays. The decode function returns\r
51  * the number of corrected symbols, or -1 if the word is uncorrectable.\r
52  *\r
53  * This code supports a symbol size from 2 bits up to 16 bits,\r
54  * implying a block size of 3 2-bit symbols (6 bits) up to 65535\r
55  * 16-bit symbols (1,048,560 bits). The code parameters are set in rs.h.\r
56  *\r
57  * Note that if symbols larger than 8 bits are used, the type of each\r
58  * data array element switches from unsigned char to unsigned int. The\r
59  * caller must ensure that elements larger than the symbol range are\r
60  * not passed to the encoder or decoder.\r
61  *\r
62  */\r
63 #include <stdio.h>\r
64 #include <stdlib.h>\r
65 #include "rs.h"\r
66 \r
67 /* This defines the type used to store an element of the Galois Field\r
68  * used by the code. Make sure this is something larger than a char if\r
69  * if anything larger than GF(256) is used.\r
70  *\r
71  * Note: unsigned char will work up to GF(256) but int seems to run\r
72  * faster on the Pentium.\r
73  */\r
74 typedef int gf;\r
75 \r
76 /* Primitive polynomials - see Lin & Costello, Appendix A,\r
77  * and  Lee & Messerschmitt, p. 453.\r
78  */\r
79 #if(MM == 2)/* Admittedly silly */\r
80 int Pp[MM+1] = { 1, 1, 1 };\r
81 \r
82 #elif(MM == 3)\r
83 /* 1 + x + x^3 */\r
84 int Pp[MM+1] = { 1, 1, 0, 1 };\r
85 \r
86 #elif(MM == 4)\r
87 /* 1 + x + x^4 */\r
88 int Pp[MM+1] = { 1, 1, 0, 0, 1 };\r
89 \r
90 #elif(MM == 5)\r
91 /* 1 + x^2 + x^5 */\r
92 int Pp[MM+1] = { 1, 0, 1, 0, 0, 1 };\r
93 \r
94 #elif(MM == 6)\r
95 /* 1 + x + x^6 */\r
96 int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1 };\r
97 \r
98 #elif(MM == 7)\r
99 /* 1 + x^3 + x^7 */\r
100 int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 1 };\r
101 \r
102 #elif(MM == 8)\r
103 /* 1+x^2+x^3+x^4+x^8 */\r
104 int Pp[MM+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };\r
105 \r
106 #elif(MM == 9)\r
107 /* 1+x^4+x^9 */\r
108 int Pp[MM+1] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };\r
109 \r
110 #elif(MM == 10)\r
111 /* 1+x^3+x^10 */\r
112 int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };\r
113 \r
114 #elif(MM == 11)\r
115 /* 1+x^2+x^11 */\r
116 int Pp[MM+1] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };\r
117 \r
118 #elif(MM == 12)\r
119 /* 1+x+x^4+x^6+x^12 */\r
120 int Pp[MM+1] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };\r
121 \r
122 #elif(MM == 13)\r
123 /* 1+x+x^3+x^4+x^13 */\r
124 int Pp[MM+1] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };\r
125 \r
126 #elif(MM == 14)\r
127 /* 1+x+x^6+x^10+x^14 */\r
128 int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };\r
129 \r
130 #elif(MM == 15)\r
131 /* 1+x+x^15 */\r
132 int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };\r
133 \r
134 #elif(MM == 16)\r
135 /* 1+x+x^3+x^12+x^16 */\r
136 int Pp[MM+1] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };\r
137 \r
138 #else\r
139 #error "MM must be in range 2-16"\r
140 #endif\r
141 \r
142 /* Alpha exponent for the first root of the generator polynomial */\r
143 #define B0      0  /* Different from the default 1 */\r
144 \r
145 /* index->polynomial form conversion table */\r
146 gf Alpha_to[NN + 1];\r
147 \r
148 /* Polynomial->index form conversion table */\r
149 gf Index_of[NN + 1];\r
150 \r
151 /* No legal value in index form represents zero, so\r
152  * we need a special value for this purpose\r
153  */\r
154 #define A0      (NN)\r
155 \r
156 /* Generator polynomial g(x)\r
157  * Degree of g(x) = 2*TT\r
158  * has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)\r
159  */\r
160 /*gf Gg[NN - KK + 1];*/\r
161 gf              Gg[NN - 1];\r
162 \r
163 /* Compute x % NN, where NN is 2**MM - 1,\r
164  * without a slow divide\r
165  */\r
166 static /*inline*/ gf\r
167 modnn(int x)\r
168 {\r
169         while (x >= NN) {\r
170                 x -= NN;\r
171                 x = (x >> MM) + (x & NN);\r
172         }\r
173         return x;\r
174 }\r
175 \r
176 /*#define       min(a,b)        ((a) < (b) ? (a) : (b))*/\r
177 \r
178 #define CLEAR(a,n) {\\r
179         int ci;\\r
180         for(ci=(n)-1;ci >=0;ci--)\\r
181                 (a)[ci] = 0;\\r
182         }\r
183 \r
184 #define COPY(a,b,n) {\\r
185         int ci;\\r
186         for(ci=(n)-1;ci >=0;ci--)\\r
187                 (a)[ci] = (b)[ci];\\r
188         }\r
189 #define COPYDOWN(a,b,n) {\\r
190         int ci;\\r
191         for(ci=(n)-1;ci >=0;ci--)\\r
192                 (a)[ci] = (b)[ci];\\r
193         }\r
194 \r
195 void init_rs(int k)\r
196 {\r
197         KK = k;\r
198         if (KK >= NN) {\r
199                 printf("KK must be less than 2**MM - 1\n");\r
200                 exit(1);\r
201         }\r
202         \r
203         generate_gf();\r
204         gen_poly();\r
205 }\r
206 \r
207 /* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]\r
208    lookup tables:  index->polynomial form   alpha_to[] contains j=alpha**i;\r
209                    polynomial form -> index form  index_of[j=alpha**i] = i\r
210    alpha=2 is the primitive element of GF(2**m)\r
211    HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:\r
212         Let @ represent the primitive element commonly called "alpha" that\r
213    is the root of the primitive polynomial p(x). Then in GF(2^m), for any\r
214    0 <= i <= 2^m-2,\r
215         @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)\r
216    where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation\r
217    of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for\r
218    example the polynomial representation of @^5 would be given by the binary\r
219    representation of the integer "alpha_to[5]".\r
220                    Similarily, index_of[] can be used as follows:\r
221         As above, let @ represent the primitive element of GF(2^m) that is\r
222    the root of the primitive polynomial p(x). In order to find the power\r
223    of @ (alpha) that has the polynomial representation\r
224         a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)\r
225    we consider the integer "i" whose binary representation with a(0) being LSB\r
226    and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry\r
227    "index_of[i]". Now, @^index_of[i] is that element whose polynomial \r
228     representation is (a(0),a(1),a(2),...,a(m-1)).\r
229    NOTE:\r
230         The element alpha_to[2^m-1] = 0 always signifying that the\r
231    representation of "@^infinity" = 0 is (0,0,0,...,0).\r
232         Similarily, the element index_of[0] = A0 always signifying\r
233    that the power of alpha which has the polynomial representation\r
234    (0,0,...,0) is "infinity".\r
235  \r
236 */\r
237 \r
238 void\r
239 generate_gf(void)\r
240 {\r
241         register int i, mask;\r
242 \r
243         mask = 1;\r
244         Alpha_to[MM] = 0;\r
245         for (i = 0; i < MM; i++) {\r
246                 Alpha_to[i] = mask;\r
247                 Index_of[Alpha_to[i]] = i;\r
248                 /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */\r
249                 if (Pp[i] != 0)\r
250                         Alpha_to[MM] ^= mask;   /* Bit-wise EXOR operation */\r
251                 mask <<= 1;     /* single left-shift */\r
252         }\r
253         Index_of[Alpha_to[MM]] = MM;\r
254         /*\r
255          * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by\r
256          * poly-repr of @^i shifted left one-bit and accounting for any @^MM\r
257          * term that may occur when poly-repr of @^i is shifted.\r
258          */\r
259         mask >>= 1;\r
260         for (i = MM + 1; i < NN; i++) {\r
261                 if (Alpha_to[i - 1] >= mask)\r
262                         Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);\r
263                 else\r
264                         Alpha_to[i] = Alpha_to[i - 1] << 1;\r
265                 Index_of[Alpha_to[i]] = i;\r
266         }\r
267         Index_of[0] = A0;\r
268         Alpha_to[NN] = 0;\r
269 }\r
270 \r
271 \r
272 /*\r
273  * Obtain the generator polynomial of the TT-error correcting, length\r
274  * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0,\r
275  * ... ,(2*TT-1)\r
276  *\r
277  * Examples:\r
278  *\r
279  * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2.\r
280  * g(x) = (x+@) (x+@**2)\r
281  *\r
282  * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4.\r
283  * g(x) = (x+1) (x+@) (x+@**2) (x+@**3)\r
284  */\r
285 void\r
286 gen_poly(void)\r
287 {\r
288         register int i, j;\r
289 \r
290         Gg[0] = Alpha_to[B0];\r
291         Gg[1] = 1;              /* g(x) = (X+@**B0) initially */\r
292         for (i = 2; i <= NN - KK; i++) {\r
293                 Gg[i] = 1;\r
294                 /*\r
295                  * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by\r
296                  * (@**(B0+i-1) + x)\r
297                  */\r
298                 for (j = i - 1; j > 0; j--)\r
299                         if (Gg[j] != 0)\r
300                                 Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)];\r
301                         else\r
302                                 Gg[j] = Gg[j - 1];\r
303                 /* Gg[0] can never be zero */\r
304                 Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)];\r
305         }\r
306         /* convert Gg[] to index form for quicker encoding */\r
307         for (i = 0; i <= NN - KK; i++)\r
308                 Gg[i] = Index_of[Gg[i]];\r
309 }\r
310 \r
311 \r
312 /*\r
313  * take the string of symbols in data[i], i=0..(k-1) and encode\r
314  * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[]\r
315  * is input and bb[] is output in polynomial form. Encoding is done by using\r
316  * a feedback shift register with appropriate connections specified by the\r
317  * elements of Gg[], which was generated above. Codeword is   c(X) =\r
318  * data(X)*X**(NN-KK)+ b(X)\r
319  */\r
320 int\r
321 encode_rs(dtype *data, dtype *bb)\r
322 {\r
323         register int i, j;\r
324         gf feedback;\r
325 \r
326         CLEAR(bb,NN-KK);\r
327         for (i = KK - 1; i >= 0; i--) {\r
328 #if (MM != 8)\r
329                 if(data[i] > NN)\r
330                         return -1;      /* Illegal symbol */\r
331 #endif\r
332                 feedback = Index_of[data[i] ^ bb[NN - KK - 1]];\r
333                 if (feedback != A0) {   /* feedback term is non-zero */\r
334                         for (j = NN - KK - 1; j > 0; j--)\r
335                                 if (Gg[j] != A0)\r
336                                         bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)];\r
337                                 else\r
338                                         bb[j] = bb[j - 1];\r
339                         bb[0] = Alpha_to[modnn(Gg[0] + feedback)];\r
340                 } else {        /* feedback term is zero. encoder becomes a\r
341                                  * single-byte shifter */\r
342                         for (j = NN - KK - 1; j > 0; j--)\r
343                                 bb[j] = bb[j - 1];\r
344                         bb[0] = 0;\r
345                 }\r
346         }\r
347         return 0;\r
348 }\r
349 \r
350 /*\r
351  * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful,\r
352  * writes the codeword into data[] itself. Otherwise data[] is unaltered.\r
353  *\r
354  * Return number of symbols corrected, or -1 if codeword is illegal\r
355  * or uncorrectable.\r
356  * \r
357  * First "no_eras" erasures are declared by the calling program. Then, the\r
358  * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).\r
359  * If the number of channel errors is not greater than "t_after_eras" the\r
360  * transmitted codeword will be recovered. Details of algorithm can be found\r
361  * in R. Blahut's "Theory ... of Error-Correcting Codes".\r
362  */\r
363 int\r
364 eras_dec_rs(dtype *data, int *eras_pos, int no_eras)\r
365 {\r
366         int deg_lambda, el, deg_omega;\r
367         int i, j, r;\r
368         gf u,q,tmp,num1,num2,den,discr_r;\r
369         gf recd[NN];\r
370         /* Err+Eras Locator poly and syndrome poly */\r
371         /*gf lambda[NN-KK + 1], s[NN-KK + 1];   \r
372         gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];\r
373         gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];*/\r
374         gf lambda[NN + 1], s[NN + 1];   \r
375         gf b[NN + 1], t[NN + 1], omega[NN + 1];\r
376         gf root[NN], reg[NN + 1], loc[NN];\r
377         int syn_error, count;\r
378 \r
379         /* data[] is in polynomial form, copy and convert to index form */\r
380         for (i = NN-1; i >= 0; i--){\r
381 #if (MM != 8)\r
382                 if(data[i] > NN)\r
383                         return -1;      /* Illegal symbol */\r
384 #endif\r
385                 recd[i] = Index_of[data[i]];\r
386         }\r
387         /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)\r
388          * namely @**(B0+i), i = 0, ... ,(NN-KK-1)\r
389          */\r
390         syn_error = 0;\r
391         for (i = 1; i <= NN-KK; i++) {\r
392                 tmp = 0;\r
393                 for (j = 0; j < NN; j++)\r
394                         if (recd[j] != A0)      /* recd[j] in index form */\r
395                                 tmp ^= Alpha_to[modnn(recd[j] + (B0+i-1)*j)];\r
396                 syn_error |= tmp;       /* set flag if non-zero syndrome =>\r
397                                          * error */\r
398                 /* store syndrome in index form  */\r
399                 s[i] = Index_of[tmp];\r
400         }\r
401         if (!syn_error) {\r
402                 /*\r
403                  * if syndrome is zero, data[] is a codeword and there are no\r
404                  * errors to correct. So return data[] unmodified\r
405                  */\r
406                 return 0;\r
407         }\r
408         CLEAR(&lambda[1],NN-KK);\r
409         lambda[0] = 1;\r
410         if (no_eras > 0) {\r
411                 /* Init lambda to be the erasure locator polynomial */\r
412                 lambda[1] = Alpha_to[eras_pos[0]];\r
413                 for (i = 1; i < no_eras; i++) {\r
414                         u = eras_pos[i];\r
415                         for (j = i+1; j > 0; j--) {\r
416                                 tmp = Index_of[lambda[j - 1]];\r
417                                 if(tmp != A0)\r
418                                         lambda[j] ^= Alpha_to[modnn(u + tmp)];\r
419                         }\r
420                 }\r
421 #ifdef ERASURE_DEBUG\r
422                 /* find roots of the erasure location polynomial */\r
423                 for(i=1;i<=no_eras;i++)\r
424                         reg[i] = Index_of[lambda[i]];\r
425                 count = 0;\r
426                 for (i = 1; i <= NN; i++) {\r
427                         q = 1;\r
428                         for (j = 1; j <= no_eras; j++)\r
429                                 if (reg[j] != A0) {\r
430                                         reg[j] = modnn(reg[j] + j);\r
431                                         q ^= Alpha_to[reg[j]];\r
432                                 }\r
433                         if (!q) {\r
434                                 /* store root and error location\r
435                                  * number indices\r
436                                  */\r
437                                 root[count] = i;\r
438                                 loc[count] = NN - i;\r
439                                 count++;\r
440                         }\r
441                 }\r
442                 if (count != no_eras) {\r
443                         printf("\n lambda(x) is WRONG\n");\r
444                         return -1;\r
445                 }\r
446 #ifndef NO_PRINT\r
447                 printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");\r
448                 for (i = 0; i < count; i++)\r
449                         printf("%d ", loc[i]);\r
450                 printf("\n");\r
451 #endif\r
452 #endif\r
453         }\r
454         for(i=0;i<NN-KK+1;i++)\r
455                 b[i] = Index_of[lambda[i]];\r
456 \r
457         /*\r
458          * Begin Berlekamp-Massey algorithm to determine error+erasure\r
459          * locator polynomial\r
460          */\r
461         r = no_eras;\r
462         el = no_eras;\r
463         while (++r <= NN-KK) {  /* r is the step number */\r
464                 /* Compute discrepancy at the r-th step in poly-form */\r
465                 discr_r = 0;\r
466                 for (i = 0; i < r; i++){\r
467                         if ((lambda[i] != 0) && (s[r - i] != A0)) {\r
468                                 discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];\r
469                         }\r
470                 }\r
471                 discr_r = Index_of[discr_r];    /* Index form */\r
472                 if (discr_r == A0) {\r
473                         /* 2 lines below: B(x) <-- x*B(x) */\r
474                         COPYDOWN(&b[1],b,NN-KK);\r
475                         b[0] = A0;\r
476                 } else {\r
477                         /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */\r
478                         t[0] = lambda[0];\r
479                         for (i = 0 ; i < NN-KK; i++) {\r
480                                 if(b[i] != A0)\r
481                                         t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];\r
482                                 else\r
483                                         t[i+1] = lambda[i+1];\r
484                         }\r
485                         if (2 * el <= r + no_eras - 1) {\r
486                                 el = r + no_eras - el;\r
487                                 /*\r
488                                  * 2 lines below: B(x) <-- inv(discr_r) *\r
489                                  * lambda(x)\r
490                                  */\r
491                                 for (i = 0; i <= NN-KK; i++)\r
492                                         b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);\r
493                         } else {\r
494                                 /* 2 lines below: B(x) <-- x*B(x) */\r
495                                 COPYDOWN(&b[1],b,NN-KK);\r
496                                 b[0] = A0;\r
497                         }\r
498                         COPY(lambda,t,NN-KK+1);\r
499                 }\r
500         }\r
501 \r
502         /* Convert lambda to index form and compute deg(lambda(x)) */\r
503         deg_lambda = 0;\r
504         for(i=0;i<NN-KK+1;i++){\r
505                 lambda[i] = Index_of[lambda[i]];\r
506                 if(lambda[i] != A0)\r
507                         deg_lambda = i;\r
508         }\r
509         /*\r
510          * Find roots of the error+erasure locator polynomial. By Chien\r
511          * Search\r
512          */\r
513         COPY(&reg[1],&lambda[1],NN-KK);\r
514         count = 0;              /* Number of roots of lambda(x) */\r
515         for (i = 1; i <= NN; i++) {\r
516                 q = 1;\r
517                 for (j = deg_lambda; j > 0; j--)\r
518                         if (reg[j] != A0) {\r
519                                 reg[j] = modnn(reg[j] + j);\r
520                                 q ^= Alpha_to[reg[j]];\r
521                         }\r
522                 if (!q) {\r
523                         /* store root (index-form) and error location number */\r
524                         root[count] = i;\r
525                         loc[count] = NN - i;\r
526                         count++;\r
527                 }\r
528         }\r
529 \r
530 #ifdef DEBUG\r
531         printf("\n Final error positions:\t");\r
532         for (i = 0; i < count; i++)\r
533                 printf("%d ", loc[i]);\r
534         printf("\n");\r
535 #endif\r
536         if (deg_lambda != count) {\r
537                 /*\r
538                  * deg(lambda) unequal to number of roots => uncorrectable\r
539                  * error detected\r
540                  */\r
541                 return -1;\r
542         }\r
543         /*\r
544          * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo\r
545          * x**(NN-KK)). in index form. Also find deg(omega).\r
546          */\r
547         deg_omega = 0;\r
548         for (i = 0; i < NN-KK;i++){\r
549                 tmp = 0;\r
550                 j = (deg_lambda < i) ? deg_lambda : i;\r
551                 for(;j >= 0; j--){\r
552                         if ((s[i + 1 - j] != A0) && (lambda[j] != A0))\r
553                                 tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];\r
554                 }\r
555                 if(tmp != 0)\r
556                         deg_omega = i;\r
557                 omega[i] = Index_of[tmp];\r
558         }\r
559         omega[NN-KK] = A0;\r
560 \r
561         /*\r
562          * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =\r
563          * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form\r
564          */\r
565         for (j = count-1; j >=0; j--) {\r
566                 num1 = 0;\r
567                 for (i = deg_omega; i >= 0; i--) {\r
568                         if (omega[i] != A0)\r
569                                 num1  ^= Alpha_to[modnn(omega[i] + i * root[j])];\r
570                 }\r
571                 num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];\r
572                 den = 0;\r
573 \r
574                 /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */\r
575                 for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {\r
576                         if(lambda[i+1] != A0)\r
577                                 den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];\r
578                 }\r
579                 if (den == 0) {\r
580 #ifdef DEBUG\r
581                         printf("\n ERROR: denominator = 0\n");\r
582 #endif\r
583                         return -1;\r
584                 }\r
585                 /* Apply error to data */\r
586                 if (num1 != 0) {\r
587                         data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];\r
588                 }\r
589         }\r
590         return count;\r
591 }\r
592 \r
593 \r
594 #endif /* USE_JPWL */