Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  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, HervĂ© 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. /* Primitive polynomials - see Lin & Costello, Appendix A,
  77.  * and  Lee & Messerschmitt, p. 453.
  78.  */
  79. #if(MM == 2)/* Admittedly silly */
  80. int Pp[MM+1] = { 1, 1, 1 };
  81.  
  82. #elif(MM == 3)
  83. /* 1 + x + x^3 */
  84. int Pp[MM+1] = { 1, 1, 0, 1 };
  85.  
  86. #elif(MM == 4)
  87. /* 1 + x + x^4 */
  88. int Pp[MM+1] = { 1, 1, 0, 0, 1 };
  89.  
  90. #elif(MM == 5)
  91. /* 1 + x^2 + x^5 */
  92. int Pp[MM+1] = { 1, 0, 1, 0, 0, 1 };
  93.  
  94. #elif(MM == 6)
  95. /* 1 + x + x^6 */
  96. int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1 };
  97.  
  98. #elif(MM == 7)
  99. /* 1 + x^3 + x^7 */
  100. int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 1 };
  101.  
  102. #elif(MM == 8)
  103. /* 1+x^2+x^3+x^4+x^8 */
  104. int Pp[MM+1] = { 1, 0, 1, 1, 1, 0, 0, 0, 1 };
  105.  
  106. #elif(MM == 9)
  107. /* 1+x^4+x^9 */
  108. int Pp[MM+1] = { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
  109.  
  110. #elif(MM == 10)
  111. /* 1+x^3+x^10 */
  112. int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 };
  113.  
  114. #elif(MM == 11)
  115. /* 1+x^2+x^11 */
  116. int Pp[MM+1] = { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
  117.  
  118. #elif(MM == 12)
  119. /* 1+x+x^4+x^6+x^12 */
  120. int Pp[MM+1] = { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1 };
  121.  
  122. #elif(MM == 13)
  123. /* 1+x+x^3+x^4+x^13 */
  124. int Pp[MM+1] = { 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
  125.  
  126. #elif(MM == 14)
  127. /* 1+x+x^6+x^10+x^14 */
  128. int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1 };
  129.  
  130. #elif(MM == 15)
  131. /* 1+x+x^15 */
  132. int Pp[MM+1] = { 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
  133.  
  134. #elif(MM == 16)
  135. /* 1+x+x^3+x^12+x^16 */
  136. int Pp[MM+1] = { 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1 };
  137.  
  138. #else
  139. #error "MM must be in range 2-16"
  140. #endif
  141.  
  142. /* Alpha exponent for the first root of the generator polynomial */
  143. #define B0      0  /* Different from the default 1 */
  144.  
  145. /* index->polynomial form conversion table */
  146. gf Alpha_to[NN + 1];
  147.  
  148. /* Polynomial->index form conversion table */
  149. gf Index_of[NN + 1];
  150.  
  151. /* No legal value in index form represents zero, so
  152.  * we need a special value for this purpose
  153.  */
  154. #define A0      (NN)
  155.  
  156. /* Generator polynomial g(x)
  157.  * Degree of g(x) = 2*TT
  158.  * has roots @**B0, @**(B0+1), ... ,@^(B0+2*TT-1)
  159.  */
  160. /*gf Gg[NN - KK + 1];*/
  161. gf              Gg[NN - 1];
  162.  
  163. /* Compute x % NN, where NN is 2**MM - 1,
  164.  * without a slow divide
  165.  */
  166. static /*inline*/ gf
  167. modnn(int x)
  168. {
  169.         while (x >= NN) {
  170.                 x -= NN;
  171.                 x = (x >> MM) + (x & NN);
  172.         }
  173.         return x;
  174. }
  175.  
  176. /*#define       min(a,b)        ((a) < (b) ? (a) : (b))*/
  177.  
  178. #define CLEAR(a,n) {\
  179.         int ci;\
  180.         for(ci=(n)-1;ci >=0;ci--)\
  181.                 (a)[ci] = 0;\
  182.         }
  183.  
  184. #define COPY(a,b,n) {\
  185.         int ci;\
  186.         for(ci=(n)-1;ci >=0;ci--)\
  187.                 (a)[ci] = (b)[ci];\
  188.         }
  189. #define COPYDOWN(a,b,n) {\
  190.         int ci;\
  191.         for(ci=(n)-1;ci >=0;ci--)\
  192.                 (a)[ci] = (b)[ci];\
  193.         }
  194.  
  195. void init_rs(int k)
  196. {
  197.         KK = k;
  198.         if (KK >= NN) {
  199.                 printf("KK must be less than 2**MM - 1\n");
  200.                 exit(1);
  201.         }
  202.        
  203.         generate_gf();
  204.         gen_poly();
  205. }
  206.  
  207. /* generate GF(2**m) from the irreducible polynomial p(X) in p[0]..p[m]
  208.    lookup tables:  index->polynomial form   alpha_to[] contains j=alpha**i;
  209.                    polynomial form -> index form  index_of[j=alpha**i] = i
  210.    alpha=2 is the primitive element of GF(2**m)
  211.    HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows:
  212.         Let @ represent the primitive element commonly called "alpha" that
  213.    is the root of the primitive polynomial p(x). Then in GF(2^m), for any
  214.    0 <= i <= 2^m-2,
  215.         @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
  216.    where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation
  217.    of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
  218.    example the polynomial representation of @^5 would be given by the binary
  219.    representation of the integer "alpha_to[5]".
  220.                    Similarily, index_of[] can be used as follows:
  221.         As above, let @ represent the primitive element of GF(2^m) that is
  222.    the root of the primitive polynomial p(x). In order to find the power
  223.    of @ (alpha) that has the polynomial representation
  224.         a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1)
  225.    we consider the integer "i" whose binary representation with a(0) being LSB
  226.    and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry
  227.    "index_of[i]". Now, @^index_of[i] is that element whose polynomial
  228.     representation is (a(0),a(1),a(2),...,a(m-1)).
  229.    NOTE:
  230.         The element alpha_to[2^m-1] = 0 always signifying that the
  231.    representation of "@^infinity" = 0 is (0,0,0,...,0).
  232.         Similarily, the element index_of[0] = A0 always signifying
  233.    that the power of alpha which has the polynomial representation
  234.    (0,0,...,0) is "infinity".
  235.  
  236. */
  237.  
  238. void
  239. generate_gf(void)
  240. {
  241.         register int i, mask;
  242.  
  243.         mask = 1;
  244.         Alpha_to[MM] = 0;
  245.         for (i = 0; i < MM; i++) {
  246.                 Alpha_to[i] = mask;
  247.                 Index_of[Alpha_to[i]] = i;
  248.                 /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */
  249.                 if (Pp[i] != 0)
  250.                         Alpha_to[MM] ^= mask;   /* Bit-wise EXOR operation */
  251.                 mask <<= 1;     /* single left-shift */
  252.         }
  253.         Index_of[Alpha_to[MM]] = MM;
  254.         /*
  255.          * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by
  256.          * poly-repr of @^i shifted left one-bit and accounting for any @^MM
  257.          * term that may occur when poly-repr of @^i is shifted.
  258.          */
  259.         mask >>= 1;
  260.         for (i = MM + 1; i < NN; i++) {
  261.                 if (Alpha_to[i - 1] >= mask)
  262.                         Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1);
  263.                 else
  264.                         Alpha_to[i] = Alpha_to[i - 1] << 1;
  265.                 Index_of[Alpha_to[i]] = i;
  266.         }
  267.         Index_of[0] = A0;
  268.         Alpha_to[NN] = 0;
  269. }
  270.  
  271.  
  272. /*
  273.  * Obtain the generator polynomial of the TT-error correcting, length
  274.  * NN=(2**MM -1) Reed Solomon code from the product of (X+@**(B0+i)), i = 0,
  275.  * ... ,(2*TT-1)
  276.  *
  277.  * Examples:
  278.  *
  279.  * If B0 = 1, TT = 1. deg(g(x)) = 2*TT = 2.
  280.  * g(x) = (x+@) (x+@**2)
  281.  *
  282.  * If B0 = 0, TT = 2. deg(g(x)) = 2*TT = 4.
  283.  * g(x) = (x+1) (x+@) (x+@**2) (x+@**3)
  284.  */
  285. void
  286. gen_poly(void)
  287. {
  288.         register int i, j;
  289.  
  290.         Gg[0] = Alpha_to[B0];
  291.         Gg[1] = 1;              /* g(x) = (X+@**B0) initially */
  292.         for (i = 2; i <= NN - KK; i++) {
  293.                 Gg[i] = 1;
  294.                 /*
  295.                  * Below multiply (Gg[0]+Gg[1]*x + ... +Gg[i]x^i) by
  296.                  * (@**(B0+i-1) + x)
  297.                  */
  298.                 for (j = i - 1; j > 0; j--)
  299.                         if (Gg[j] != 0)
  300.                                 Gg[j] = Gg[j - 1] ^ Alpha_to[modnn((Index_of[Gg[j]]) + B0 + i - 1)];
  301.                         else
  302.                                 Gg[j] = Gg[j - 1];
  303.                 /* Gg[0] can never be zero */
  304.                 Gg[0] = Alpha_to[modnn((Index_of[Gg[0]]) + B0 + i - 1)];
  305.         }
  306.         /* convert Gg[] to index form for quicker encoding */
  307.         for (i = 0; i <= NN - KK; i++)
  308.                 Gg[i] = Index_of[Gg[i]];
  309. }
  310.  
  311.  
  312. /*
  313.  * take the string of symbols in data[i], i=0..(k-1) and encode
  314.  * systematically to produce NN-KK parity symbols in bb[0]..bb[NN-KK-1] data[]
  315.  * is input and bb[] is output in polynomial form. Encoding is done by using
  316.  * a feedback shift register with appropriate connections specified by the
  317.  * elements of Gg[], which was generated above. Codeword is   c(X) =
  318.  * data(X)*X**(NN-KK)+ b(X)
  319.  */
  320. int
  321. encode_rs(dtype *data, dtype *bb)
  322. {
  323.         register int i, j;
  324.         gf feedback;
  325.  
  326.         CLEAR(bb,NN-KK);
  327.         for (i = KK - 1; i >= 0; i--) {
  328. #if (MM != 8)
  329.                 if(data[i] > NN)
  330.                         return -1;      /* Illegal symbol */
  331. #endif
  332.                 feedback = Index_of[data[i] ^ bb[NN - KK - 1]];
  333.                 if (feedback != A0) {   /* feedback term is non-zero */
  334.                         for (j = NN - KK - 1; j > 0; j--)
  335.                                 if (Gg[j] != A0)
  336.                                         bb[j] = bb[j - 1] ^ Alpha_to[modnn(Gg[j] + feedback)];
  337.                                 else
  338.                                         bb[j] = bb[j - 1];
  339.                         bb[0] = Alpha_to[modnn(Gg[0] + feedback)];
  340.                 } else {        /* feedback term is zero. encoder becomes a
  341.                                  * single-byte shifter */
  342.                         for (j = NN - KK - 1; j > 0; j--)
  343.                                 bb[j] = bb[j - 1];
  344.                         bb[0] = 0;
  345.                 }
  346.         }
  347.         return 0;
  348. }
  349.  
  350. /*
  351.  * Performs ERRORS+ERASURES decoding of RS codes. If decoding is successful,
  352.  * writes the codeword into data[] itself. Otherwise data[] is unaltered.
  353.  *
  354.  * Return number of symbols corrected, or -1 if codeword is illegal
  355.  * or uncorrectable.
  356.  *
  357.  * First "no_eras" erasures are declared by the calling program. Then, the
  358.  * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2).
  359.  * If the number of channel errors is not greater than "t_after_eras" the
  360.  * transmitted codeword will be recovered. Details of algorithm can be found
  361.  * in R. Blahut's "Theory ... of Error-Correcting Codes".
  362.  */
  363. int
  364. eras_dec_rs(dtype *data, int *eras_pos, int no_eras)
  365. {
  366.         int deg_lambda, el, deg_omega;
  367.         int i, j, r;
  368.         gf u,q,tmp,num1,num2,den,discr_r;
  369.         gf recd[NN];
  370.         /* Err+Eras Locator poly and syndrome poly */
  371.         /*gf lambda[NN-KK + 1], s[NN-KK + 1];  
  372.         gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1];
  373.         gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK];*/
  374.         gf lambda[NN + 1], s[NN + 1];  
  375.         gf b[NN + 1], t[NN + 1], omega[NN + 1];
  376.         gf root[NN], reg[NN + 1], loc[NN];
  377.         int syn_error, count;
  378.  
  379.         /* data[] is in polynomial form, copy and convert to index form */
  380.         for (i = NN-1; i >= 0; i--){
  381. #if (MM != 8)
  382.                 if(data[i] > NN)
  383.                         return -1;      /* Illegal symbol */
  384. #endif
  385.                 recd[i] = Index_of[data[i]];
  386.         }
  387.         /* first form the syndromes; i.e., evaluate recd(x) at roots of g(x)
  388.          * namely @**(B0+i), i = 0, ... ,(NN-KK-1)
  389.          */
  390.         syn_error = 0;
  391.         for (i = 1; i <= NN-KK; i++) {
  392.                 tmp = 0;
  393.                 for (j = 0; j < NN; j++)
  394.                         if (recd[j] != A0)      /* recd[j] in index form */
  395.                                 tmp ^= Alpha_to[modnn(recd[j] + (B0+i-1)*j)];
  396.                 syn_error |= tmp;       /* set flag if non-zero syndrome =>
  397.                                          * error */
  398.                 /* store syndrome in index form  */
  399.                 s[i] = Index_of[tmp];
  400.         }
  401.         if (!syn_error) {
  402.                 /*
  403.                  * if syndrome is zero, data[] is a codeword and there are no
  404.                  * errors to correct. So return data[] unmodified
  405.                  */
  406.                 return 0;
  407.         }
  408.         CLEAR(&lambda[1],NN-KK);
  409.         lambda[0] = 1;
  410.         if (no_eras > 0) {
  411.                 /* Init lambda to be the erasure locator polynomial */
  412.                 lambda[1] = Alpha_to[eras_pos[0]];
  413.                 for (i = 1; i < no_eras; i++) {
  414.                         u = eras_pos[i];
  415.                         for (j = i+1; j > 0; j--) {
  416.                                 tmp = Index_of[lambda[j - 1]];
  417.                                 if(tmp != A0)
  418.                                         lambda[j] ^= Alpha_to[modnn(u + tmp)];
  419.                         }
  420.                 }
  421. #ifdef ERASURE_DEBUG
  422.                 /* find roots of the erasure location polynomial */
  423.                 for(i=1;i<=no_eras;i++)
  424.                         reg[i] = Index_of[lambda[i]];
  425.                 count = 0;
  426.                 for (i = 1; i <= NN; i++) {
  427.                         q = 1;
  428.                         for (j = 1; j <= no_eras; j++)
  429.                                 if (reg[j] != A0) {
  430.                                         reg[j] = modnn(reg[j] + j);
  431.                                         q ^= Alpha_to[reg[j]];
  432.                                 }
  433.                         if (!q) {
  434.                                 /* store root and error location
  435.                                  * number indices
  436.                                  */
  437.                                 root[count] = i;
  438.                                 loc[count] = NN - i;
  439.                                 count++;
  440.                         }
  441.                 }
  442.                 if (count != no_eras) {
  443.                         printf("\n lambda(x) is WRONG\n");
  444.                         return -1;
  445.                 }
  446. #ifndef NO_PRINT
  447.                 printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n");
  448.                 for (i = 0; i < count; i++)
  449.                         printf("%d ", loc[i]);
  450.                 printf("\n");
  451. #endif
  452. #endif
  453.         }
  454.         for(i=0;i<NN-KK+1;i++)
  455.                 b[i] = Index_of[lambda[i]];
  456.  
  457.         /*
  458.          * Begin Berlekamp-Massey algorithm to determine error+erasure
  459.          * locator polynomial
  460.          */
  461.         r = no_eras;
  462.         el = no_eras;
  463.         while (++r <= NN-KK) {  /* r is the step number */
  464.                 /* Compute discrepancy at the r-th step in poly-form */
  465.                 discr_r = 0;
  466.                 for (i = 0; i < r; i++){
  467.                         if ((lambda[i] != 0) && (s[r - i] != A0)) {
  468.                                 discr_r ^= Alpha_to[modnn(Index_of[lambda[i]] + s[r - i])];
  469.                         }
  470.                 }
  471.                 discr_r = Index_of[discr_r];    /* Index form */
  472.                 if (discr_r == A0) {
  473.                         /* 2 lines below: B(x) <-- x*B(x) */
  474.                         COPYDOWN(&b[1],b,NN-KK);
  475.                         b[0] = A0;
  476.                 } else {
  477.                         /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */
  478.                         t[0] = lambda[0];
  479.                         for (i = 0 ; i < NN-KK; i++) {
  480.                                 if(b[i] != A0)
  481.                                         t[i+1] = lambda[i+1] ^ Alpha_to[modnn(discr_r + b[i])];
  482.                                 else
  483.                                         t[i+1] = lambda[i+1];
  484.                         }
  485.                         if (2 * el <= r + no_eras - 1) {
  486.                                 el = r + no_eras - el;
  487.                                 /*
  488.                                  * 2 lines below: B(x) <-- inv(discr_r) *
  489.                                  * lambda(x)
  490.                                  */
  491.                                 for (i = 0; i <= NN-KK; i++)
  492.                                         b[i] = (lambda[i] == 0) ? A0 : modnn(Index_of[lambda[i]] - discr_r + NN);
  493.                         } else {
  494.                                 /* 2 lines below: B(x) <-- x*B(x) */
  495.                                 COPYDOWN(&b[1],b,NN-KK);
  496.                                 b[0] = A0;
  497.                         }
  498.                         COPY(lambda,t,NN-KK+1);
  499.                 }
  500.         }
  501.  
  502.         /* Convert lambda to index form and compute deg(lambda(x)) */
  503.         deg_lambda = 0;
  504.         for(i=0;i<NN-KK+1;i++){
  505.                 lambda[i] = Index_of[lambda[i]];
  506.                 if(lambda[i] != A0)
  507.                         deg_lambda = i;
  508.         }
  509.         /*
  510.          * Find roots of the error+erasure locator polynomial. By Chien
  511.          * Search
  512.          */
  513.         COPY(&reg[1],&lambda[1],NN-KK);
  514.         count = 0;              /* Number of roots of lambda(x) */
  515.         for (i = 1; i <= NN; i++) {
  516.                 q = 1;
  517.                 for (j = deg_lambda; j > 0; j--)
  518.                         if (reg[j] != A0) {
  519.                                 reg[j] = modnn(reg[j] + j);
  520.                                 q ^= Alpha_to[reg[j]];
  521.                         }
  522.                 if (!q) {
  523.                         /* store root (index-form) and error location number */
  524.                         root[count] = i;
  525.                         loc[count] = NN - i;
  526.                         count++;
  527.                 }
  528.         }
  529.  
  530. #ifdef DEBUG
  531.         printf("\n Final error positions:\t");
  532.         for (i = 0; i < count; i++)
  533.                 printf("%d ", loc[i]);
  534.         printf("\n");
  535. #endif
  536.         if (deg_lambda != count) {
  537.                 /*
  538.                  * deg(lambda) unequal to number of roots => uncorrectable
  539.                  * error detected
  540.                  */
  541.                 return -1;
  542.         }
  543.         /*
  544.          * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
  545.          * x**(NN-KK)). in index form. Also find deg(omega).
  546.          */
  547.         deg_omega = 0;
  548.         for (i = 0; i < NN-KK;i++){
  549.                 tmp = 0;
  550.                 j = (deg_lambda < i) ? deg_lambda : i;
  551.                 for(;j >= 0; j--){
  552.                         if ((s[i + 1 - j] != A0) && (lambda[j] != A0))
  553.                                 tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])];
  554.                 }
  555.                 if(tmp != 0)
  556.                         deg_omega = i;
  557.                 omega[i] = Index_of[tmp];
  558.         }
  559.         omega[NN-KK] = A0;
  560.  
  561.         /*
  562.          * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
  563.          * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form
  564.          */
  565.         for (j = count-1; j >=0; j--) {
  566.                 num1 = 0;
  567.                 for (i = deg_omega; i >= 0; i--) {
  568.                         if (omega[i] != A0)
  569.                                 num1  ^= Alpha_to[modnn(omega[i] + i * root[j])];
  570.                 }
  571.                 num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)];
  572.                 den = 0;
  573.  
  574.                 /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */
  575.                 for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) {
  576.                         if(lambda[i+1] != A0)
  577.                                 den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])];
  578.                 }
  579.                 if (den == 0) {
  580. #ifdef DEBUG
  581.                         printf("\n ERROR: denominator = 0\n");
  582. #endif
  583.                         return -1;
  584.                 }
  585.                 /* Apply error to data */
  586.                 if (num1 != 0) {
  587.                         data[loc[j]] ^= Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])];
  588.                 }
  589.         }
  590.         return count;
  591. }
  592.  
  593.  
  594. #endif /* USE_JPWL */
  595.