ReedSolomon.cs
上传用户:tjjgrl
上传日期:2019-04-04
资源大小:1010k
文件大小:10k
源码类别:

电子政务应用

开发平台:

C#

  1. using System;
  2. namespace ThoughtWorks.QRCode.Codec.Ecc
  3. {
  4. public class ReedSolomon
  5. {
  6. virtual public bool CorrectionSucceeded
  7. {
  8. get
  9. {
  10. return correctionSucceeded;
  11. }
  12. }
  13. virtual public int NumCorrectedErrors
  14. {
  15. get
  16. {
  17. return NErrors;
  18. }
  19. }
  20. //G(x)=a^8+a^4+a^3+a^2+1
  21. internal int[] y;
  22. internal int[] gexp = new int[512];
  23. internal int[] glog = new int[256];
  24. internal int NPAR;
  25. //final int NPAR = 15;
  26. internal int MAXDEG;
  27. internal int[] synBytes;
  28. /* The Error Locator Polynomial, also known as Lambda or Sigma. Lambda[0] == 1 */
  29. internal int[] Lambda;
  30. /* The Error Evaluator Polynomial */
  31. internal int[] Omega;
  32. /* local ANSI declarations */
  33. /* error locations found using Chien's search*/
  34. internal int[] ErrorLocs = new int[256];
  35. internal int NErrors;
  36. /* erasure flags */
  37. internal int[] ErasureLocs = new int[256];
  38. internal int NErasures = 0;
  39. internal bool correctionSucceeded = true;
  40. public ReedSolomon(int[] source, int NPAR)
  41. {
  42. initializeGaloisTables();
  43. y = source;
  44. this.NPAR = NPAR;
  45. MAXDEG = NPAR * 2;
  46. synBytes = new int[MAXDEG];
  47. Lambda = new int[MAXDEG];
  48. Omega = new int[MAXDEG];
  49. }
  50. internal virtual void  initializeGaloisTables()
  51. {
  52. int i, z;
  53. int pinit, p1, p2, p3, p4, p5, p6, p7, p8;
  54. pinit = p2 = p3 = p4 = p5 = p6 = p7 = p8 = 0;
  55. p1 = 1;
  56. gexp[0] = 1;
  57. gexp[255] = gexp[0];
  58. glog[0] = 0; /* shouldn't log[0] be an error? */
  59. for (i = 1; i < 256; i++)
  60. {
  61. pinit = p8;
  62. p8 = p7;
  63. p7 = p6;
  64. p6 = p5;
  65. p5 = p4 ^ pinit;
  66. p4 = p3 ^ pinit;
  67. p3 = p2 ^ pinit;
  68. p2 = p1;
  69. p1 = pinit;
  70. gexp[i] = p1 + p2 * 2 + p3 * 4 + p4 * 8 + p5 * 16 + p6 * 32 + p7 * 64 + p8 * 128;
  71. gexp[i + 255] = gexp[i];
  72. }
  73. for (i = 1; i < 256; i++)
  74. {
  75. for (z = 0; z < 256; z++)
  76. {
  77. if (gexp[z] == i)
  78. {
  79. glog[i] = z;
  80. break;
  81. }
  82. }
  83. }
  84. }
  85. /* multiplication using logarithms */
  86. internal virtual int gmult(int a, int b)
  87. {
  88. int i, j;
  89. if (a == 0 || b == 0)
  90. return (0);
  91. i = glog[a];
  92. j = glog[b];
  93. return (gexp[i + j]);
  94. }
  95. internal virtual int ginv(int elt)
  96. {
  97. return (gexp[255 - glog[elt]]);
  98. }
  99. internal virtual void  decode_data(int[] data)
  100. {
  101. int i, j, sum;
  102. for (j = 0; j < MAXDEG; j++)
  103. {
  104. sum = 0;
  105. for (i = 0; i < data.Length; i++)
  106. {
  107. sum = data[i] ^ gmult(gexp[j + 1], sum);
  108. }
  109. synBytes[j] = sum;
  110. }
  111. }
  112. public virtual void  correct()
  113. {
  114. //
  115. decode_data(y);
  116. correctionSucceeded = true;
  117. bool hasError = false;
  118. for (int i = 0; i < synBytes.Length; i++)
  119. {
  120. //Console.out.println("SyndromeS"+String.valueOf(i) + " = " + synBytes[i]);
  121. if (synBytes[i] != 0)
  122. hasError = true;
  123. }
  124. if (hasError)
  125. correctionSucceeded = correct_errors_erasures(y, y.Length, 0, new int[1]);
  126. }
  127. internal virtual void  Modified_Berlekamp_Massey()
  128. {
  129. int n, L, L2, k, d, i;
  130. int[] psi = new int[MAXDEG];
  131. int[] psi2 = new int[MAXDEG];
  132. int[] D = new int[MAXDEG];
  133. int[] gamma = new int[MAXDEG];
  134. /* initialize Gamma, the erasure locator polynomial */
  135. init_gamma(gamma);
  136. /* initialize to z */
  137. copy_poly(D, gamma);
  138. mul_z_poly(D);
  139. copy_poly(psi, gamma);
  140. k = - 1; L = NErasures;
  141. for (n = NErasures; n < 8; n++)
  142. {
  143. d = compute_discrepancy(psi, synBytes, L, n);
  144. if (d != 0)
  145. {
  146. /* psi2 = psi - d*D */
  147. for (i = 0; i < MAXDEG; i++)
  148. psi2[i] = psi[i] ^ gmult(d, D[i]);
  149. if (L < (n - k))
  150. {
  151. L2 = n - k;
  152. k = n - L;
  153. /* D = scale_poly(ginv(d), psi); */
  154. for (i = 0; i < MAXDEG; i++)
  155. D[i] = gmult(psi[i], ginv(d));
  156. L = L2;
  157. }
  158. /* psi = psi2 */
  159. for (i = 0; i < MAXDEG; i++)
  160. psi[i] = psi2[i];
  161. }
  162. mul_z_poly(D);
  163. }
  164. for (i = 0; i < MAXDEG; i++)
  165. Lambda[i] = psi[i];
  166. compute_modified_omega();
  167. }
  168. /* given Psi (called Lambda in Modified_Berlekamp_Massey) and synBytes,
  169. compute the combined erasure/error evaluator polynomial as 
  170. Psi*S mod z^4
  171. */
  172. internal virtual void  compute_modified_omega()
  173. {
  174. int i;
  175. int[] product = new int[MAXDEG * 2];
  176. mult_polys(product, Lambda, synBytes);
  177. zero_poly(Omega);
  178. for (i = 0; i < NPAR; i++)
  179. Omega[i] = product[i];
  180. }
  181. /* polynomial multiplication */
  182. internal virtual void  mult_polys(int[] dst, int[] p1, int[] p2)
  183. {
  184. int i, j;
  185. int[] tmp1 = new int[MAXDEG * 2];
  186. for (i = 0; i < (MAXDEG * 2); i++)
  187. dst[i] = 0;
  188. for (i = 0; i < MAXDEG; i++)
  189. {
  190. for (j = MAXDEG; j < (MAXDEG * 2); j++)
  191. tmp1[j] = 0;
  192. /* scale tmp1 by p1[i] */
  193. for (j = 0; j < MAXDEG; j++)
  194. tmp1[j] = gmult(p2[j], p1[i]);
  195. /* and mult (shift) tmp1 right by i */
  196. for (j = (MAXDEG * 2) - 1; j >= i; j--)
  197. tmp1[j] = tmp1[j - i];
  198. for (j = 0; j < i; j++)
  199. tmp1[j] = 0;
  200. /* add into partial product */
  201. for (j = 0; j < (MAXDEG * 2); j++)
  202. dst[j] ^= tmp1[j];
  203. }
  204. }
  205. /* gamma = product (1-z*a^Ij) for erasure locs Ij */
  206. internal virtual void  init_gamma(int[] gamma)
  207. {
  208. int e;
  209. int[] tmp = new int[MAXDEG];
  210. zero_poly(gamma);
  211. zero_poly(tmp);
  212. gamma[0] = 1;
  213. for (e = 0; e < NErasures; e++)
  214. {
  215. copy_poly(tmp, gamma);
  216. scale_poly(gexp[ErasureLocs[e]], tmp);
  217. mul_z_poly(tmp);
  218. add_polys(gamma, tmp);
  219. }
  220. }
  221. internal virtual void  compute_next_omega(int d, int[] A, int[] dst, int[] src)
  222. {
  223. int i;
  224. for (i = 0; i < MAXDEG; i++)
  225. {
  226. dst[i] = src[i] ^ gmult(d, A[i]);
  227. }
  228. }
  229. internal virtual int compute_discrepancy(int[] lambda, int[] S, int L, int n)
  230. {
  231. int i, sum = 0;
  232. for (i = 0; i <= L; i++)
  233. sum ^= gmult(lambda[i], S[n - i]);
  234. return (sum);
  235. }
  236. /// <summary>******* polynomial arithmetic ******************</summary>
  237. internal virtual void  add_polys(int[] dst, int[] src)
  238. {
  239. int i;
  240. for (i = 0; i < MAXDEG; i++)
  241. dst[i] ^= src[i];
  242. }
  243. internal virtual void  copy_poly(int[] dst, int[] src)
  244. {
  245. int i;
  246. for (i = 0; i < MAXDEG; i++)
  247. dst[i] = src[i];
  248. }
  249. internal virtual void  scale_poly(int k, int[] poly)
  250. {
  251. int i;
  252. for (i = 0; i < MAXDEG; i++)
  253. poly[i] = gmult(k, poly[i]);
  254. }
  255. internal virtual void  zero_poly(int[] poly)
  256. {
  257. int i;
  258. for (i = 0; i < MAXDEG; i++)
  259. poly[i] = 0;
  260. }
  261. /* multiply by z, i.e., shift right by 1 */
  262. internal virtual void  mul_z_poly(int[] src)
  263. {
  264. int i;
  265. for (i = MAXDEG - 1; i > 0; i--)
  266. src[i] = src[i - 1];
  267. src[0] = 0;
  268. }
  269. /* Finds all the roots of an error-locator polynomial with coefficients
  270. * Lambda[j] by evaluating Lambda at successive values of alpha. 
  271. * This can be tested with the decoder's equations case.
  272. */
  273. internal virtual void  Find_Roots()
  274. {
  275. int sum, r, k;
  276. NErrors = 0;
  277. for (r = 1; r < 256; r++)
  278. {
  279. sum = 0;
  280. /* evaluate lambda at r */
  281. for (k = 0; k < NPAR + 1; k++)
  282. {
  283. sum ^= gmult(gexp[(k * r) % 255], Lambda[k]);
  284. }
  285. if (sum == 0)
  286. {
  287. ErrorLocs[NErrors] = (255 - r); NErrors++;
  288. //if (DEBUG) fprintf(stderr, "Root found at r = %d, (255-r) = %dn", r, (255-r));
  289. }
  290. }
  291. }
  292. /* Combined Erasure And Error Magnitude Computation 
  293. * Pass in the codeword, its size in bytes, as well as
  294. * an array of any known erasure locations, along the number
  295. * of these erasures.
  296. * Evaluate Omega(actually Psi)/Lambda' at the roots
  297. * alpha^(-i) for error locs i. 
  298. *
  299. * Returns 1 if everything ok, or 0 if an out-of-bounds error is found
  300. *
  301. */
  302. internal virtual bool correct_errors_erasures(int[] codeword, int csize, int nerasures, int[] erasures)
  303. {
  304. int r, i, j, err;
  305. /* If you want to take advantage of erasure correction, be sure to
  306. set NErasures and ErasureLocs[] with the locations of erasures. 
  307. */
  308. NErasures = nerasures;
  309. for (i = 0; i < NErasures; i++)
  310. ErasureLocs[i] = erasures[i];
  311. Modified_Berlekamp_Massey();
  312. Find_Roots();
  313. if ((NErrors <= NPAR) || NErrors > 0)
  314. {
  315. /* first check for illegal error locs */
  316. for (r = 0; r < NErrors; r++)
  317. {
  318. if (ErrorLocs[r] >= csize)
  319. {
  320. //if (DEBUG) fprintf(stderr, "Error loc i=%d outside of codeword length %dn", i, csize);
  321. //Console.out.println("Error loc i="+ErrorLocs[r]+" outside of codeword length"+csize);
  322. return false;
  323. }
  324. }
  325. for (r = 0; r < NErrors; r++)
  326. {
  327. int num, denom;
  328. i = ErrorLocs[r];
  329. /* evaluate Omega at alpha^(-i) */
  330. num = 0;
  331. for (j = 0; j < MAXDEG; j++)
  332. num ^= gmult(Omega[j], gexp[((255 - i) * j) % 255]);
  333. /* evaluate Lambda' (derivative) at alpha^(-i) ; all odd powers disappear */
  334. denom = 0;
  335. for (j = 1; j < MAXDEG; j += 2)
  336. {
  337. denom ^= gmult(Lambda[j], gexp[((255 - i) * (j - 1)) % 255]);
  338. }
  339. err = gmult(num, ginv(denom));
  340. //if (DEBUG) fprintf(stderr, "Error magnitude %#x at loc %dn", err, csize-i);
  341. codeword[csize - i - 1] ^= err;
  342. }
  343. //for (int p = 0; p < codeword.length; p++)
  344. // Console.out.println(codeword[p]);
  345. //Console.out.println("correction succeeded");
  346. return true;
  347. }
  348. else
  349. {
  350. //if (DEBUG && NErrors) fprintf(stderr, "Uncorrectable codewordn");
  351. //Console.out.println("Uncorrectable codeword");
  352. return false;
  353. }
  354. }
  355. }
  356. }