/**
  * <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>
  *
  * @param received data and error-correction codewords
  * @param twoS number of error-correction codewords available
  * @throws ReedSolomonException if decoding fails for any reason
  */
 public function decode(&$received, $twoS)
 {
     $poly = new GenericGFPoly($this->field, $received);
     $syndromeCoefficients = fill_array(0, $twoS, 0);
     $noError = true;
     for ($i = 0; $i < $twoS; $i++) {
         $eval = $poly->evaluateAt($this->field->exp($i + $this->field->getGeneratorBase()));
         $syndromeCoefficients[count($syndromeCoefficients) - 1 - $i] = $eval;
         if ($eval != 0) {
             $noError = false;
         }
     }
     if ($noError) {
         return;
     }
     $syndrome = new GenericGFPoly($this->field, $syndromeCoefficients);
     $sigmaOmega = $this->runEuclideanAlgorithm($this->field->buildMonomial($twoS, 1), $syndrome, $twoS);
     $sigma = $sigmaOmega[0];
     $omega = $sigmaOmega[1];
     $errorLocations = $this->findErrorLocations($sigma);
     $errorMagnitudes = $this->findErrorMagnitudes($omega, $errorLocations);
     for ($i = 0; $i < count($errorLocations); $i++) {
         $position = count($received) - 1 - $this->field->log($errorLocations[$i]);
         if ($position < 0) {
             throw new ReedSolomonException("Bad error location");
         }
         $received[$position] = GenericGF::addOrSubtract($received[$position], $errorMagnitudes[$i]);
     }
 }
Exemplo n.º 2
0
 public function divide(GenericGFPoly $other)
 {
     if ($other->getField() != $this->field) {
         throw new \InvalidArgumentException('GenericGFPolys do not have same GenericGF field');
     }
     if ($other->isZero()) {
         throw new \InvalidArgumentException('Divide by 0');
     }
     $quotient = $this->field->getZero();
     $remainder = $this;
     $denominatorLeadingTerm = $other->getCoefficient($other->getDegree());
     $inverseDenominatorLeadingTerm = $this->field->inverse($denominatorLeadingTerm);
     while ($remainder->getDegree() >= $other->getDegree() && !$remainder->isZero()) {
         $degreeDifference = $remainder->getDegree() - $other->getDegree();
         $scale = $this->field->multiply($remainder->getCoefficient($remainder->getDegree()), $inverseDenominatorLeadingTerm);
         $term = $other->multiplyByMonomial($degreeDifference, $scale);
         $iterationQuotient = $this->field->buildMonomial($degreeDifference, $scale);
         $quotient = $quotient->addOrSubtract($iterationQuotient);
         $remainder = $remainder->addOrSubtract($term);
     }
     return new DivisionResult($quotient, $remainder);
 }