Beispiel #1
0
 /**
  * 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.
  *
  * @param received data and error-correction codewords
  * @param twoS number of error-correction codewords available
  * @throws ReedSolomonException if decoding fails for any reason
  */
 public void decode(int[] received, int twoS) throws ReedSolomonException {
   GenericGFPoly poly = new GenericGFPoly(field, received);
   int[] syndromeCoefficients = new int[twoS];
   boolean noError = true;
   for (int i = 0; i < twoS; i++) {
     int eval = poly.evaluateAt(field.exp(i + field.getGeneratorBase()));
     syndromeCoefficients[syndromeCoefficients.length - 1 - i] = eval;
     if (eval != 0) {
       noError = false;
     }
   }
   if (noError) {
     return;
   }
   GenericGFPoly syndrome = new GenericGFPoly(field, syndromeCoefficients);
   GenericGFPoly[] sigmaOmega =
       runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
   GenericGFPoly sigma = sigmaOmega[0];
   GenericGFPoly omega = sigmaOmega[1];
   int[] errorLocations = findErrorLocations(sigma);
   int[] errorMagnitudes = findErrorMagnitudes(omega, errorLocations);
   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] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);
   }
 }
 /**
  * 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.
  *
  * @param received data and error-correction codewords
  * @param twoS number of error-correction codewords available
  * @throws ReedSolomonException if decoding fails for any reason
  */
 public void decode(int[] received, int twoS) throws ReedSolomonException {
   GenericGFPoly poly = new GenericGFPoly(field, received);
   int[] syndromeCoefficients = new int[twoS];
   boolean dataMatrix = field.equals(GenericGF.GenericGFs.AZTEC_DATA_8.mGf);
   boolean 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;
   }
   GenericGFPoly syndrome = new GenericGFPoly(field, syndromeCoefficients);
   GenericGFPoly[] sigmaOmega =
       runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
   GenericGFPoly sigma = sigmaOmega[0];
   GenericGFPoly 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] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);
   }
 }
 GenericGFPoly a(GenericGFPoly paramGenericGFPoly)
 {
   if (!this.a.equals(paramGenericGFPoly.a)) {
     throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field");
   }
   if (c()) {
     return paramGenericGFPoly;
   }
   if (paramGenericGFPoly.c()) {
     return this;
   }
   Object localObject1 = this.b;
   Object localObject2 = paramGenericGFPoly.b;
   if (localObject1.length > localObject2.length) {}
   for (;;)
   {
     int[] arrayOfInt = new int[localObject1.length];
     int i = localObject1.length - localObject2.length;
     System.arraycopy(localObject1, 0, arrayOfInt, 0, i);
     for (int j = i; j < localObject1.length; j++) {
       arrayOfInt[j] = GenericGF.b(localObject2[(j - i)], localObject1[j]);
     }
     return new GenericGFPoly(this.a, arrayOfInt);
     Object localObject3 = localObject2;
     localObject2 = localObject1;
     localObject1 = localObject3;
   }
 }
Beispiel #4
0
 private int[] findErrorMagnitudes(GenericGFPoly errorEvaluator, int[] errorLocations) {
   // 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,
         //    GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
         // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
         // Below is a funny-looking workaround from Steven Parkes
         int term = field.multiply(errorLocations[j], xiInverse);
         int termPlus1 = (term & 0x1) == 0 ? term | 1 : term & ~1;
         denominator = field.multiply(denominator, termPlus1);
       }
     }
     result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denominator));
     if (field.getGeneratorBase() != 0) {
       result[i] = field.multiply(result[i], xiInverse);
     }
   }
   return result;
 }
Beispiel #5
0
 private int[] findErrorLocations(GenericGFPoly errorLocator) throws ReedSolomonException {
   // This is a direct application of Chien's search
   int numErrors = errorLocator.getDegree();
   if (numErrors == 1) { // shortcut
     return new int[] {errorLocator.getCoefficient(1)};
   }
   int[] result = new int[numErrors];
   int e = 0;
   for (int i = 1; i < field.getSize() && 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;
 }
 GenericGFPoly b(GenericGFPoly paramGenericGFPoly)
 {
   if (!this.a.equals(paramGenericGFPoly.a)) {
     throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field");
   }
   if ((c()) || (paramGenericGFPoly.c())) {
     return this.a.a();
   }
   int[] arrayOfInt1 = this.b;
   int i = arrayOfInt1.length;
   int[] arrayOfInt2 = paramGenericGFPoly.b;
   int j = arrayOfInt2.length;
   int[] arrayOfInt3 = new int[-1 + (i + j)];
   for (int k = 0; k < i; k++)
   {
     int m = arrayOfInt1[k];
     for (int n = 0; n < j; n++) {
       arrayOfInt3[(k + n)] = GenericGF.b(arrayOfInt3[(k + n)], this.a.c(m, arrayOfInt2[n]));
     }
   }
   return new GenericGFPoly(this.a, arrayOfInt3);
 }
 GenericGFPoly[] c(GenericGFPoly paramGenericGFPoly)
 {
   if (!this.a.equals(paramGenericGFPoly.a)) {
     throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field");
   }
   if (paramGenericGFPoly.c()) {
     throw new IllegalArgumentException("Divide by 0");
   }
   GenericGFPoly localGenericGFPoly1 = this.a.a();
   int i = paramGenericGFPoly.a(paramGenericGFPoly.b());
   int j = this.a.c(i);
   GenericGFPoly localGenericGFPoly2 = localGenericGFPoly1;
   GenericGFPoly localGenericGFPoly4;
   for (GenericGFPoly localGenericGFPoly3 = this; (localGenericGFPoly3.b() >= paramGenericGFPoly.b()) && (!localGenericGFPoly3.c()); localGenericGFPoly3 = localGenericGFPoly3.a(localGenericGFPoly4))
   {
     int k = localGenericGFPoly3.b() - paramGenericGFPoly.b();
     int m = this.a.c(localGenericGFPoly3.a(localGenericGFPoly3.b()), j);
     localGenericGFPoly4 = paramGenericGFPoly.a(k, m);
     localGenericGFPoly2 = localGenericGFPoly2.a(this.a.a(k, m));
   }
   return new GenericGFPoly[] { localGenericGFPoly2, localGenericGFPoly3 };
 }
Beispiel #8
0
  private GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R)
      throws ReedSolomonException {
    // Assume a's degree is >= b's
    if (a.getDegree() < b.getDegree()) {
      GenericGFPoly temp = a;
      a = b;
      b = temp;
    }

    GenericGFPoly rLast = a;
    GenericGFPoly r = b;
    GenericGFPoly tLast = field.getZero();
    GenericGFPoly t = field.getOne();

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

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

      t = q.multiply(tLast).addOrSubtract(tLastLast);

      if (r.getDegree() >= rLast.getDegree()) {
        throw new IllegalStateException("Division algorithm failed to reduce polynomial?");
      }
    }

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

    int inverse = field.inverse(sigmaTildeAtZero);
    GenericGFPoly sigma = t.multiply(inverse);
    GenericGFPoly omega = r.multiply(inverse);
    return new GenericGFPoly[] {sigma, omega};
  }