/** * <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]); } }
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); }