// SPDX-License-Identifier: GPL-2.0 /* *GenericReedSolomonencoder/decoderlibrary * *Copyright2002,PhilKarn,KA9Q *MaybeusedunderthetermsoftheGNUGeneralPublicLicense(GPL) * *AdaptiontothekernelbyThomasGleixner(tglx@linutronix.de) * *Genericdatawidthindependentcodewhichisincludedbythewrappers.
*/
{ struct rs_codec *rs = rsc->codec; int deg_lambda, el, deg_omega; int i, j, r, k, pad; int nn = rs->nn; int nroots = rs->nroots; int fcr = rs->fcr; int prim = rs->prim; int iprim = rs->iprim;
uint16_t *alpha_to = rs->alpha_to;
uint16_t *index_of = rs->index_of;
uint16_t u, q, tmp, num1, num2, den, discr_r, syn_error; int count = 0; int num_corrected;
uint16_t msk = (uint16_t) rs->nn;
/* Check length parameter for validity */
pad = nn - nroots - len;
BUG_ON(pad < 0 || pad >= nn - nroots);
/* Does the caller provide the syndrome ? */ if (s != NULL) { for (i = 0; i < nroots; i++) { /* The syndrome is in index form, *sonnrepresentszero
*/ if (s[i] != nn) goto decode;
}
/* syndrome is zero, no errors to correct */ return0;
}
/* form the syndromes; i.e., evaluate data(x) at roots of
* g(x) */ for (i = 0; i < nroots; i++)
syn[i] = (((uint16_t) data[0]) ^ invmsk) & msk;
for (j = 0; j < nroots; j++) { for (i = 0; i < nroots; i++) { if (syn[i] == 0) {
syn[i] = ((uint16_t) par[j]) & msk;
} else {
syn[i] = (((uint16_t) par[j]) & msk) ^
alpha_to[rs_modnn(rs, index_of[syn[i]] +
(fcr+i)*prim)];
}
}
}
s = syn;
/* Convert syndromes to index form, checking for nonzero condition */
syn_error = 0; for (i = 0; i < nroots; i++) {
syn_error |= s[i];
s[i] = index_of[s[i]];
}
if (!syn_error) { /* if syndrome is zero, data[] is a codeword and there are no *errorstocorrect.Soreturndata[]unmodified
*/ return0;
}
if (no_eras > 0) { /* Init lambda to be the erasure locator polynomial */
lambda[1] = alpha_to[rs_modnn(rs,
prim * (nn - 1 - (eras_pos[0] + pad)))]; for (i = 1; i < no_eras; i++) {
u = rs_modnn(rs, prim * (nn - 1 - (eras_pos[i] + pad))); for (j = i + 1; j > 0; j--) {
tmp = index_of[lambda[j - 1]]; if (tmp != nn) {
lambda[j] ^=
alpha_to[rs_modnn(rs, u + tmp)];
}
}
}
}
for (i = 0; i < nroots + 1; i++)
b[i] = index_of[lambda[i]];
/* *BeginBerlekamp-Masseyalgorithmtodetermineerror+erasure *locatorpolynomial
*/
r = no_eras;
el = no_eras; while (++r <= nroots) { /* r is the step number */ /* Compute discrepancy at the r-th step in poly-form */
discr_r = 0; for (i = 0; i < r; i++) { if ((lambda[i] != 0) && (s[r - i - 1] != nn)) {
discr_r ^=
alpha_to[rs_modnn(rs,
index_of[lambda[i]] +
s[r - i - 1])];
}
}
discr_r = index_of[discr_r]; /* Index form */ if (discr_r == nn) { /* 2 lines below: B(x) <-- x*B(x) */
memmove (&b[1], b, nroots * sizeof (b[0]));
b[0] = nn;
} else { /* 7 lines below: T(x) <-- lambda(x)-discr_r*x*b(x) */
t[0] = lambda[0]; for (i = 0; i < nroots; i++) { if (b[i] != nn) {
t[i + 1] = lambda[i + 1] ^
alpha_to[rs_modnn(rs, discr_r +
b[i])];
} else
t[i + 1] = lambda[i + 1];
} if (2 * el <= r + no_eras - 1) {
el = r + no_eras - el; /* *2linesbelow:B(x)<--inv(discr_r)* *lambda(x)
*/ for (i = 0; i <= nroots; i++) {
b[i] = (lambda[i] == 0) ? nn :
rs_modnn(rs, index_of[lambda[i]]
- discr_r + nn);
}
} else { /* 2 lines below: B(x) <-- x*B(x) */
memmove(&b[1], b, nroots * sizeof(b[0]));
b[0] = nn;
}
memcpy(lambda, t, (nroots + 1) * sizeof(t[0]));
}
}
/* Convert lambda to index form and compute deg(lambda(x)) */
deg_lambda = 0; for (i = 0; i < nroots + 1; i++) {
lambda[i] = index_of[lambda[i]]; if (lambda[i] != nn)
deg_lambda = i;
}
/* lambda[i+1] for i even is the formal derivative
* lambda_pr of lambda[i] */ for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) { if (lambda[i + 1] != nn) {
den ^= alpha_to[rs_modnn(rs, lambda[i + 1] +
i * root[j])];
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.