5 * Created by Christian Brunschen on 05/05/2008.
6 * Copyright 2008 Google UK. All rights reserved.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 #include <zxing/common/reedsolomon/GF256Poly.h>
24 #include <zxing/common/reedsolomon/GF256.h>
25 #include <zxing/common/IllegalArgumentException.h>
30 void GF256Poly::fixCoefficients() {
31 int coefficientsLength = coefficients.size();
32 if (coefficientsLength > 1 && coefficients[0] == 0) {
33 // Leading term must be non-zero for anything except
34 // the constant polynomial "0"
36 while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) {
39 if (firstNonZero == coefficientsLength) {
40 coefficientsLength = field.getZero()->coefficients.size();
41 coefficients.reset(new Array<int> (coefficientsLength));
42 *coefficients = *(field.getZero()->coefficients);
44 ArrayRef<int> c(coefficients);
45 coefficientsLength -= firstNonZero;
46 coefficients.reset(new Array<int> (coefficientsLength));
47 for (int i = 0; i < coefficientsLength; i++) {
48 coefficients[i] = c[i + firstNonZero];
54 GF256Poly::GF256Poly(GF256 &f, ArrayRef<int> c) :
55 Counted(), field(f), coefficients(c) {
59 GF256Poly::~GF256Poly() {
63 int GF256Poly::getDegree() {
64 return coefficients.size() - 1;
67 bool GF256Poly::isZero() {
68 return coefficients[0] == 0;
71 int GF256Poly::getCoefficient(int degree) {
72 return coefficients[coefficients.size() - 1 - degree];
75 int GF256Poly::evaluateAt(int a) {
77 return getCoefficient(0);
79 int size = coefficients.size();
81 // Just the sum of the coefficients
83 for (int i = 0; i < size; i++) {
84 result = GF256::addOrSubtract(result, coefficients[i]);
88 int result = coefficients[0];
89 for (int i = 1; i < size; i++) {
90 result = GF256::addOrSubtract(field.multiply(a, result), coefficients[i]);
95 Ref<GF256Poly> GF256Poly::addOrSubtract(Ref<GF256Poly> b) {
96 if (&field != &b->field) {
97 throw IllegalArgumentException("Fields must be the same");
103 return Ref<GF256Poly>(this);
106 ArrayRef<int> largerCoefficients = coefficients;
107 ArrayRef<int> smallerCoefficients = b->coefficients;
108 if (smallerCoefficients.size() > largerCoefficients.size()) {
109 ArrayRef<int> tmp(smallerCoefficients);
110 smallerCoefficients = largerCoefficients;
111 largerCoefficients = tmp;
114 ArrayRef<int> sumDiff(new Array<int> (largerCoefficients.size()));
116 unsigned lengthDiff = largerCoefficients.size() - smallerCoefficients.size();
117 for (unsigned i = 0; i < lengthDiff; i++) {
118 sumDiff[i] = largerCoefficients[i];
120 for (unsigned i = lengthDiff; i < largerCoefficients.size(); i++) {
121 sumDiff[i] = GF256::addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
123 return Ref<GF256Poly>(new GF256Poly(field, sumDiff));
126 Ref<GF256Poly> GF256Poly::multiply(Ref<GF256Poly> b) {
127 if (&field != &b->field) {
128 throw IllegalArgumentException("Fields must be the same");
130 if (isZero() || b->isZero()) {
131 return field.getZero();
133 ArrayRef<int> aCoefficients = coefficients;
134 int aLength = aCoefficients.size();
135 ArrayRef<int> bCoefficients = b->coefficients;
136 int bLength = bCoefficients.size();
137 int productLength = aLength + bLength - 1;
138 ArrayRef<int> product(new Array<int> (productLength));
139 for (int i = 0; i < aLength; i++) {
140 int aCoeff = aCoefficients[i];
141 for (int j = 0; j < bLength; j++) {
142 product[i + j] = GF256::addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));
146 return Ref<GF256Poly>(new GF256Poly(field, product));
149 Ref<GF256Poly> GF256Poly::multiply(int scalar) {
151 return field.getZero();
154 return Ref<GF256Poly>(this);
156 int size = coefficients.size();
157 ArrayRef<int> product(new Array<int> (size));
158 for (int i = 0; i < size; i++) {
159 product[i] = field.multiply(coefficients[i], scalar);
161 return Ref<GF256Poly>(new GF256Poly(field, product));
164 Ref<GF256Poly> GF256Poly::multiplyByMonomial(int degree, int coefficient) {
166 throw IllegalArgumentException("Degree must be non-negative");
168 if (coefficient == 0) {
169 return field.getZero();
171 int size = coefficients.size();
172 ArrayRef<int> product(new Array<int> (size + degree));
173 for (int i = 0; i < size; i++) {
174 product[i] = field.multiply(coefficients[i], coefficient);
176 return Ref<GF256Poly>(new GF256Poly(field, product));
179 const char *GF256Poly::description() const {
180 ostringstream result;
182 return result.str().c_str();
185 ostream& operator<<(ostream& out, const GF256Poly& p) {
186 GF256Poly &poly = const_cast<GF256Poly&>(p);
187 out << "Poly[" << poly.coefficients.size() << "]";
188 if (poly.coefficients.size() > 0) {
189 out << "(" << poly.coefficients[0];
190 for (unsigned i = 1; i < poly.coefficients.size(); i++) {
191 out << "," << poly.coefficients[i];