STEP06 ? add dissect_kerberos_AD_AP_OPTIONS
[metze/wireshark/wip.git] / epan / reedsolomon.c
1 /* reedsolomon.c
2  *
3  * Reed-Solomon encoding and decoding,
4  * by Phil Karn (karn@ka9q.ampr.org) September 1996
5  * Copyright 1999 Phil Karn, KA9Q
6  * Separate CCSDS version create Dec 1998, merged into this version May 1999
7  *
8  * This file is derived from my generic RS encoder/decoder, which is
9  * in turn based on the program "new_rs_erasures.c" by Robert
10  * Morelos-Zaragoza (robert@spectra.eng.hawaii.edu) and Hari Thirumoorthy
11  * (harit@spectra.eng.hawaii.edu), Aug 1995
12  *
13  * Wireshark - Network traffic analyzer
14  * By Gerald Combs <gerald@wireshark.org>
15  * Copyright 1998 Gerald Combs
16  *
17  * SPDX-License-Identifier: GPL-2.0-or-later
18  */
19 #include <stdio.h>
20 #include "reedsolomon.h"
21 #include <wsutil/ws_printf.h> /* ws_debug_printf */
22
23 #ifdef CCSDS
24 /* CCSDS field generator polynomial: 1+x+x^2+x^7+x^8 */
25 int Pp[MM+1] = { 1, 1, 1, 0, 0, 0, 0, 1, 1 };
26
27 #else /* not CCSDS */
28 /* MM, KK, B0, PRIM are user-defined in rs.h */
29
30 /* Primitive polynomials - see Lin & Costello, Appendix A,
31  * and  Lee & Messerschmitt, p. 453.
32  */
33 #if(MM == 2)/* Admittedly silly */
34 int Pp[MM+1] = { 1, 1, 1 };
35
36 #elif(MM == 3)
37 /* 1 + x + x^3 */
38 int Pp[MM+1] = { 1, 1, 0, 1 };
39
40 #elif(MM == 4)
41 /* 1 + x + x^4 */
42 int Pp[MM+1] = { 1, 1, 0, 0, 1 };
43
44 #elif(MM == 5)
45 /* 1 + x^2 + x^5 */
46 int Pp[MM+1] = { 1, 0, 1, 0, 0, 1 };
47
48 #elif(MM == 6)
49 /* 1 + x + x^6 */
50 int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1 };
51
52 #elif(MM == 7)
53 /* 1 + x^3 + x^7 */
54 int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 1 };
55
56 #elif(MM == 8)
57 /* 1+x^2+x^3+x^4+x^8 */
58 int Pp[MM+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };
59
60 #elif(MM == 9)
61 /* 1+x^4+x^9 */
62 int Pp[MM+1] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
63
64 #elif(MM == 10)
65 /* 1+x^3+x^10 */
66 int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
67
68 #elif(MM == 11)
69 /* 1+x^2+x^11 */
70 int Pp[MM+1] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
71
72 #elif(MM == 12)
73 /* 1+x+x^4+x^6+x^12 */
74 int Pp[MM+1] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };
75
76 #elif(MM == 13)
77 /* 1+x+x^3+x^4+x^13 */
78 int Pp[MM+1] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
79
80 #elif(MM == 14)
81 /* 1+x+x^6+x^10+x^14 */
82 int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };
83
84 #elif(MM == 15)
85 /* 1+x+x^15 */
86 int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
87
88 #elif(MM == 16)
89 /* 1+x+x^3+x^12+x^16 */
90 int Pp[MM+1] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };
91
92 #else
93 #error "Either CCSDS must be defined, or MM must be set in range 2-16"
94 #endif
95
96 #endif
97
98 #ifdef STANDARD_ORDER /* first byte transmitted is index of x**(KK-1) in message poly*/
99         /* definitions used in the encode routine*/
100         #define MESSAGE(i) data[KK-(i)-1]
101         #define REMAINDER(i) bb[NN-KK-(i)-1]
102         /* definitions used in the decode routine*/
103         #define RECEIVED(i) data[NN-1-(i)]
104         #define ERAS_INDEX(i) (NN-1-eras_pos[i])
105         #define INDEX_TO_POS(i) (NN-1-(i))
106 #else /* first byte transmitted is index of x**0 in message polynomial*/
107         /* definitions used in the encode routine*/
108         #define MESSAGE(i) data[i]
109         #define REMAINDER(i) bb[i]
110         /* definitions used in the decode routine*/
111         #define RECEIVED(i) data[i]
112         #define ERAS_INDEX(i) eras_pos[i]
113         #define INDEX_TO_POS(i) i
114 #endif
115
116
117 /* This defines the type used to store an element of the Galois Field
118  * used by the code. Make sure this is something larger than a char if
119  * if anything larger than GF(256) is used.
120  *
121  * Note: unsigned char will work up to GF(256) but int seems to run
122  * faster on the Pentium.
123  */
124 typedef int gf;
125
126 /* index->polynomial form conversion table */
127 static gf Alpha_to[NN + 1];
128
129 /* Polynomial->index form conversion table */
130 static gf Index_of[NN + 1];
131
132 /* No legal value in index form represents zero, so
133  * we need a special value for this purpose
134  */
135 #define A0      (NN)
136
137 /* Generator polynomial g(x) in index form */
138 static gf Gg[NN - KK + 1];
139
140 static int RS_init; /* Initialization flag */
141
142 /* Compute x % NN, where NN is 2**MM - 1,
143  * without a slow divide
144  */
145 /* static inline gf*/
146 static gf
147 modnn(int x)
148 {
149   while (x >= NN) {
150     x -= NN;
151     x = (x >> MM) + (x & NN);
152   }
153   return x;
154 }
155
156 #define min_(a,b)       ((a) < (b) ? (a) : (b))
157
158 #define CLEAR(a,n) {\
159 int ci;\
160 for(ci=(n)-1;ci >=0;ci--)\
161 (a)[ci] = 0;\
162 }
163
164 #define COPY(a,b,n) {\
165 int ci;\
166 for(ci=(n)-1;ci >=0;ci--)\
167 (a)[ci] = (b)[ci];\
168 }
169
170 #define COPYDOWN(a,b,n) {\
171 int ci;\
172 for(ci=(n)-1;ci >=0;ci--)\
173 (a)[ci] = (b)[ci];\
174 }
175
176 static void init_rs(void);
177
178 #ifdef CCSDS
179 /* Conversion lookup tables from conventional alpha to Berlekamp's
180  * dual-basis representation. Used in the CCSDS version only.
181  * taltab[] -- convert conventional to dual basis
182  * tal1tab[] -- convert dual basis to conventional
183
184  * Note: the actual RS encoder/decoder works with the conventional basis.
185  * So data is converted from dual to conventional basis before either
186  * encoding or decoding and then converted back.
187  */
188 static unsigned char taltab[NN+1],tal1tab[NN+1];
189
190 static unsigned char tal[] = { 0x8d, 0xef, 0xec, 0x86, 0xfa, 0x99, 0xaf, 0x7b };
191
192 /* Generate conversion lookup tables between conventional alpha representation
193  * (@**7, @**6, ...@**0)
194  *  and Berlekamp's dual basis representation
195  * (l0, l1, ...l7)
196  */
197 static void
198 gen_ltab(void)
199 {
200   int i,j,k;
201
202   for(i=0;i<256;i++){/* For each value of input */
203     taltab[i] = 0;
204     for(j=0;j<8;j++) /* for each column of matrix */
205       for(k=0;k<8;k++){ /* for each row of matrix */
206         if(i & (1<<k))
207           taltab[i] ^= tal[7-k] & (1<<j);
208       }
209     tal1tab[taltab[i]] = i;
210   }
211 }
212 #endif /* CCSDS */
213
214 #if PRIM != 1
215 static int Ldec;/* Decrement for aux location variable in Chien search */
216
217 static void
218 gen_ldec(void)
219 {
220   for(Ldec=1;(Ldec % PRIM) != 0;Ldec+= NN)
221     ;
222   Ldec /= PRIM;
223 }
224 #else
225 #define Ldec 1
226 #endif
227
228 /* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m]
229    lookup tables:  index->polynomial form   alpha_to[] contains j=alpha**i;
230                    polynomial form -> index form  index_of[j=alpha**i] = i
231    alpha=2 is the primitive element of GF(2**m)
232    HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
233         Let @ represent the primitive element commonly called "alpha" that
234    is the root of the primitive polynomial p(x). Then in GF(2^m), for any
235    0 <= i <= 2^m-2,
236         @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
237    where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
238    of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
239    example the polynomial representation of @^5 would be given by the binary
240    representation of the integer "alpha_to[5]".
241                    Similarily, index_of[] can be used as follows:
242         As above, let @ represent the primitive element of GF(2^m) that is
243    the root of the primitive polynomial p(x). In order to find the power
244    of @ (alpha) that has the polynomial representation
245         a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
246    we consider the integer "i" whose binary representation with a(0) being LSB
247    and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
248    "index_of[i]". Now, @^index_of[i] is that element whose polynomial
249     representation is (a(0),a(1),a(2),...,a(m-1)).
250    NOTE:
251         The element alpha_to[2^m-1] = 0 always signifying that the
252    representation of "@^infinity" = 0 is (0,0,0,...,0).
253         Similarily, the element index_of[0] = A0 always signifying
254    that the power of alpha which has the polynomial representation
255    (0,0,...,0) is "infinity".
256
257 */
258
259 static void
260 generate_gf(void)
261 {
262   register int i, mask;
263
264   mask = 1;
265   Alpha_to[MM] = 0;
266   for (i = 0; i < MM; i++) {
267     Alpha_to[i] = mask;
268     Index_of[Alpha_to[i]] = i;
269     /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
270     if (Pp[i] != 0)
271       Alpha_to[MM] ^= mask;     /* Bit-wise EXOR operation */
272     mask <<= 1; /* single left-shift */
273   }
274   Index_of[Alpha_to[MM]] = MM;
275   /*
276    * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
277    * poly-repr of @^i shifted left one-bit and accounting for any @^MM
278    * term that may occur when poly-repr of @^i is shifted.
279    */
280   mask >>= 1;
281   for (i = MM + 1; i < NN; i++) {
282     if (Alpha_to[i - 1] >= mask)
283       Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
284     else
285       Alpha_to[i] = Alpha_to[i - 1] << 1;
286     Index_of[Alpha_to[i]] = i;
287   }
288   Index_of[0] = A0;
289   Alpha_to[NN] = 0;
290 }
291
292 /*
293  * Obtain the generator polynomial of the TT-error correcting, length
294  * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0,
295  * ... ,(2*TT-1)
296  *
297  * Examples:
298  *
299  * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2.
300  * g(x) = (x+@) (x+@**2)
301  *
302  * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4.
303  * g(x) = (x+1) (x+@) (x+@**2) (x+@**3)
304  */
305 static void
306 gen_poly(void)
307 {
308   register int i, j;
309
310   Gg[0] = 1;
311   for (i = 0; i < NN - KK; i++) {
312     Gg[i+1] = 1;
313     /*
314      * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by
315      * (@**(B0+i)*PRIM + x)
316      */
317     for (j = i; j > 0; j--)
318       if (Gg[j] != 0)
319         Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + (B0 + i) *PRIM)];
320       else
321         Gg[j] = Gg[j - 1];
322     /* Gg[0] can never be zero */
323     Gg[0] = Alpha_to[modnn(Index_of[Gg[0]] + (B0 + i) * PRIM)];
324   }
325   /* convert Gg[] to index form for quicker encoding */
326   for (i = 0; i <= NN - KK; i++)
327     Gg[i] = Index_of[Gg[i]];
328 }
329
330
331 /*
332  * take the string of symbols in data[i], i=0..(k-1) and encode
333  * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[]
334  * is input and bb[] is output in polynomial form. Encoding is done by using
335  * a feedback shift register with appropriate connections specified by the
336  * elements of Gg[], which was generated above. Codeword is   c(X) =
337  * data(X)*X**(NN-KK)+ b(X)
338  */
339
340 int
341 encode_rs(dtype data[KK], dtype bb[NN-KK])
342 {
343   register int i, j;
344   gf feedback;
345
346 #if DEBUG >= 1 && MM != 8
347   /* Check for illegal input values */
348   for(i=0;i<KK;i++)
349     if(MESSAGE(i) > NN)
350       return -1;
351 #endif
352
353   if(!RS_init)
354     init_rs();
355
356   CLEAR(bb,NN-KK);
357
358 #ifdef CCSDS
359   /* Convert to conventional basis */
360   for(i=0;i<KK;i++)
361     MESSAGE(i) = tal1tab[MESSAGE(i)];
362 #endif
363
364   for(i = KK - 1; i >= 0; i--) {
365     feedback = Index_of[MESSAGE(i) ^ REMAINDER(NN - KK - 1)];
366     if (feedback != A0) {       /* feedback term is non-zero */
367       for (j = NN - KK - 1; j > 0; j--)
368         if (Gg[j] != A0)
369           REMAINDER(j) = REMAINDER(j - 1) ^ Alpha_to[modnn(Gg[j] + feedback)];
370         else
371           REMAINDER(j) = REMAINDER(j - 1);
372       REMAINDER(0) = Alpha_to[modnn(Gg[0] + feedback)];
373     } else {    /* feedback term is zero. encoder becomes a
374                  * single-byte shifter */
375       for (j = NN - KK - 1; j > 0; j--)
376         REMAINDER(j) = REMAINDER(j - 1);
377       REMAINDER(0) = 0;
378     }
379   }
380 #ifdef CCSDS
381   /* Convert to l-basis */
382   for(i=0;i<NN;i++)
383     MESSAGE(i) = taltab[MESSAGE(i)];
384 #endif
385
386   return 0;
387 }
388
389 /*
390  * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful,
391  * writes the codeword into data[] itself. Otherwise data[] is unaltered.
392  *
393  * Return number of symbols corrected, or -1 if codeword is illegal
394  * or uncorrectable. If eras_pos is non-null, the detected error locations
395  * are written back. NOTE! This array must be at least NN-KK elements long.
396  *
397  * First "no_eras" erasures are declared by the calling program. Then, the
398  * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
399  * If the number of channel errors is not greater than "t_after_eras" the
400  * transmitted codeword will be recovered. Details of algorithm can be found
401  * in R. Blahut's "Theory ... of Error-Correcting Codes".
402
403  * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure
404  * will result. The decoder *could* check for this condition, but it would involve
405  * extra time on every decoding operation.
406  */
407
408 int
409 eras_dec_rs(dtype data[NN], int eras_pos[NN-KK], int no_eras)
410 {
411   int deg_lambda, el, deg_omega;
412   int i, j, r,k;
413   gf u,q,tmp,num1,num2,den,discr_r;
414   gf lambda[NN-KK + 1], s[NN-KK + 1];   /* Err+Eras Locator poly
415                                          * and syndrome poly */
416   gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
417   gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];
418   int syn_error, count;
419
420   if(!RS_init)
421     init_rs();
422
423 #ifdef CCSDS
424   /* Convert to conventional basis */
425   for(i=0;i<NN;i++)
426     RECEIVED(i) = tal1tab[RECEIVED(i)];
427 #endif
428
429 #if DEBUG >= 1 && MM != 8
430   /* Check for illegal input values */
431   for(i=0;i<NN;i++)
432     if(RECEIVED(i) > NN)
433       return -1;
434 #endif
435   /* form the syndromes; i.e., evaluate data(x) at roots of g(x)
436    * namely @**(B0+i)*PRIM, i = 0, ... ,(NN-KK-1)
437    */
438   for(i=1;i<=NN-KK;i++){
439     s[i] = RECEIVED(0);
440   }
441   for(j=1;j<NN;j++){
442     if(RECEIVED(j) == 0)
443       continue;
444     tmp = Index_of[RECEIVED(j)];
445
446     /*  s[i] ^= Alpha_to[modnn(tmp + (B0+i-1)*j)]; */
447     for(i=1;i<=NN-KK;i++)
448       s[i] ^= Alpha_to[modnn(tmp + (B0+i-1)*PRIM*j)];
449   }
450   /* Convert syndromes to index form, checking for nonzero condition */
451   syn_error = 0;
452   for(i=1;i<=NN-KK;i++){
453     syn_error |= s[i];
454         /*ws_debug_printf("syndrome %d = %x\n",i,s[i]);*/
455     s[i] = Index_of[s[i]];
456   }
457
458   if (!syn_error) {
459     /* if syndrome is zero, data[] is a codeword and there are no
460      * errors to correct. So return data[] unmodified
461      */
462     count = 0;
463     goto finish;
464   }
465   CLEAR(&lambda[1],NN-KK);
466   lambda[0] = 1;
467
468   if (no_eras > 0) {
469     /* Init lambda to be the erasure locator polynomial */
470     lambda[1] = Alpha_to[modnn(PRIM * ERAS_INDEX(0))];
471     for (i = 1; i < no_eras; i++) {
472       u = modnn(PRIM*ERAS_INDEX(i));
473       for (j = i+1; j > 0; j--) {
474         tmp = Index_of[lambda[j - 1]];
475         if(tmp != A0)
476           lambda[j] ^= Alpha_to[modnn(u + tmp)];
477       }
478     }
479 #if DEBUG >= 1
480     /* Test code that verifies the erasure locator polynomial just constructed
481        Needed only for decoder debugging. */
482
483     /* find roots of the erasure location polynomial */
484     for(i=1;i<=no_eras;i++)
485       reg[i] = Index_of[lambda[i]];
486     count = 0;
487     for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
488       q = 1;
489       for (j = 1; j <= no_eras; j++)
490         if (reg[j] != A0) {
491           reg[j] = modnn(reg[j] + j);
492           q ^= Alpha_to[reg[j]];
493         }
494       if (q != 0)
495         continue;
496       /* store root and error location number indices */
497       root[count] = i;
498       loc[count] = k;
499       count++;
500     }
501     if (count != no_eras) {
502       ws_debug_printf("\n lambda(x) is WRONG\n");
503       count = -1;
504       goto finish;
505     }
506 #if DEBUG >= 2
507     ws_debug_printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
508     for (i = 0; i < count; i++)
509       ws_debug_printf("%d ", loc[i]);
510     ws_debug_printf("\n");
511 #endif
512 #endif
513   }
514   for(i=0;i<NN-KK+1;i++)
515     b[i] = Index_of[lambda[i]];
516
517   /*
518    * Begin Berlekamp-Massey algorithm to determine error+erasure
519    * locator polynomial
520    */
521   r = no_eras;
522   el = no_eras;
523   while (++r <= NN-KK) {        /* r is the step number */
524     /* Compute discrepancy at the r-th step in poly-form */
525     discr_r = 0;
526     for (i = 0; i < r; i++){
527       if ((lambda[i] != 0) && (s[r - i] != A0)) {
528         discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
529       }
530     }
531     discr_r = Index_of[discr_r];        /* Index form */
532     if (discr_r == A0) {
533       /* 2 lines below: B(x) <-- x*B(x) */
534       COPYDOWN(&b[1],b,NN-KK);
535       b[0] = A0;
536     } else {
537       /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
538       t[0] = lambda[0];
539       for (i = 0 ; i < NN-KK; i++) {
540         if(b[i] != A0)
541           t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
542         else
543           t[i+1] = lambda[i+1];
544       }
545       if (2 * el <= r + no_eras - 1) {
546         el = r + no_eras - el;
547         /*
548          * 2 lines below: B(x) <-- inv(discr_r) *
549          * lambda(x)
550          */
551         for (i = 0; i <= NN-KK; i++)
552           b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
553       } else {
554         /* 2 lines below: B(x) <-- x*B(x) */
555         COPYDOWN(&b[1],b,NN-KK);
556         b[0] = A0;
557       }
558       COPY(lambda,t,NN-KK+1);
559     }
560   }
561
562   /* Convert lambda to index form and compute deg(lambda(x)) */
563   deg_lambda = 0;
564   for(i=0;i<NN-KK+1;i++){
565     lambda[i] = Index_of[lambda[i]];
566     if(lambda[i] != A0)
567       deg_lambda = i;
568   }
569   /*
570    * Find roots of the error+erasure locator polynomial by Chien
571    * Search
572    */
573   COPY(&reg[1],&lambda[1],NN-KK);
574   count = 0;            /* Number of roots of lambda(x) */
575   for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) {
576     q = 1;
577     for (j = deg_lambda; j > 0; j--){
578       if (reg[j] != A0) {
579         reg[j] = modnn(reg[j] + j);
580         q ^= Alpha_to[reg[j]];
581       }
582     }
583     if (q != 0)
584       continue;
585     /* store root (index-form) and error location number */
586     root[count] = i;
587     loc[count] = k;
588     /* If we've already found max possible roots,
589      * abort the search to save time
590      */
591     if(++count == deg_lambda)
592       break;
593   }
594   if (deg_lambda != count) {
595     /*
596      * deg(lambda) unequal to number of roots => uncorrectable
597      * error detected
598      */
599     count = -1;
600     goto finish;
601   }
602   /*
603    * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
604    * x**(NN-KK)). in index form. Also find deg(omega).
605    */
606   deg_omega = 0;
607   for (i = 0; i < NN-KK;i++){
608     tmp = 0;
609     j = (deg_lambda < i) ? deg_lambda : i;
610     for(;j >= 0; j--){
611       if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
612         tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
613     }
614     if(tmp != 0)
615       deg_omega = i;
616     omega[i] = Index_of[tmp];
617   }
618   omega[NN-KK] = A0;
619
620   /*
621    * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
622    * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
623    */
624   for (j = count-1; j >=0; j--) {
625     num1 = 0;
626     for (i = deg_omega; i >= 0; i--) {
627       if (omega[i] != A0)
628         num1  ^= Alpha_to[modnn(omega[i] + i * root[j])];
629     }
630     num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
631     den = 0;
632
633     /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
634     for (i = min_(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
635       if(lambda[i+1] != A0)
636         den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
637     }
638     if (den == 0) {
639 #if DEBUG >= 1
640       ws_debug_printf("\n ERROR: denominator = 0\n");
641 #endif
642       /* Convert to dual- basis */
643       count = -1;
644       goto finish;
645     }
646     /* Apply error to data */
647     if (num1 != 0) {
648       RECEIVED(loc[j]) ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
649     }
650   }
651  finish:
652 #ifdef CCSDS
653   /* Convert to dual- basis */
654   for(i=0;i<NN;i++)
655     RECEIVED(i) = taltab[RECEIVED(i)];
656 #endif
657   if(eras_pos != NULL){
658     for(i=0;i<count;i++){
659       if(eras_pos!= NULL)
660         eras_pos[i] = INDEX_TO_POS(loc[i]);
661     }
662   }
663   return count;
664 }
665 /* Encoder/decoder initialization - call this first! */
666 static void
667 init_rs(void)
668 {
669   generate_gf();
670   gen_poly();
671 #ifdef CCSDS
672   gen_ltab();
673 #endif
674 #if PRIM != 1
675   gen_ldec();
676 #endif
677   RS_init = 1;
678 }
679
680 /*
681  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
682  *
683  * Local Variables:
684  * c-basic-offset: 2
685  * tab-width: 8
686  * indent-tabs-mode: nil
687  * End:
688  *
689  * ex: set shiftwidth=2 tabstop=8 expandtab:
690  * :indentSize=2:tabSize=8:noTabs=true:
691  */