New C# port from Suraj Supekar
[zxing.git] / csharp / common / reedsolomon / GF256Poly.cs
diff --git a/csharp/common/reedsolomon/GF256Poly.cs b/csharp/common/reedsolomon/GF256Poly.cs
new file mode 100755 (executable)
index 0000000..df5abb3
--- /dev/null
@@ -0,0 +1,328 @@
+/*\r
+* Copyright 2007 ZXing authors\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*      http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+using System;\r
+namespace com.google.zxing.common.reedsolomon\r
+{\r
+       \r
+       /// <summary> <p>Represents a polynomial whose coefficients are elements of GF(256).\r
+       /// Instances of this class are immutable.</p>\r
+       /// \r
+       /// <p>Much credit is due to William Rucklidge since portions of this code are an indirect\r
+       /// port of his C++ Reed-Solomon implementation.</p>\r
+       /// \r
+       /// </summary>\r
+       /// <author>  Sean Owen\r
+       /// </author>\r
+       /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
+       /// </author>\r
+       sealed class GF256Poly\r
+       {\r
+               internal int[] Coefficients\r
+               {\r
+                       get\r
+                       {\r
+                               return coefficients;\r
+                       }\r
+                       \r
+               }\r
+               /// <returns> degree of this polynomial\r
+               /// </returns>\r
+               internal int Degree\r
+               {\r
+                       get\r
+                       {\r
+                               return coefficients.Length - 1;\r
+                       }\r
+                       \r
+               }\r
+               /// <returns> true iff this polynomial is the monomial "0"\r
+               /// </returns>\r
+               internal bool Zero\r
+               {\r
+                       get\r
+                       {\r
+                               return coefficients[0] == 0;\r
+                       }\r
+                       \r
+               }\r
+               \r
+               //UPGRADE_NOTE: Final was removed from the declaration of 'field '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
+               private GF256 field;\r
+               //UPGRADE_NOTE: Final was removed from the declaration of 'coefficients '. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
+               private int[] coefficients;\r
+               \r
+               /// <param name="field">the {@link GF256} instance representing the field to use\r
+               /// to perform computations\r
+               /// </param>\r
+               /// <param name="coefficients">coefficients as ints representing elements of GF(256), arranged\r
+               /// from most significant (highest-power term) coefficient to least significant\r
+               /// </param>\r
+               /// <throws>  IllegalArgumentException if argument is null or empty, </throws>\r
+               /// <summary> or if leading coefficient is 0 and this is not a\r
+               /// constant polynomial (that is, it is not the monomial "0")\r
+               /// </summary>\r
+               internal GF256Poly(GF256 field, int[] coefficients)\r
+               {\r
+                       if (coefficients == null || coefficients.Length == 0)\r
+                       {\r
+                               throw new System.ArgumentException();\r
+                       }\r
+                       this.field = field;\r
+                       int coefficientsLength = coefficients.Length;\r
+                       if (coefficientsLength > 1 && coefficients[0] == 0)\r
+                       {\r
+                               // Leading term must be non-zero for anything except the constant polynomial "0"\r
+                               int firstNonZero = 1;\r
+                               while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0)\r
+                               {\r
+                                       firstNonZero++;\r
+                               }\r
+                               if (firstNonZero == coefficientsLength)\r
+                               {\r
+                                       this.coefficients = field.Zero.coefficients;\r
+                               }\r
+                               else\r
+                               {\r
+                                       this.coefficients = new int[coefficientsLength - firstNonZero];\r
+                                       Array.Copy(coefficients, firstNonZero, this.coefficients, 0, this.coefficients.Length);\r
+                               }\r
+                       }\r
+                       else\r
+                       {\r
+                               this.coefficients = coefficients;\r
+                       }\r
+               }\r
+               \r
+               /// <returns> coefficient of x^degree term in this polynomial\r
+               /// </returns>\r
+               internal int getCoefficient(int degree)\r
+               {\r
+                       return coefficients[coefficients.Length - 1 - degree];\r
+               }\r
+               \r
+               /// <returns> evaluation of this polynomial at a given point\r
+               /// </returns>\r
+               internal int evaluateAt(int a)\r
+               {\r
+                       if (a == 0)\r
+                       {\r
+                               // Just return the x^0 coefficient\r
+                               return getCoefficient(0);\r
+                       }\r
+                       int size = coefficients.Length;\r
+                       if (a == 1)\r
+                       {\r
+                               // Just the sum of the coefficients\r
+                               int result = 0;\r
+                               for (int i = 0; i < size; i++)\r
+                               {\r
+                                       result = GF256.addOrSubtract(result, coefficients[i]);\r
+                               }\r
+                               return result;\r
+                       }\r
+                       int result2 = coefficients[0];\r
+                       for (int i = 1; i < size; i++)\r
+                       {\r
+                               result2 = GF256.addOrSubtract(field.multiply(a, result2), coefficients[i]);\r
+                       }\r
+                       return result2;\r
+               }\r
+               \r
+               internal GF256Poly addOrSubtract(GF256Poly other)\r
+               {\r
+                       if (!field.Equals(other.field))\r
+                       {\r
+                               throw new System.ArgumentException("GF256Polys do not have same GF256 field");\r
+                       }\r
+                       if (Zero)\r
+                       {\r
+                               return other;\r
+                       }\r
+                       if (other.Zero)\r
+                       {\r
+                               return this;\r
+                       }\r
+                       \r
+                       int[] smallerCoefficients = this.coefficients;\r
+                       int[] largerCoefficients = other.coefficients;\r
+                       if (smallerCoefficients.Length > largerCoefficients.Length)\r
+                       {\r
+                               int[] temp = smallerCoefficients;\r
+                               smallerCoefficients = largerCoefficients;\r
+                               largerCoefficients = temp;\r
+                       }\r
+                       int[] sumDiff = new int[largerCoefficients.Length];\r
+                       int lengthDiff = largerCoefficients.Length - smallerCoefficients.Length;\r
+                       // Copy high-order terms only found in higher-degree polynomial's coefficients\r
+                       Array.Copy(largerCoefficients, 0, sumDiff, 0, lengthDiff);\r
+                       \r
+                       for (int i = lengthDiff; i < largerCoefficients.Length; i++)\r
+                       {\r
+                               sumDiff[i] = GF256.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);\r
+                       }\r
+                       \r
+                       return new GF256Poly(field, sumDiff);\r
+               }\r
+               \r
+               internal GF256Poly multiply(GF256Poly other)\r
+               {\r
+                       if (!field.Equals(other.field))\r
+                       {\r
+                               throw new System.ArgumentException("GF256Polys do not have same GF256 field");\r
+                       }\r
+                       if (Zero || other.Zero)\r
+                       {\r
+                               return field.Zero;\r
+                       }\r
+                       int[] aCoefficients = this.coefficients;\r
+                       int aLength = aCoefficients.Length;\r
+                       int[] bCoefficients = other.coefficients;\r
+                       int bLength = bCoefficients.Length;\r
+                       int[] product = new int[aLength + bLength - 1];\r
+                       for (int i = 0; i < aLength; i++)\r
+                       {\r
+                               int aCoeff = aCoefficients[i];\r
+                               for (int j = 0; j < bLength; j++)\r
+                               {\r
+                                       product[i + j] = GF256.addOrSubtract(product[i + j], field.multiply(aCoeff, bCoefficients[j]));\r
+                               }\r
+                       }\r
+                       return new GF256Poly(field, product);\r
+               }\r
+               \r
+               internal GF256Poly multiply(int scalar)\r
+               {\r
+                       if (scalar == 0)\r
+                       {\r
+                               return field.Zero;\r
+                       }\r
+                       if (scalar == 1)\r
+                       {\r
+                               return this;\r
+                       }\r
+                       int size = coefficients.Length;\r
+                       int[] product = new int[size];\r
+                       for (int i = 0; i < size; i++)\r
+                       {\r
+                               product[i] = field.multiply(coefficients[i], scalar);\r
+                       }\r
+                       return new GF256Poly(field, product);\r
+               }\r
+               \r
+               internal GF256Poly multiplyByMonomial(int degree, int coefficient)\r
+               {\r
+                       if (degree < 0)\r
+                       {\r
+                               throw new System.ArgumentException();\r
+                       }\r
+                       if (coefficient == 0)\r
+                       {\r
+                               return field.Zero;\r
+                       }\r
+                       int size = coefficients.Length;\r
+                       int[] product = new int[size + degree];\r
+                       for (int i = 0; i < size; i++)\r
+                       {\r
+                               product[i] = field.multiply(coefficients[i], coefficient);\r
+                       }\r
+                       return new GF256Poly(field, product);\r
+               }\r
+               \r
+               internal GF256Poly[] divide(GF256Poly other)\r
+               {\r
+                       if (!field.Equals(other.field))\r
+                       {\r
+                               throw new System.ArgumentException("GF256Polys do not have same GF256 field");\r
+                       }\r
+                       if (other.Zero)\r
+                       {\r
+                               throw new System.ArgumentException("Divide by 0");\r
+                       }\r
+                       \r
+                       GF256Poly quotient = field.Zero;\r
+                       GF256Poly remainder = this;\r
+                       \r
+                       int denominatorLeadingTerm = other.getCoefficient(other.Degree);\r
+                       int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);\r
+                       \r
+                       while (remainder.Degree >= other.Degree && !remainder.Zero)\r
+                       {\r
+                               int degreeDifference = remainder.Degree - other.Degree;\r
+                               int scale = field.multiply(remainder.getCoefficient(remainder.Degree), inverseDenominatorLeadingTerm);\r
+                               GF256Poly term = other.multiplyByMonomial(degreeDifference, scale);\r
+                               GF256Poly iterationQuotient = field.buildMonomial(degreeDifference, scale);\r
+                               quotient = quotient.addOrSubtract(iterationQuotient);\r
+                               remainder = remainder.addOrSubtract(term);\r
+                       }\r
+                       \r
+                       return new GF256Poly[]{quotient, remainder};\r
+               }\r
+               \r
+               public override System.String ToString()\r
+               {\r
+                       System.Text.StringBuilder result = new System.Text.StringBuilder(8 * Degree);\r
+                       for (int degree = Degree; degree >= 0; degree--)\r
+                       {\r
+                               int coefficient = getCoefficient(degree);\r
+                               if (coefficient != 0)\r
+                               {\r
+                                       if (coefficient < 0)\r
+                                       {\r
+                                               result.Append(" - ");\r
+                                               coefficient = - coefficient;\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (result.Length > 0)\r
+                                               {\r
+                                                       result.Append(" + ");\r
+                                               }\r
+                                       }\r
+                                       if (degree == 0 || coefficient != 1)\r
+                                       {\r
+                                               int alphaPower = field.log(coefficient);\r
+                                               if (alphaPower == 0)\r
+                                               {\r
+                                                       result.Append('1');\r
+                                               }\r
+                                               else if (alphaPower == 1)\r
+                                               {\r
+                                                       result.Append('a');\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       result.Append("a^");\r
+                                                       result.Append(alphaPower);\r
+                                               }\r
+                                       }\r
+                                       if (degree != 0)\r
+                                       {\r
+                                               if (degree == 1)\r
+                                               {\r
+                                                       result.Append('x');\r
+                                               }\r
+                                               else\r
+                                               {\r
+                                                       result.Append("x^");\r
+                                                       result.Append(degree);\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       return result.ToString();\r
+               }\r
+       }\r
+}
\ No newline at end of file