2 * lib/reed_solomon/decode_rs.c
5 * Generic Reed Solomon encoder / decoder library
7 * Copyright 2002, Phil Karn, KA9Q
8 * May be used under the terms of the GNU General Public License (GPL)
10 * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de)
12 * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $
16 /* Generic data width independent code which is included by the
20 int deg_lambda
, el
, deg_omega
;
23 int nroots
= rs
->nroots
;
26 int iprim
= rs
->iprim
;
27 uint16_t *alpha_to
= rs
->alpha_to
;
28 uint16_t *index_of
= rs
->index_of
;
29 uint16_t u
, q
, tmp
, num1
, num2
, den
, discr_r
, syn_error
;
30 /* Err+Eras Locator poly and syndrome poly The maximum value
31 * of nroots is 8. So the necessary stack size will be about
34 uint16_t lambda
[nroots
+ 1], syn
[nroots
];
35 uint16_t b
[nroots
+ 1], t
[nroots
+ 1], omega
[nroots
+ 1];
36 uint16_t root
[nroots
], reg
[nroots
+ 1], loc
[nroots
];
38 uint16_t msk
= (uint16_t) rs
->nn
;
40 /* Check length parameter for validity */
41 pad
= nn
- nroots
- len
;
42 if (pad
< 0 || pad
>= nn
)
45 /* Does the caller provide the syndrome ? */
49 /* form the syndromes; i.e., evaluate data(x) at roots of
51 for (i
= 0; i
< nroots
; i
++)
52 syn
[i
] = (((uint16_t) data
[0]) ^ invmsk
) & msk
;
54 for (j
= 1; j
< len
; j
++) {
55 for (i
= 0; i
< nroots
; i
++) {
57 syn
[i
] = (((uint16_t) data
[j
]) ^
60 syn
[i
] = ((((uint16_t) data
[j
]) ^
62 alpha_to
[rs_modnn(rs
, index_of
[syn
[i
]] +
68 for (j
= 0; j
< nroots
; j
++) {
69 for (i
= 0; i
< nroots
; i
++) {
71 syn
[i
] = ((uint16_t) par
[j
]) & msk
;
73 syn
[i
] = (((uint16_t) par
[j
]) & msk
) ^
74 alpha_to
[rs_modnn(rs
, index_of
[syn
[i
]] +
81 /* Convert syndromes to index form, checking for nonzero condition */
83 for (i
= 0; i
< nroots
; i
++) {
85 s
[i
] = index_of
[s
[i
]];
89 /* if syndrome is zero, data[] is a codeword and there are no
90 * errors to correct. So return data[] unmodified
97 memset(&lambda
[1], 0, nroots
* sizeof(lambda
[0]));
101 /* Init lambda to be the erasure locator polynomial */
102 lambda
[1] = alpha_to
[rs_modnn(rs
,
103 prim
* (nn
- 1 - eras_pos
[0]))];
104 for (i
= 1; i
< no_eras
; i
++) {
105 u
= rs_modnn(rs
, prim
* (nn
- 1 - eras_pos
[i
]));
106 for (j
= i
+ 1; j
> 0; j
--) {
107 tmp
= index_of
[lambda
[j
- 1]];
110 alpha_to
[rs_modnn(rs
, u
+ tmp
)];
116 for (i
= 0; i
< nroots
+ 1; i
++)
117 b
[i
] = index_of
[lambda
[i
]];
120 * Begin Berlekamp-Massey algorithm to determine error+erasure
125 while (++r
<= nroots
) { /* r is the step number */
126 /* Compute discrepancy at the r-th step in poly-form */
128 for (i
= 0; i
< r
; i
++) {
129 if ((lambda
[i
] != 0) && (s
[r
- i
- 1] != nn
)) {
131 alpha_to
[rs_modnn(rs
,
132 index_of
[lambda
[i
]] +
136 discr_r
= index_of
[discr_r
]; /* Index form */
138 /* 2 lines below: B(x) <-- x*B(x) */
139 memmove (&b
[1], b
, nroots
* sizeof (b
[0]));
142 /* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */
144 for (i
= 0; i
< nroots
; i
++) {
146 t
[i
+ 1] = lambda
[i
+ 1] ^
147 alpha_to
[rs_modnn(rs
, discr_r
+
150 t
[i
+ 1] = lambda
[i
+ 1];
152 if (2 * el
<= r
+ no_eras
- 1) {
153 el
= r
+ no_eras
- el
;
155 * 2 lines below: B(x) <-- inv(discr_r) *
158 for (i
= 0; i
<= nroots
; i
++) {
159 b
[i
] = (lambda
[i
] == 0) ? nn
:
160 rs_modnn(rs
, index_of
[lambda
[i
]]
164 /* 2 lines below: B(x) <-- x*B(x) */
165 memmove(&b
[1], b
, nroots
* sizeof(b
[0]));
168 memcpy(lambda
, t
, (nroots
+ 1) * sizeof(t
[0]));
172 /* Convert lambda to index form and compute deg(lambda(x)) */
174 for (i
= 0; i
< nroots
+ 1; i
++) {
175 lambda
[i
] = index_of
[lambda
[i
]];
179 /* Find roots of error+erasure locator polynomial by Chien search */
180 memcpy(®
[1], &lambda
[1], nroots
* sizeof(reg
[0]));
181 count
= 0; /* Number of roots of lambda(x) */
182 for (i
= 1, k
= iprim
- 1; i
<= nn
; i
++, k
= rs_modnn(rs
, k
+ iprim
)) {
183 q
= 1; /* lambda[0] is always 0 */
184 for (j
= deg_lambda
; j
> 0; j
--) {
186 reg
[j
] = rs_modnn(rs
, reg
[j
] + j
);
187 q
^= alpha_to
[reg
[j
]];
191 continue; /* Not a root */
192 /* store root (index-form) and error location number */
195 /* If we've already found max possible roots,
196 * abort the search to save time
198 if (++count
== deg_lambda
)
201 if (deg_lambda
!= count
) {
203 * deg(lambda) unequal to number of roots => uncorrectable
210 * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo
211 * x**nroots). in index form. Also find deg(omega).
213 deg_omega
= deg_lambda
- 1;
214 for (i
= 0; i
<= deg_omega
; i
++) {
216 for (j
= i
; j
>= 0; j
--) {
217 if ((s
[i
- j
] != nn
) && (lambda
[j
] != nn
))
219 alpha_to
[rs_modnn(rs
, s
[i
- j
] + lambda
[j
])];
221 omega
[i
] = index_of
[tmp
];
225 * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 =
226 * inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form
228 for (j
= count
- 1; j
>= 0; j
--) {
230 for (i
= deg_omega
; i
>= 0; i
--) {
232 num1
^= alpha_to
[rs_modnn(rs
, omega
[i
] +
235 num2
= alpha_to
[rs_modnn(rs
, root
[j
] * (fcr
- 1) + nn
)];
238 /* lambda[i+1] for i even is the formal derivative
239 * lambda_pr of lambda[i] */
240 for (i
= min(deg_lambda
, nroots
- 1) & ~1; i
>= 0; i
-= 2) {
241 if (lambda
[i
+ 1] != nn
) {
242 den
^= alpha_to
[rs_modnn(rs
, lambda
[i
+ 1] +
246 /* Apply error to data */
247 if (num1
!= 0 && loc
[j
] >= pad
) {
248 uint16_t cor
= alpha_to
[rs_modnn(rs
,index_of
[num1
] +
250 nn
- index_of
[den
])];
251 /* Store the error correction pattern, if a
252 * correction buffer is available */
256 /* If a data buffer is given and the
257 * error is inside the message,
259 if (data
&& (loc
[j
] < (nn
- nroots
)))
260 data
[loc
[j
] - pad
] ^= cor
;
266 if (eras_pos
!= NULL
) {
267 for (i
= 0; i
< count
; i
++)
268 eras_pos
[i
] = loc
[i
] - pad
;