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 }