mirror of
https://github.com/status-im/qzxing.git
synced 2025-02-08 00:55:33 +00:00
199 lines
5.7 KiB
C++
199 lines
5.7 KiB
C++
/*
|
|
* GF256Poly.cpp
|
|
* zxing
|
|
*
|
|
* Created by Christian Brunschen on 05/05/2008.
|
|
* Copyright 2008 Google UK. All rights reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <zxing/common/reedsolomon/GF256Poly.h>
|
|
#include <zxing/common/reedsolomon/GF256.h>
|
|
#include <zxing/common/IllegalArgumentException.h>
|
|
|
|
namespace zxing {
|
|
using namespace std;
|
|
|
|
void GF256Poly::fixCoefficients() {
|
|
int coefficientsLength = coefficients.size();
|
|
if (coefficientsLength > 1 && coefficients[0] == 0) {
|
|
// Leading term must be non-zero for anything except
|
|
// the constant polynomial "0"
|
|
int firstNonZero = 1;
|
|
while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) {
|
|
firstNonZero++;
|
|
}
|
|
if (firstNonZero == coefficientsLength) {
|
|
coefficientsLength = field.getZero()->coefficients.size();
|
|
coefficients.reset(new Array<int> (coefficientsLength));
|
|
*coefficients = *(field.getZero()->coefficients);
|
|
} else {
|
|
ArrayRef<int> c(coefficients);
|
|
coefficientsLength -= firstNonZero;
|
|
coefficients.reset(new Array<int> (coefficientsLength));
|
|
for (int i = 0; i < coefficientsLength; i++) {
|
|
coefficients[i] = c[i + firstNonZero];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
GF256Poly::GF256Poly(GF256 &f, ArrayRef<int> c) :
|
|
Counted(), field(f), coefficients(c) {
|
|
fixCoefficients();
|
|
}
|
|
|
|
GF256Poly::~GF256Poly() {
|
|
|
|
}
|
|
|
|
int GF256Poly::getDegree() {
|
|
return coefficients.size() - 1;
|
|
}
|
|
|
|
bool GF256Poly::isZero() {
|
|
return coefficients[0] == 0;
|
|
}
|
|
|
|
int GF256Poly::getCoefficient(int degree) {
|
|
return coefficients[coefficients.size() - 1 - degree];
|
|
}
|
|
|
|
int GF256Poly::evaluateAt(int a) {
|
|
if (a == 0) {
|
|
return getCoefficient(0);
|
|
}
|
|
int size = coefficients.size();
|
|
if (a == 1) {
|
|
// Just the sum of the coefficients
|
|
int result = 0;
|
|
for (int i = 0; i < size; i++) {
|
|
result = GF256::addOrSubtract(result, coefficients[i]);
|
|
}
|
|
return result;
|
|
}
|
|
int result = coefficients[0];
|
|
for (int i = 1; i < size; i++) {
|
|
result = GF256::addOrSubtract(field.multiply(a, result), coefficients[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Ref<GF256Poly> GF256Poly::addOrSubtract(Ref<GF256Poly> b) {
|
|
if (&field != &b->field) {
|
|
throw IllegalArgumentException("Fields must be the same");
|
|
}
|
|
if (isZero()) {
|
|
return b;
|
|
}
|
|
if (b->isZero()) {
|
|
return Ref<GF256Poly>(this);
|
|
}
|
|
|
|
ArrayRef<int> largerCoefficients = coefficients;
|
|
ArrayRef<int> smallerCoefficients = b->coefficients;
|
|
if (smallerCoefficients.size() > largerCoefficients.size()) {
|
|
ArrayRef<int> tmp(smallerCoefficients);
|
|
smallerCoefficients = largerCoefficients;
|
|
largerCoefficients = tmp;
|
|
}
|
|
|
|
ArrayRef<int> sumDiff(new Array<int> (largerCoefficients.size()));
|
|
|
|
unsigned lengthDiff = largerCoefficients.size() - smallerCoefficients.size();
|
|
for (unsigned i = 0; i < lengthDiff; i++) {
|
|
sumDiff[i] = largerCoefficients[i];
|
|
}
|
|
for (unsigned i = lengthDiff; i < largerCoefficients.size(); i++) {
|
|
sumDiff[i] = GF256::addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
|
|
}
|
|
return Ref<GF256Poly>(new GF256Poly(field, sumDiff));
|
|
}
|
|
|
|
Ref<GF256Poly> GF256Poly::multiply(Ref<GF256Poly> b) {
|
|
if (&field != &b->field) {
|
|
throw IllegalArgumentException("Fields must be the same");
|
|
}
|
|
if (isZero() || b->isZero()) {
|
|
return field.getZero();
|
|
}
|
|
ArrayRef<int> aCoefficients = coefficients;
|
|
int aLength = aCoefficients.size();
|
|
ArrayRef<int> bCoefficients = b->coefficients;
|
|
int bLength = bCoefficients.size();
|
|
int productLength = aLength + bLength - 1;
|
|
ArrayRef<int> product(new Array<int> (productLength));
|
|
for (int i = 0; i < aLength; i++) {
|
|
int aCoeff = aCoefficients[i];
|
|
for (int j = 0; j < bLength; j++) {
|
|
product[i + j] = GF256::addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));
|
|
}
|
|
}
|
|
|
|
return Ref<GF256Poly>(new GF256Poly(field, product));
|
|
}
|
|
|
|
Ref<GF256Poly> GF256Poly::multiply(int scalar) {
|
|
if (scalar == 0) {
|
|
return field.getZero();
|
|
}
|
|
if (scalar == 1) {
|
|
return Ref<GF256Poly>(this);
|
|
}
|
|
int size = coefficients.size();
|
|
ArrayRef<int> product(new Array<int> (size));
|
|
for (int i = 0; i < size; i++) {
|
|
product[i] = field.multiply(coefficients[i], scalar);
|
|
}
|
|
return Ref<GF256Poly>(new GF256Poly(field, product));
|
|
}
|
|
|
|
Ref<GF256Poly> GF256Poly::multiplyByMonomial(int degree, int coefficient) {
|
|
if (degree < 0) {
|
|
throw IllegalArgumentException("Degree must be non-negative");
|
|
}
|
|
if (coefficient == 0) {
|
|
return field.getZero();
|
|
}
|
|
int size = coefficients.size();
|
|
ArrayRef<int> product(new Array<int> (size + degree));
|
|
for (int i = 0; i < size; i++) {
|
|
product[i] = field.multiply(coefficients[i], coefficient);
|
|
}
|
|
return Ref<GF256Poly>(new GF256Poly(field, product));
|
|
}
|
|
|
|
const char *GF256Poly::description() const {
|
|
ostringstream result;
|
|
result << *this;
|
|
return result.str().c_str();
|
|
}
|
|
|
|
ostream& operator<<(ostream& out, const GF256Poly& p) {
|
|
GF256Poly &poly = const_cast<GF256Poly&>(p);
|
|
out << "Poly[" << poly.coefficients.size() << "]";
|
|
if (poly.coefficients.size() > 0) {
|
|
out << "(" << poly.coefficients[0];
|
|
for (unsigned i = 1; i < poly.coefficients.size(); i++) {
|
|
out << "," << poly.coefficients[i];
|
|
}
|
|
out << ")";
|
|
}
|
|
return out;
|
|
}
|
|
|
|
}
|