Esempio n. 1
0
        private int[] findErrorMagnitudes(GF256Poly errorEvaluator, int[] errorLocations, bool dataMatrix)
        {
            // This is directly applying Forney's Formula
            int s = errorLocations.Length;

            int[] result = new int[s];
            for (int i = 0; i < s; i++)
            {
                int xiInverse   = field.inverse(errorLocations[i]);
                int denominator = 1;
                for (int j = 0; j < s; j++)
                {
                    if (i != j)
                    {
                        denominator = field.multiply(denominator, GF256.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
                    }
                }
                result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));
                // Thanks to sanfordsquires for this fix:
                if (dataMatrix)
                {
                    result[i] = field.multiply(result[i], xiInverse);
                }
            }
            return(result);
        }
 public void encode(int[] toEncode, int ecBytes)
 {
     if (ecBytes == 0)
     {
         throw new System.ArgumentException("No error correction bytes");
     }
     int dataBytes = toEncode.Length - ecBytes;
     if (dataBytes <= 0)
     {
         throw new System.ArgumentException("No data bytes provided");
     }
     GF256Poly generator = buildGenerator(ecBytes);
     int[] infoCoefficients = new int[dataBytes];
     Array.Copy(toEncode, 0, infoCoefficients, 0, dataBytes);
     GF256Poly info = new GF256Poly(field, infoCoefficients);
     info = info.multiplyByMonomial(ecBytes, 1);
     GF256Poly remainder = info.divide(generator)[1];
     int[] coefficients = remainder.Coefficients;
     int numZeroCoefficients = ecBytes - coefficients.Length;
     for (int i = 0; i < numZeroCoefficients; i++)
     {
         toEncode[dataBytes + i] = 0;
     }
     Array.Copy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.Length);
 }
Esempio n. 3
0
        private int[] findErrorLocations(GF256Poly errorLocator)
        {
            // This is a direct application of Chien's search
            int numErrors = errorLocator.Degree;

            if (numErrors == 1)
            {
                // shortcut
                return(new int[] { errorLocator.getCoefficient(1) });
            }
            int[] result = new int[numErrors];
            int   e      = 0;

            for (int i = 1; i < 256 && e < numErrors; i++)
            {
                if (errorLocator.evaluateAt(i) == 0)
                {
                    result[e] = field.inverse(i);
                    e++;
                }
            }
            if (e != numErrors)
            {
                throw new ReedSolomonException("Error locator degree does not match number of roots");
            }
            return(result);
        }
Esempio n. 4
0
        private int[] MathForReferenceImplementation(int[] aCoeff, int[] bCoeff, string option)
        {
            GF256     field = GF256.QR_CODE_FIELD;
            GF256Poly aPoly = new GF256Poly(field, aCoeff);
            GF256Poly bPoly = new GF256Poly(field, bCoeff);

            switch (option)
            {
            case "xor":
                return(aPoly.addOrSubtract(bPoly).Coefficients);

            case "multy":
                return(aPoly.multiply(bPoly).Coefficients);

            default:
                throw new ArgumentException("No such test option");
            }
        }
Esempio n. 5
0
        /// <summary> <p>Decodes given set of received codewords, which include both data and error-correction
        /// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
        /// in the input.</p>
        ///
        /// </summary>
        /// <param name="received">data and error-correction codewords
        /// </param>
        /// <param name="twoS">number of error-correction codewords available
        /// </param>
        /// <throws>  ReedSolomonException if decoding fails for any reason </throws>
        public void  decode(int[] received, int twoS)
        {
            GF256Poly poly = new GF256Poly(field, received);

            int[] syndromeCoefficients = new int[twoS];
            bool  dataMatrix           = field.Equals(GF256.DATA_MATRIX_FIELD);
            bool  noError = true;

            for (int i = 0; i < twoS; i++)
            {
                // Thanks to sanfordsquires for this fix:
                int eval = poly.evaluateAt(field.exp(dataMatrix?i + 1:i));
                syndromeCoefficients[syndromeCoefficients.Length - 1 - i] = eval;
                if (eval != 0)
                {
                    noError = false;
                }
            }
            if (noError)
            {
                return;
            }
            GF256Poly syndrome = new GF256Poly(field, syndromeCoefficients);

            GF256Poly[] sigmaOmega = runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
            GF256Poly   sigma      = sigmaOmega[0];
            GF256Poly   omega      = sigmaOmega[1];

            int[] errorLocations  = findErrorLocations(sigma);
            int[] errorMagnitudes = findErrorMagnitudes(omega, errorLocations, dataMatrix);
            for (int i = 0; i < errorLocations.Length; i++)
            {
                int position = received.Length - 1 - field.log(errorLocations[i]);
                if (position < 0)
                {
                    throw new ReedSolomonException("Bad error location");
                }
                received[position] = GF256.addOrSubtract(received[position], errorMagnitudes[i]);
            }
        }
Esempio n. 6
0
 /// <summary> Create a representation of GF(256) using the given primitive polynomial.
 /// 
 /// </summary>
 /// <param name="primitive">irreducible polynomial whose coefficients are represented by
 /// the bits of an int, where the least-significant bit represents the constant
 /// coefficient
 /// </param>
 private GF256(int primitive)
 {
     expTable = new int[256];
     logTable = new int[256];
     int x = 1;
     for (int i = 0; i < 256; i++)
     {
         expTable[i] = x;
         x <<= 1; // x = x * 2; we're assuming the generator alpha is 2
         if (x >= 0x100)
         {
             x ^= primitive;
         }
     }
     for (int i = 0; i < 255; i++)
     {
         logTable[expTable[i]] = i;
     }
     // logTable[0] == 0 but this should never be used
     zero = new GF256Poly(this, new int[]{0});
     one = new GF256Poly(this, new int[]{1});
 }
Esempio n. 7
0
        /// <summary> Create a representation of GF(256) using the given primitive polynomial.
        ///
        /// </summary>
        /// <param name="primitive">irreducible polynomial whose coefficients are represented by
        /// the bits of an int, where the least-significant bit represents the constant
        /// coefficient
        /// </param>
        private GF256(int primitive)
        {
            expTable = new int[256];
            logTable = new int[256];
            int x = 1;

            for (int i = 0; i < 256; i++)
            {
                expTable[i] = x;
                x         <<= 1;         // x = x * 2; we're assuming the generator alpha is 2
                if (x >= 0x100)
                {
                    x ^= primitive;
                }
            }
            for (int i = 0; i < 255; i++)
            {
                logTable[expTable[i]] = i;
            }
            // logTable[0] == 0 but this should never be used
            zero = new GF256Poly(this, new int[] { 0 });
            one  = new GF256Poly(this, new int[] { 1 });
        }
 /// <summary> <p>Decodes given set of received codewords, which include both data and error-correction
 /// codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
 /// in the input.</p>
 /// 
 /// </summary>
 /// <param name="received">data and error-correction codewords
 /// </param>
 /// <param name="twoS">number of error-correction codewords available
 /// </param>
 /// <throws>  ReedSolomonException if decoding fails for any reason </throws>
 public void decode(int[] received, int twoS)
 {
     GF256Poly poly = new GF256Poly(field, received);
     int[] syndromeCoefficients = new int[twoS];
     bool dataMatrix = field.Equals(GF256.DATA_MATRIX_FIELD);
     bool noError = true;
     for (int i = 0; i < twoS; i++)
     {
         // Thanks to sanfordsquires for this fix:
         int eval = poly.evaluateAt(field.exp(dataMatrix?i + 1:i));
         syndromeCoefficients[syndromeCoefficients.Length - 1 - i] = eval;
         if (eval != 0)
         {
             noError = false;
         }
     }
     if (noError)
     {
         return ;
     }
     GF256Poly syndrome = new GF256Poly(field, syndromeCoefficients);
     GF256Poly[] sigmaOmega = runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
     GF256Poly sigma = sigmaOmega[0];
     GF256Poly omega = sigmaOmega[1];
     int[] errorLocations = findErrorLocations(sigma);
     int[] errorMagnitudes = findErrorMagnitudes(omega, errorLocations, dataMatrix);
     for (int i = 0; i < errorLocations.Length; i++)
     {
         int position = received.Length - 1 - field.log(errorLocations[i]);
         if (position < 0)
         {
             throw new ReedSolomonException("Bad error location");
         }
         received[position] = GF256.addOrSubtract(received[position], errorMagnitudes[i]);
     }
 }
Esempio n. 9
0
        private GF256Poly[] runEuclideanAlgorithm(GF256Poly a, GF256Poly b, int R)
        {
            // Assume a's degree is >= b's
            if (a.Degree < b.Degree)
            {
                GF256Poly temp = a;
                a = b;
                b = temp;
            }

            GF256Poly rLast = a;
            GF256Poly r     = b;
            GF256Poly sLast = field.One;
            GF256Poly s     = field.Zero;
            GF256Poly tLast = field.Zero;
            GF256Poly t     = field.One;

            // Run Euclidean algorithm until r's degree is less than R/2
            while (r.Degree >= R / 2)
            {
                GF256Poly rLastLast = rLast;
                GF256Poly sLastLast = sLast;
                GF256Poly tLastLast = tLast;
                rLast = r;
                sLast = s;
                tLast = t;

                // Divide rLastLast by rLast, with quotient in q and remainder in r
                if (rLast.Zero)
                {
                    // Oops, Euclidean algorithm already terminated?
                    throw new ReedSolomonException("r_{i-1} was zero");
                }
                r = rLastLast;
                GF256Poly q = field.Zero;
                int       denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree);
                int       dltInverse             = field.inverse(denominatorLeadingTerm);
                while (r.Degree >= rLast.Degree && !r.Zero)
                {
                    int degreeDiff = r.Degree - rLast.Degree;
                    int scale      = field.multiply(r.getCoefficient(r.Degree), dltInverse);
                    q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));
                    r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
                }

                s = q.multiply(sLast).addOrSubtract(sLastLast);
                t = q.multiply(tLast).addOrSubtract(tLastLast);
            }

            int sigmaTildeAtZero = t.getCoefficient(0);

            if (sigmaTildeAtZero == 0)
            {
                throw new ReedSolomonException("sigmaTilde(0) was zero");
            }

            int       inverse = field.inverse(sigmaTildeAtZero);
            GF256Poly sigma   = t.multiply(inverse);
            GF256Poly omega   = r.multiply(inverse);

            return(new GF256Poly[] { sigma, omega });
        }
        private GF256Poly[] runEuclideanAlgorithm(GF256Poly a, GF256Poly b, int R)
        {
            // Assume a's degree is >= b's
            if (a.Degree < b.Degree)
            {
                GF256Poly temp = a;
                a = b;
                b = temp;
            }

            GF256Poly rLast = a;
            GF256Poly r = b;
            GF256Poly sLast = field.One;
            GF256Poly s = field.Zero;
            GF256Poly tLast = field.Zero;
            GF256Poly t = field.One;

            // Run Euclidean algorithm until r's degree is less than R/2
            while (r.Degree >= R / 2)
            {
                GF256Poly rLastLast = rLast;
                GF256Poly sLastLast = sLast;
                GF256Poly tLastLast = tLast;
                rLast = r;
                sLast = s;
                tLast = t;

                // Divide rLastLast by rLast, with quotient in q and remainder in r
                if (rLast.Zero)
                {
                    // Oops, Euclidean algorithm already terminated?
                    throw new ReedSolomonException("r_{i-1} was zero");
                }
                r = rLastLast;
                GF256Poly q = field.Zero;
                int denominatorLeadingTerm = rLast.getCoefficient(rLast.Degree);
                int dltInverse = field.inverse(denominatorLeadingTerm);
                while (r.Degree >= rLast.Degree && !r.Zero)
                {
                    int degreeDiff = r.Degree - rLast.Degree;
                    int scale = field.multiply(r.getCoefficient(r.Degree), dltInverse);
                    q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));
                    r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
                }

                s = q.multiply(sLast).addOrSubtract(sLastLast);
                t = q.multiply(tLast).addOrSubtract(tLastLast);
            }

            int sigmaTildeAtZero = t.getCoefficient(0);
            if (sigmaTildeAtZero == 0)
            {
                throw new ReedSolomonException("sigmaTilde(0) was zero");
            }

            int inverse = field.inverse(sigmaTildeAtZero);
            GF256Poly sigma = t.multiply(inverse);
            GF256Poly omega = r.multiply(inverse);
            return new GF256Poly[]{sigma, omega};
        }
 private int[] findErrorMagnitudes(GF256Poly errorEvaluator, int[] errorLocations, bool dataMatrix)
 {
     // This is directly applying Forney's Formula
     int s = errorLocations.Length;
     int[] result = new int[s];
     for (int i = 0; i < s; i++)
     {
         int xiInverse = field.inverse(errorLocations[i]);
         int denominator = 1;
         for (int j = 0; j < s; j++)
         {
             if (i != j)
             {
                 denominator = field.multiply(denominator, GF256.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
             }
         }
         result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));
         // Thanks to sanfordsquires for this fix:
         if (dataMatrix)
         {
             result[i] = field.multiply(result[i], xiInverse);
         }
     }
     return result;
 }
 private int[] findErrorLocations(GF256Poly errorLocator)
 {
     // This is a direct application of Chien's search
     int numErrors = errorLocator.Degree;
     if (numErrors == 1)
     {
         // shortcut
         return new int[]{errorLocator.getCoefficient(1)};
     }
     int[] result = new int[numErrors];
     int e = 0;
     for (int i = 1; i < 256 && e < numErrors; i++)
     {
         if (errorLocator.evaluateAt(i) == 0)
         {
             result[e] = field.inverse(i);
             e++;
         }
     }
     if (e != numErrors)
     {
         throw new ReedSolomonException("Error locator degree does not match number of roots");
     }
     return result;
 }