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