/** * <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]); } }
if ($a == 0) { throw new Exception(); } return $this->expTable[$this->size - $this->logTable[$a] - 1]; } /** * @return product of a and b in GF(size) */ function multiply($a, $b) { if ($a == 0 || $b == 0) { return 0; } return $this->expTable[($this->logTable[$a] + $this->logTable[$b]) % ($this->size - 1)]; } public function getSize() { return $this->size; } public function getGeneratorBase() { return $this->generatorBase; } // @Override public function toString() { return "GF(0x" . dechex(intval($this->primitive)) . ',' . $this->size . ')'; } } GenericGF::Init();
public function multiply(GenericGFPoly $other) { if ($other->getField() != $this->field) { throw new \InvalidArgumentException('GenericGFPolys do not have same GenericGF field'); } if ($this->isZero() || $other->isZero()) { return $this->field->getZero(); } $aCoefficients = $this->getCoefficients(); $aLength = count($aCoefficients); $bCoefficients = $other->getCoefficients(); $bLength = count($bCoefficients); $product = array_fill(0, $aLength + $bLength - 1, 0); for ($i = 0; $i < $aLength; $i++) { $aCoeff = $aCoefficients[$i]; for ($j = 0; $j < $bLength; $j++) { $product[$i + $j] = GenericGF::addOrSubtract($product[$i + $j], $this->field->multiply($aCoeff, $bCoefficients[$j])); } } return new self($this->field, $product); }