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