#pragma once
#include "ZXAlgorithms.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <vector>
namespace ZXing {
class GenericGF;
class GenericGFPoly
{
struct Coefficients : public std::vector<int>
{
void reserve(size_t s)
{
if (capacity() < s)
std::vector<int>::reserve(std::max(size_t(32), s));
}
void resize(size_t s)
{
reserve(s);
std::vector<int>::resize(s);
}
void resize(size_t s, int i)
{
reserve(s);
std::vector<int>::resize(s, i);
}
};
public:
GenericGFPoly() = default;
GenericGFPoly(const GenericGF& field, std::vector<int>&& coefficients) : _field(&field)
{
assert(!coefficients.empty());
_coefficients.swap(coefficients); normalize();
}
GenericGFPoly(const GenericGF& field, const std::vector<int>& coefficients) : GenericGFPoly(field, std::vector<int>(coefficients)) {}
GenericGFPoly& operator=(GenericGFPoly&& other) noexcept = default;
GenericGFPoly(GenericGFPoly&& other) noexcept = default;
GenericGFPoly& operator=(const GenericGFPoly& other) {
assert(_field == other._field);
_coefficients.reserve(other._coefficients.size());
_coefficients = other._coefficients;
return *this;
}
GenericGFPoly(const GenericGFPoly& other) {
_field = other._field;
*this = other;
}
GenericGFPoly& setField(const GenericGF& field)
{
_field = &field;
return *this;
}
const GenericGF& field() const noexcept { return *_field; }
const auto& coefficients() const noexcept { return _coefficients; }
int degree() const {
return Size(_coefficients) - 1;
}
bool isZero() const {
return _coefficients[0] == 0;
}
int leadingCoefficient() const noexcept {
return _coefficients.front();
}
int constant() const noexcept {
return _coefficients.back();
}
GenericGFPoly& setMonomial(int coefficient, int degree = 0)
{
assert(degree >= 0 && (coefficient != 0 || degree == 0));
_coefficients.resize(degree + 1);
std::fill(_coefficients.begin(), _coefficients.end(), 0);
_coefficients.front() = coefficient;
return *this;
}
int evaluateAt(int a) const;
GenericGFPoly& addOrSubtract(GenericGFPoly& other);
GenericGFPoly& multiply(const GenericGFPoly& other);
GenericGFPoly& multiplyByMonomial(int coefficient, int degree = 0);
GenericGFPoly& divide(const GenericGFPoly& other, GenericGFPoly& quotient);
friend void swap(GenericGFPoly& a, GenericGFPoly& b) noexcept
{
std::swap(a._field, b._field);
std::swap(a._coefficients, b._coefficients);
}
private:
void normalize();
const GenericGF* _field = nullptr;
Coefficients _coefficients, _cache; };
}