Mercurial > hgrepos > Python2 > PyMuPDF
view mupdf-source/thirdparty/zxing-cpp/core/src/ReedSolomonDecoder.cpp @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line source
/* * Copyright 2016 Nu-book Inc. * Copyright 2016 ZXing authors * Copyright 2017 Axel Waggershauser */ // SPDX-License-Identifier: Apache-2.0 #include "ReedSolomonDecoder.h" #include "GenericGF.h" #include "ZXConfig.h" #include <algorithm> #include <stdexcept> #include <utility> namespace ZXing { static bool RunEuclideanAlgorithm(const GenericGF& field, std::vector<int>&& rCoefs, GenericGFPoly& sigma, GenericGFPoly& omega) { int R = Size(rCoefs); // == numECCodeWords GenericGFPoly r(field, std::move(rCoefs)); GenericGFPoly& tLast = omega.setField(field); GenericGFPoly& t = sigma.setField(field); ZX_THREAD_LOCAL GenericGFPoly q, rLast; rLast.setField(field); q.setField(field); rLast.setMonomial(1, R); tLast.setMonomial(0); t.setMonomial(1); // Assume r's degree is < rLast's if (r.degree() >= rLast.degree()) swap(r, rLast); // Run Euclidean algorithm until r's degree is less than R/2 while (r.degree() >= R / 2) { swap(tLast, t); swap(rLast, r); // Divide rLastLast by rLast, with quotient in q and remainder in r if (rLast.isZero()) return false; // Oops, Euclidean algorithm already terminated? r.divide(rLast, q); q.multiply(tLast); q.addOrSubtract(t); swap(t, q); // t = q if (r.degree() >= rLast.degree()) throw std::runtime_error("Division algorithm failed to reduce polynomial?"); } int sigmaTildeAtZero = t.constant(); if (sigmaTildeAtZero == 0) return false; int inverse = field.inverse(sigmaTildeAtZero); t.multiplyByMonomial(inverse); r.multiplyByMonomial(inverse); // sigma is t omega = std::move(r); return true; } static std::vector<int> FindErrorLocations(const GenericGF& field, const GenericGFPoly& errorLocator) { // This is a direct application of Chien's search int numErrors = errorLocator.degree(); std::vector<int> res; res.reserve(numErrors); for (int i = 1; i < field.size() && Size(res) < numErrors; i++) if (errorLocator.evaluateAt(i) == 0) res.push_back(field.inverse(i)); if (Size(res) != numErrors) return {}; // Error locator degree does not match number of roots return res; } static std::vector<int> FindErrorMagnitudes(const GenericGF& field, const GenericGFPoly& errorEvaluator, const std::vector<int>& errorLocations) { // This is directly applying Forney's Formula int s = Size(errorLocations); std::vector<int> res(s); for (int i = 0; i < s; ++i) { int xiInverse = field.inverse(errorLocations[i]); int denom = 1; for (int j = 0; j < s; ++j) if (i != j) denom = field.multiply(denom, 1 ^ field.multiply(errorLocations[j], xiInverse)); res[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse), field.inverse(denom)); if (field.generatorBase() != 0) res[i] = field.multiply(res[i], xiInverse); } return res; } bool ReedSolomonDecode(const GenericGF& field, std::vector<int>& message, int numECCodeWords) { GenericGFPoly poly(field, message); std::vector<int> syndromes(numECCodeWords); for (int i = 0; i < numECCodeWords; i++) syndromes[numECCodeWords - 1 - i] = poly.evaluateAt(field.exp(i + field.generatorBase())); // if all syndromes are 0 there is no error to correct if (std::all_of(syndromes.begin(), syndromes.end(), [](int c) { return c == 0; })) return true; ZX_THREAD_LOCAL GenericGFPoly sigma, omega; if (!RunEuclideanAlgorithm(field, std::move(syndromes), sigma, omega)) return false; auto errorLocations = FindErrorLocations(field, sigma); if (errorLocations.empty()) return false; auto errorMagnitudes = FindErrorMagnitudes(field, omega, errorLocations); int msgLen = Size(message); for (int i = 0; i < Size(errorLocations); ++i) { int position = msgLen - 1 - field.log(errorLocations[i]); if (position < 0) return false; message[position] ^= errorMagnitudes[i]; } return true; } } // namespace ZXing
