www.pudn.com > ReedSolomon_codec.rar > ReedSolomon.h
// ReedSolomon.h: interface for the CReedSolomon class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_REEDSOLOMON_H__7A4D7FA4_C47A_4880_9E03_833194109EA0__INCLUDED_) #define AFX_REEDSOLOMON_H__7A4D7FA4_C47A_4880_9E03_833194109EA0__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include#include #include #include #include using namespace std; #define DEBUG 1 /************************************************************************ 类CReedSolomon用于RS码的解码及编码 有两种方式初始化: 使用下面的_INIT_DATA或者使用预定义的值(只指定symsize). symsize表示2的多少次方, 码长为2**symsize. genpoly生成多项式, 应该为不可约多项式, 可参照预定义值 fcs 应该小于(1 << symsize). prim 不能为0, 且小于(1 << symsize) nroots 应该小于(1 << symsize), 表示校验码的长度. 纠错能力为0~nroots/2. ************************************************************************/ struct _INIT_DATA { int symsize; // RS code over GF(2**symsize) = mm int genpoly; // Generator polynomial int fcs; // First consecutive root, index form int prim;// Primitive element, index form int nroots;// Number of generator roots = number of parity symbols int ntrials; // no use }; // 预定义的初始值数组 extern _INIT_DATA Tab[]; template class CReedSolomon { public: CReedSolomon(unsigned int symsize, unsigned int gfpoly, unsigned int m_fcr, unsigned int m_prim, unsigned int m_nroots); CReedSolomon(_INIT_DATA data); CReedSolomon(unsigned int m); void Encode(T* data, T* parity); int Decode(T* data, T* eras_pos, int no_eras); virtual ~CReedSolomon(); private: inline int modnn(int x) { while (x >= m_nn) { x -= m_nn; x = (x >> m_mm) + (x & m_nn); } return x; } public: unsigned int m_mm; /* Bits per symbol */ unsigned int m_nn; /* Symbols per block (= (1< CReedSolomon ::CReedSolomon(unsigned int m) { assert(m >= 2 && m <= 16); _INIT_DATA& data = Tab[m - 2]; this->CReedSolomon < T >::CReedSolomon(data.symsize, data.genpoly, data.fcs, data.prim, data.nroots); } template CReedSolomon ::CReedSolomon(_INIT_DATA data) { this->CReedSolomon < T >::CReedSolomon(data.symsize, data.genpoly, data.fcs, data.prim, data.nroots); } #define A0 m_nn //#define T unsigned char template CReedSolomon ::CReedSolomon( unsigned int symsize, unsigned int gfpoly, unsigned int fcr, unsigned int prim, unsigned int nroots) { int i; int j; int sr; int root; int iprim; /* Need version with ints rather than chars */ assert(symsize <= 8 * sizeof(T)); assert(fcr < (1 << symsize)); assert(prim != 0 && prim < (1 << symsize)); /* Can't have more roots than symbol values! */ assert(nroots < (1 << symsize)); m_mm = symsize; m_nn = (1 << symsize) - 1; m_alpha_to = new T[m_nn + 1]; m_index_of = new T[m_nn + 1]; /* Generate Galois field lookup tables */ m_index_of[0] = A0; /* log(zero) = -inf */ m_alpha_to[A0] = 0; /* alpha**-inf = 0 */ sr = 1; for (i = 0; i < m_nn; i++) { m_index_of[sr] = i; m_alpha_to[i] = sr; sr <<= 1; if (sr & (1 << symsize)) sr ^= gfpoly; sr &= m_nn; } /* field generator polynomial is not primitive! */ assert(sr == 1); /* Form RS code generator polynomial from its roots */ m_genpoly = new T[nroots + 1]; m_fcr = fcr; m_prim = prim; m_nroots = nroots; /* Find m_prim-th root of 1, used in decoding */ for (iprim = 1; (iprim % prim) != 0; iprim += m_nn); m_iprim = iprim / prim; m_genpoly[0] = 1; for (i = 0, root = fcr * prim; i < nroots; i++, root += prim) { m_genpoly[i + 1] = 1; /* Multiply m_genpoly[] by @**(root + x) */ for (j = i; j > 0; j--) { if (m_genpoly[j] != 0) { m_genpoly[j] = m_genpoly[j - 1] ^ m_alpha_to[modnn(m_index_of[m_genpoly[j]] + root)]; } else m_genpoly[j] = m_genpoly[j - 1]; } /* m_genpoly[0] can never be zero */ m_genpoly[0] = m_alpha_to[modnn(m_index_of[m_genpoly[0]] + root)]; } /* convert m_genpoly[] to index form for quicker encoding */ for (i = 0; i <= nroots; i++) m_genpoly[i] = m_index_of[m_genpoly[i]]; } template CReedSolomon ::~CReedSolomon() { delete m_alpha_to; delete m_index_of; delete m_genpoly; } template void CReedSolomon ::Encode(T* data, T* bb) { unsigned int i; unsigned int j; T feedback; memset(bb, 0, m_nroots * sizeof(T)); for (i = 0; i < m_nn - m_nroots; i++) { feedback = m_index_of[data[i] ^ bb[0]]; if (feedback != A0) { /* feedback term is non-zero */ #ifdef UNNORMALIZED /* This line is unnecessary when m_genpoly[m_nroots] is unity, as it must * always be for the polynomials constructed by init_rs() */ feedback = modnn(m_nn - m_genpoly[m_nroots] + feedback); #endif for (j = 1; j < m_nroots; j++) { bb[j] ^= m_alpha_to[modnn(feedback + m_genpoly[m_nroots - j])]; } } /* Shift */ memmove(&bb[0], &bb[1], sizeof(T) * (m_nroots - 1)); if (feedback != A0) { bb[m_nroots - 1] = m_alpha_to[modnn(feedback + m_genpoly[0])]; } else bb[m_nroots - 1] = 0; } } template int CReedSolomon ::Decode(T* data, T* eras_pos, int no_eras) { int deg_lambda; int el; int deg_omega; int i; int j; int r; int k; T u; T q; T tmp; T num1; T num2; T den; T discr_r; /* Err+Eras Locator poly * and syndrome poly */ vector < T > lambda(m_nroots + 1), s(m_nroots); vector < T > b(m_nroots + 1), t(m_nroots + 1), omega(m_nroots + 1); vector root(m_nroots); vector reg(m_nroots + 1); vector loc(m_nroots); int syn_error; int count; /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ for (i = 0; i < m_nroots; i++) s[i] = data[0]; for (j = 1; j < m_nn; j++) { for (i = 0; i < m_nroots; i++) { if (s[i] == 0) { s[i] = data[j]; } else { s[i] = data[j] ^ m_alpha_to[modnn(m_index_of[s[i]] + (m_fcr + i) * m_prim)]; } } } /* Convert syndromes to index form, checking for nonzero condition */ syn_error = 0; for (i = 0; i < m_nroots; i++) { syn_error |= s[i]; s[i] = m_index_of[s[i]]; } if (!syn_error) { /* if syndrome is zero, data[] is a codeword and there are no * errors to correct. So return data[] unmodified */ count = 0; goto finish; } memset(&lambda[1], 0, m_nroots * sizeof(lambda[0])); lambda[0] = 1; if (no_eras > 0) { /* Init lambda to be the erasure locator polynomial */ lambda[1] = m_alpha_to[modnn(m_prim * (m_nn - 1 - eras_pos[0]))]; for (i = 1; i < no_eras; i++) { u = modnn(m_prim * (m_nn - 1 - eras_pos[i])); for (j = i + 1; j > 0; j--) { tmp = m_index_of[lambda[j - 1]]; if (tmp != A0) lambda[j] ^= m_alpha_to[modnn(u + tmp)]; } } } for (i = 0; i < m_nroots + 1; i++) b[i] = m_index_of[lambda[i]]; /* * Begin Berlekamp-Massey algorithm to determine error+erasure * locator polynomial */ r = no_eras; el = no_eras; while (++r <= m_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] != A0)) { discr_r ^= m_alpha_to[modnn(m_index_of[lambda[i]] + s[r - i - 1])]; } } discr_r = m_index_of[discr_r]; /* Index form */ if (discr_r == A0) { /* 2 lines below: B(x) <-- x*B(x) */ //memmove(&b[1],b,m_nroots*sizeof(b[0])); char_traits < T >::move(b.begin() + 1, b.begin(), b.size() - 1); b[0] = A0; } else { /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ t[0] = lambda[0]; for (i = 0; i < m_nroots; i++) { if (b[i] != A0) { t[i + 1] = lambda[i + 1] ^ m_alpha_to[modnn(discr_r + b[i])]; } else t[i + 1] = lambda[i + 1]; } if (2 * el <= r + no_eras - 1) { el = r + no_eras - el; /* * 2 lines below: B(x) <-- inv(discr_r) * * lambda(x) */ for (i = 0; i <= m_nroots; i++) { b[i] = (lambda[i] == 0) ? A0 : modnn(m_index_of[lambda[i]] - discr_r + m_nn); } } else { /* 2 lines below: B(x) <-- x*B(x) */ //memmove(&b[1],b,m_nroots*sizeof(b[0])); char_traits < T >::move(b.begin() + 1, b.begin(), b.size() - 1); b[0] = A0; } // memcpy(lambda,t,(m_nroots+1)*sizeof(t[0])); char_traits < T >::copy(lambda.begin(), t.begin(), t.size()); } } /* Convert lambda to index form and compute deg(lambda(x)) */ deg_lambda = 0; for (i = 0; i < m_nroots + 1; i++) { lambda[i] = m_index_of[lambda[i]]; if (lambda[i] != A0) deg_lambda = i; } /* Find roots of the error+erasure locator polynomial by Chien search */ // memcpy(®[1],&lambda[1],m_nroots*sizeof(reg[0])); char_traits < T >::copy(reg.begin() + 1, lambda.begin() + 1, reg.size() - 1); count = 0; /* Number of roots of lambda(x) */ for (i = 1, k = m_iprim - 1; i <= m_nn; i++, k = modnn(k + m_iprim)) { q = 1; /* lambda[0] is always 0 */ for (j = deg_lambda; j > 0; j--) { if (reg[j] != A0) { reg[j] = modnn(reg[j] + j); q ^= m_alpha_to[reg[j]]; } } if (q != 0) continue; /* Not a root */ /* store root (index-form) and error location number */ root[count] = i; loc[count] = k; /* If we've already found max possible roots, * abort the search to save time */ if (++count == deg_lambda) break; } if (deg_lambda != count) { /* * deg(lambda) unequal to number of roots => uncorrectable * error detected */ count = -1; goto finish; } /* * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo * x**m_nroots). in index form. Also find deg(omega). */ deg_omega = 0; for (i = 0; i < m_nroots; i++) { tmp = 0; j = (deg_lambda < i) ? deg_lambda : i; for (; j >= 0; j--) { if ((s[i - j] != A0) && (lambda[j] != A0)) { tmp ^= m_alpha_to[modnn(s[i - j] + lambda[j])]; } } if (tmp != 0) deg_omega = i; omega[i] = m_index_of[tmp]; } omega[m_nroots] = A0; /* * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = * inv(X(l))**(m_fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form */ for (j = count - 1; j >= 0; j--) { num1 = 0; for (i = deg_omega; i >= 0; i--) { if (omega[i] != A0) { num1 ^= m_alpha_to[modnn(omega[i] + i * root[j])]; } } num2 = m_alpha_to[modnn(root[j] * (m_fcr - 1) + m_nn)]; den = 0; /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ for (i = _cpp_min((unsigned int) deg_lambda, m_nroots - 1) &~1; i >= 0; i -= 2) { if (lambda[i + 1] != A0) { den ^= m_alpha_to[modnn(lambda[i + 1] + i * root[j])]; } } if (den == 0) { count = -1; goto finish; } /* Apply error to data */ if (num1 != 0) { data[loc[j]] ^= m_alpha_to[modnn(m_index_of[num1] + m_index_of[num2] + m_nn - m_index_of[den])]; } } finish: if (eras_pos != NULL) { for (i = 0; i < count; i++) eras_pos[i] = loc[i]; } return count; } #endif // !defined(AFX_REEDSOLOMON_H__7A4D7FA4_C47A_4880_9E03_833194109EA0__INCLUDED_)