not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
5.0 KiB

  1. /*
  2. Ported to JavaScript by Lazar Laszlo 2011
  3. lazarsoft@gmail.com, www.lazarsoft.info
  4. */
  5. /*
  6. *
  7. * Copyright 2007 ZXing authors
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License");
  10. * you may not use this file except in compliance with the License.
  11. * You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing, software
  16. * distributed under the License is distributed on an "AS IS" BASIS,
  17. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18. * See the License for the specific language governing permissions and
  19. * limitations under the License.
  20. */
  21. function ReedSolomonDecoder(field)
  22. {
  23. this.field = field;
  24. this.decode=function(received, twoS)
  25. {
  26. var poly = new GF256Poly(this.field, received);
  27. var syndromeCoefficients = new Array(twoS);
  28. for(var i=0;i<syndromeCoefficients.length;i++)syndromeCoefficients[i]=0;
  29. var dataMatrix = false;//this.field.Equals(GF256.DATA_MATRIX_FIELD);
  30. var noError = true;
  31. for (var i = 0; i < twoS; i++)
  32. {
  33. // Thanks to sanfordsquires for this fix:
  34. var evalu = poly.evaluateAt(this.field.exp(dataMatrix?i + 1:i));
  35. syndromeCoefficients[syndromeCoefficients.length - 1 - i] = evalu;
  36. if (evalu != 0)
  37. {
  38. noError = false;
  39. }
  40. }
  41. if (noError)
  42. {
  43. return ;
  44. }
  45. var syndrome = new GF256Poly(this.field, syndromeCoefficients);
  46. var sigmaOmega = this.runEuclideanAlgorithm(this.field.buildMonomial(twoS, 1), syndrome, twoS);
  47. var sigma = sigmaOmega[0];
  48. var omega = sigmaOmega[1];
  49. var errorLocations = this.findErrorLocations(sigma);
  50. var errorMagnitudes = this.findErrorMagnitudes(omega, errorLocations, dataMatrix);
  51. for (var i = 0; i < errorLocations.length; i++)
  52. {
  53. var position = received.length - 1 - this.field.log(errorLocations[i]);
  54. if (position < 0)
  55. {
  56. throw "ReedSolomonException Bad error location";
  57. }
  58. received[position] = GF256.addOrSubtract(received[position], errorMagnitudes[i]);
  59. }
  60. }
  61. this.runEuclideanAlgorithm=function( a, b, R)
  62. {
  63. // Assume a's degree is >= b's
  64. if (a.Degree < b.Degree)
  65. {
  66. var temp = a;
  67. a = b;
  68. b = temp;
  69. }
  70. var rLast = a;
  71. var r = b;
  72. var sLast = this.field.One;
  73. var s = this.field.Zero;
  74. var tLast = this.field.Zero;
  75. var t = this.field.One;
  76. // Run Euclidean algorithm until r's degree is less than R/2
  77. while (r.Degree >= Math.floor(R / 2))
  78. {
  79. var rLastLast = rLast;
  80. var sLastLast = sLast;
  81. var tLastLast = tLast;
  82. rLast = r;
  83. sLast = s;
  84. tLast = t;
  85. // Divide rLastLast by rLast, with quotient in q and remainder in r
  86. if (rLast.Zero)
  87. {
  88. // Oops, Euclidean algorithm already terminated?
  89. throw "r_{i-1} was zero";
  90. }
  91. r = rLastLast;
  92. var q = this.field.Zero;
  93. var denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree);
  94. var dltInverse = this.field.inverse(denominatorLeadingTerm);
  95. while (r.Degree >= rLast.Degree && !r.Zero)
  96. {
  97. var degreeDiff = r.Degree - rLast.Degree;
  98. var scale = this.field.multiply(r.getCoefficient(r.Degree), dltInverse);
  99. q = q.addOrSubtract(this.field.buildMonomial(degreeDiff, scale));
  100. r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
  101. //r.EXE();
  102. }
  103. s = q.multiply1(sLast).addOrSubtract(sLastLast);
  104. t = q.multiply1(tLast).addOrSubtract(tLastLast);
  105. }
  106. var sigmaTildeAtZero = t.getCoefficient(0);
  107. if (sigmaTildeAtZero == 0)
  108. {
  109. throw "ReedSolomonException sigmaTilde(0) was zero";
  110. }
  111. var inverse = this.field.inverse(sigmaTildeAtZero);
  112. var sigma = t.multiply2(inverse);
  113. var omega = r.multiply2(inverse);
  114. return new Array(sigma, omega);
  115. }
  116. this.findErrorLocations=function( errorLocator)
  117. {
  118. // This is a direct application of Chien's search
  119. var numErrors = errorLocator.Degree;
  120. if (numErrors == 1)
  121. {
  122. // shortcut
  123. return new Array(errorLocator.getCoefficient(1));
  124. }
  125. var result = new Array(numErrors);
  126. var e = 0;
  127. for (var i = 1; i < 256 && e < numErrors; i++)
  128. {
  129. if (errorLocator.evaluateAt(i) == 0)
  130. {
  131. result[e] = this.field.inverse(i);
  132. e++;
  133. }
  134. }
  135. if (e != numErrors)
  136. {
  137. throw "Error locator degree does not match number of roots";
  138. }
  139. return result;
  140. }
  141. this.findErrorMagnitudes=function( errorEvaluator, errorLocations, dataMatrix)
  142. {
  143. // This is directly applying Forney's Formula
  144. var s = errorLocations.length;
  145. var result = new Array(s);
  146. for (var i = 0; i < s; i++)
  147. {
  148. var xiInverse = this.field.inverse(errorLocations[i]);
  149. var denominator = 1;
  150. for (var j = 0; j < s; j++)
  151. {
  152. if (i != j)
  153. {
  154. denominator = this.field.multiply(denominator, GF256.addOrSubtract(1, this.field.multiply(errorLocations[j], xiInverse)));
  155. }
  156. }
  157. result[i] = this.field.multiply(errorEvaluator.evaluateAt(xiInverse), this.field.inverse(denominator));
  158. // Thanks to sanfordsquires for this fix:
  159. if (dataMatrix)
  160. {
  161. result[i] = this.field.multiply(result[i], xiInverse);
  162. }
  163. }
  164. return result;
  165. }
  166. }