diff mupdf-source/thirdparty/zxing-cpp/core/src/GenericGFPoly.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 diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/zxing-cpp/core/src/GenericGFPoly.cpp	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,163 @@
+/*
+* Copyright 2016 Nu-book Inc.
+* Copyright 2016 ZXing authors
+* Copyright 2017 Axel Waggershauser
+*/
+// SPDX-License-Identifier: Apache-2.0
+
+#include "GenericGFPoly.h"
+
+#include "GenericGF.h"
+#include "ZXAlgorithms.h"
+
+#include <algorithm>
+#include <cassert>
+#include <stdexcept>
+
+namespace ZXing {
+
+int
+GenericGFPoly::evaluateAt(int a) const
+{
+	if (a == 0) // return the x^0 coefficient
+		return constant();
+
+	if (a == 1) // return the sum of the coefficients
+		return Reduce(_coefficients, 0, [](auto s, auto c) { return s ^ c; });
+
+	return std::accumulate(_coefficients.begin(), _coefficients.end(), 0,
+						   [this, a](auto s, auto c) { return _field->multiply(a, s) ^ c; });
+}
+
+GenericGFPoly& GenericGFPoly::addOrSubtract(GenericGFPoly& other)
+{
+	assert(_field == other._field); // "GenericGFPolys do not have same GenericGF field"
+	
+	if (isZero()) {
+		swap(*this, other);
+		return *this;
+	}
+	
+	if (other.isZero())
+		return *this;
+
+	auto& smallerCoefs = other._coefficients;
+	auto& largerCoefs = _coefficients;
+	if (smallerCoefs.size() > largerCoefs.size())
+		std::swap(smallerCoefs, largerCoefs);
+
+	size_t lengthDiff = largerCoefs.size() - smallerCoefs.size();
+
+	// high-order terms only found in higher-degree polynomial's coefficients stay untouched
+	for (size_t i = lengthDiff; i < largerCoefs.size(); ++i)
+		largerCoefs[i] ^= smallerCoefs[i - lengthDiff];
+
+	normalize();
+	return *this;
+}
+
+GenericGFPoly&
+GenericGFPoly::multiply(const GenericGFPoly& other)
+{
+	assert(_field == other._field); // "GenericGFPolys do not have same GenericGF field"
+
+	if (isZero() || other.isZero())
+		return setMonomial(0);
+
+	auto& a = _coefficients;
+	auto& b = other._coefficients;
+
+	// To disable the use of the malloc cache, simply uncomment:
+	// Coefficients _cache;
+	_cache.resize(a.size() + b.size() - 1);
+	std::fill(_cache.begin(), _cache.end(), 0);
+	for (size_t i = 0; i < a.size(); ++i)
+		for (size_t j = 0; j < b.size(); ++j)
+			_cache[i + j] ^= _field->multiply(a[i], b[j]);
+
+	_coefficients.swap(_cache);
+
+	normalize();
+	return *this;
+}
+
+GenericGFPoly&
+GenericGFPoly::multiplyByMonomial(int coefficient, int degree)
+{
+	assert(degree >= 0);
+
+	if (coefficient == 0)
+		return setMonomial(0);
+
+	for (int& c : _coefficients)
+		c = _field->multiply(c, coefficient);
+
+	_coefficients.resize(_coefficients.size() + degree, 0);
+
+	normalize();
+	return *this;
+}
+
+GenericGFPoly&
+GenericGFPoly::divide(const GenericGFPoly& other, GenericGFPoly& quotient)
+{
+	assert(_field == other._field); // "GenericGFPolys do not have same GenericGF field"
+
+	if (other.isZero())
+		throw std::invalid_argument("Divide by 0");
+
+	quotient.setField(*_field);
+	if (degree() < other.degree()) {
+		// the remainder is this and the quotient is 0
+		quotient.setMonomial(0);
+		return *this;
+	}
+
+	// use Expanded Synthetic Division (see https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders):
+	// we use the memory from this (the dividend) and swap it with quotient, which will then accumulate the result as
+	// [quotient : remainder]. we later copy back the remainder into this and shorten the quotient.
+	std::swap(*this, quotient);
+	auto& divisor = other._coefficients;
+	auto& result = quotient._coefficients;
+	auto normalizer = _field->inverse(divisor[0]);
+	for (int i = 0; i < Size(result) - (Size(divisor) - 1); ++i) {
+		auto& ci = result[i];
+		if (ci == 0)
+			continue;
+
+		ci = _field->multiply(ci, normalizer);
+
+		// we always skip the first coefficient of the divisor, because it's only used to normalize the dividend coefficient
+		for (int j = 1; j < Size(divisor); ++j)
+			result[i + j] ^= _field->multiply(divisor[j], ci); // equivalent to: result[i + j] += -divisor[j] * ci
+	}
+
+	// extract the normalized remainder from result
+	auto firstNonZero = std::find_if(result.end() - other.degree(), result.end(), [](int c){ return c != 0; });
+	if (firstNonZero == result.end()) {
+		setMonomial(0);
+	} else {
+		_coefficients.resize(result.end() - firstNonZero);
+		std::copy(firstNonZero, result.end(), _coefficients.begin());
+	}
+	// cut off the tail with the remainder to leave the quotient
+	result.resize(result.size() - other.degree());
+
+	return *this;
+}
+
+void GenericGFPoly::normalize()
+{
+	auto firstNonZero = FindIf(_coefficients, [](int c){ return c != 0; });
+	// Leading term must be non-zero for anything except the constant polynomial "0"
+	if (firstNonZero != _coefficients.begin()) {
+		if (firstNonZero == _coefficients.end()) {
+			_coefficients.resize(1, 0);
+		} else {
+			std::copy(firstNonZero, _coefficients.end(), _coefficients.begin());
+			_coefficients.resize(_coefficients.end() - firstNonZero);
+		}
+	}
+}
+
+} // namespace ZXing