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 "GF256Poly.h"
25 #include "../IllegalArgumentException.h"
27 using namespace common;
29 namespace reedsolomon {
31 void GF256Poly::fixCoefficients() {
32 int coefficientsLength = coefficients.size();
33 if (coefficientsLength > 1 && coefficients[0] == 0) {
34 // Leading term must be non-zero for anything except
35 // the constant polynomial "0"
37 while (firstNonZero < coefficientsLength &&
38 coefficients[firstNonZero] == 0) {
41 if (firstNonZero == coefficientsLength) {
42 coefficientsLength = field.getZero()->coefficients.size();
43 coefficients.reset(new Array<int>(coefficientsLength));
44 *coefficients = *(field.getZero()->coefficients);
46 ArrayRef<int>c(coefficients);
47 coefficientsLength -= firstNonZero;
48 coefficients.reset(new Array<int>(coefficientsLength));
49 for (int i = 0; i < coefficientsLength; i++) {
50 coefficients[i] = c[i + firstNonZero];
56 GF256Poly::GF256Poly(GF256 &f, ArrayRef<int> c) :
57 Counted(), field(f), coefficients(c) {
59 cout << "instantiating GF256Poly @ " << this << " with Array " << c.array_ << "(" << c.array_->count_ << "), size " << c.size() << ", ";
60 cout << "coefficients size = " << coefficients.size() << "\n";
65 GF256Poly::~GF256Poly() {
67 cout << "destroying GF256Poly @ " << this << "\n";
71 int GF256Poly::getDegree() {
72 return coefficients.size() - 1;
75 bool GF256Poly::isZero() {
76 return coefficients[0] == 0;
79 int GF256Poly::getCoefficient(int degree) {
80 return coefficients[coefficients.size() - 1 - degree];
83 int GF256Poly::evaluateAt(int a) {
85 return getCoefficient(0);
87 int size = coefficients.size();
89 // Just the sum of the coefficients
91 for (int i = 0; i < size; i++) {
92 result = GF256::addOrSubtract(result, coefficients[i]);
96 int result = coefficients[0];
97 for (int i = 1; i < size; i++) {
98 result = GF256::addOrSubtract(field.multiply(a, result),
104 GF256Poly *GF256Poly::addOrSubtract(GF256Poly *b) {
105 if (&field != &b->field) {
106 throw new IllegalArgumentException("Fields must be the same");
115 ArrayRef<int> largerCoefficients = coefficients;
116 ArrayRef<int> smallerCoefficients = b->coefficients;
117 if (smallerCoefficients.size() > largerCoefficients.size()) {
118 ArrayRef<int> tmp(smallerCoefficients);
119 smallerCoefficients = largerCoefficients;
120 largerCoefficients = tmp;
123 ArrayRef<int> sumDiff(new Array<int>(largerCoefficients.size()));
125 unsigned lengthDiff = largerCoefficients.size() - smallerCoefficients.size();
126 for (unsigned i = 0; i < lengthDiff; i++) {
127 sumDiff[i] = largerCoefficients[i];
129 for (unsigned i = lengthDiff; i < largerCoefficients.size(); i++) {
130 sumDiff[i] = GF256::addOrSubtract(smallerCoefficients[i - lengthDiff],
131 largerCoefficients[i]);
133 return new GF256Poly(field, sumDiff);
136 GF256Poly *GF256Poly::multiply(GF256Poly *b) {
137 if (&field != &b->field) {
138 throw new IllegalArgumentException("Fields must be the same");
140 if (isZero() || b->isZero()) {
141 return field.getZero();
143 ArrayRef<int> aCoefficients = coefficients;
144 int aLength = aCoefficients.size();
145 ArrayRef<int> bCoefficients = b->coefficients;
146 int bLength = bCoefficients.size();
147 int productLength = aLength + bLength - 1;
148 ArrayRef<int> product(new Array<int>(productLength));
149 for (int i = 0; i < aLength; i++) {
150 int aCoeff = aCoefficients[i];
151 for (int j = 0; j < bLength; j++) {
153 GF256::addOrSubtract(product[i + j],
154 field.multiply(aCoeff, bCoefficients[j]));
158 return new GF256Poly(field, product);
161 GF256Poly *GF256Poly::multiply(int scalar) {
163 return field.getZero();
168 int size = coefficients.size();
169 ArrayRef<int> product(new Array<int>(size));
170 for (int i = 0; i < size; i++) {
171 product[i] = field.multiply(coefficients[i], scalar);
173 return new GF256Poly(field, product);
176 GF256Poly *GF256Poly::multiplyByMonomial(int degree,
179 throw new IllegalArgumentException("Degree must be non-negative");
181 if (coefficient == 0) {
182 return field.getZero();
184 int size = coefficients.size();
185 ArrayRef<int> product (new Array<int>(size + degree));
186 for (int i = 0; i < size; i++) {
187 product[i] = field.multiply(coefficients[i], coefficient);
189 return new GF256Poly(field, product);
192 const char *GF256Poly::description() const {
193 ostringstream result;
195 return result.str().c_str();
199 ostream& operator<<(ostream& out, const GF256Poly& p)
201 GF256Poly &poly = const_cast<GF256Poly&>(p);
202 out << "Poly[" << poly.coefficients.size() << "]";
203 if (poly.coefficients.size() > 0) {
204 out << "(" << poly.coefficients[0];
205 for (unsigned i = 1; i < poly.coefficients.size(); i++) {
206 out << "," << poly.coefficients[i];