001: package JSci.maths.matrices;
002:
003: import JSci.GlobalSettings;
004: import JSci.maths.groups.AbelianGroup;
005: import JSci.maths.algebras.*;
006: import JSci.maths.fields.*;
007:
008: /**
009: * The RingMatrix class provides an object for encapsulating matrices over an arbitrary ring.
010: * @version 1.1
011: * @author Mark Hale
012: */
013: public class RingMatrix extends Matrix {
014: /**
015: * Array containing the elements of the matrix.
016: */
017: protected Ring.Member matrix[][];
018:
019: /**
020: * Constructs a matrix.
021: */
022: protected RingMatrix(final int rows, final int cols) {
023: super (rows, cols);
024: }
025:
026: /**
027: * Constructs a matrix by wrapping an array.
028: * @param array an assigned value
029: */
030: public RingMatrix(final Ring.Member array[][]) {
031: this (array.length, array[0].length);
032: matrix = array;
033: }
034:
035: /**
036: * Compares two matrices for equality.
037: * @param m a matrix
038: */
039: public boolean equals(Object m) {
040: if (m != null && (m instanceof RingMatrix)
041: && numRows == ((RingMatrix) m).rows()
042: && numCols == ((RingMatrix) m).columns()) {
043: final RingMatrix rm = (RingMatrix) m;
044: for (int j, i = 0; i < numRows; i++) {
045: for (j = 0; j < numCols; j++) {
046: if (!matrix[i][j].equals(rm.getElement(i, j)))
047: return false;
048: }
049: }
050: return true;
051: } else
052: return false;
053: }
054:
055: /**
056: * Returns a string representing this matrix.
057: */
058: public String toString() {
059: final StringBuffer buf = new StringBuffer(5 * numRows * numCols);
060: for (int j, i = 0; i < numRows; i++) {
061: for (j = 0; j < numCols; j++) {
062: buf.append(matrix[i][j].toString());
063: buf.append(' ');
064: }
065: buf.append('\n');
066: }
067: return buf.toString();
068: }
069:
070: /**
071: * Returns an element of the matrix.
072: * @param i row index of the element
073: * @param j column index of the element
074: * @exception MatrixDimensionException If attempting to access an invalid element.
075: */
076: public Ring.Member getElement(final int i, final int j) {
077: if (i >= 0 && i < numRows && j >= 0 && j < numCols)
078: return matrix[i][j];
079: else
080: throw new MatrixDimensionException(getInvalidElementMsg(i,
081: j));
082: }
083:
084: /**
085: * Sets the value of an element of the matrix.
086: * @param i row index of the element
087: * @param j column index of the element
088: * @param r a ring element
089: * @exception MatrixDimensionException If attempting to access an invalid element.
090: */
091: public void setElement(final int i, final int j, final Ring.Member r) {
092: if (i >= 0 && i < numRows && j >= 0 && j < numCols)
093: matrix[i][j] = r;
094: else
095: throw new MatrixDimensionException(getInvalidElementMsg(i,
096: j));
097: }
098:
099: public Object getSet() {
100: throw new RuntimeException(
101: "Not yet implemented: please file bug report");
102: }
103:
104: //============
105: // OPERATIONS
106: //============
107:
108: /**
109: * Returns the negative of this matrix.
110: */
111: public AbelianGroup.Member negate() {
112: final Ring.Member array[][] = new Ring.Member[numRows][numCols];
113: for (int j, i = 0; i < numRows; i++) {
114: array[i][0] = (Ring.Member) matrix[i][0].negate();
115: for (j = 1; j < numCols; j++)
116: array[i][j] = (Ring.Member) matrix[i][j].negate();
117: }
118: return new RingMatrix(array);
119: }
120:
121: // ADDITION
122:
123: /**
124: * Returns the addition of this matrix and another.
125: */
126: public final AbelianGroup.Member add(final AbelianGroup.Member m) {
127: if (m instanceof RingMatrix)
128: return add((RingMatrix) m);
129: else
130: throw new IllegalArgumentException(
131: "Member class not recognised by this method.");
132: }
133:
134: /**
135: * Returns the addition of this matrix and another.
136: * @param m a matrix
137: * @exception MatrixDimensionException If the matrices are different sizes.
138: */
139: public RingMatrix add(final RingMatrix m) {
140: if (numRows == m.numRows && numCols == m.numCols) {
141: final Ring.Member array[][] = new Ring.Member[numRows][numCols];
142: for (int j, i = 0; i < numRows; i++) {
143: array[i][0] = (Ring.Member) matrix[i][0].add(m
144: .getElement(i, 0));
145: for (j = 1; j < numCols; j++)
146: array[i][j] = (Ring.Member) matrix[i][j].add(m
147: .getElement(i, j));
148: }
149: return new RingMatrix(array);
150: } else
151: throw new MatrixDimensionException(
152: "Matrices are different sizes.");
153: }
154:
155: // SUBTRACTION
156:
157: /**
158: * Returns the subtraction of this matrix and another.
159: */
160: public final AbelianGroup.Member subtract(
161: final AbelianGroup.Member m) {
162: if (m instanceof RingMatrix)
163: return subtract((RingMatrix) m);
164: else
165: throw new IllegalArgumentException(
166: "Member class not recognised by this method.");
167: }
168:
169: /**
170: * Returns the subtraction of this matrix and another.
171: * @param m a matrix
172: * @exception MatrixDimensionException If the matrices are different sizes.
173: */
174: public RingMatrix subtract(final RingMatrix m) {
175: if (numRows == m.numRows && numCols == m.numCols) {
176: final Ring.Member array[][] = new Ring.Member[numRows][numCols];
177: for (int j, i = 0; i < numRows; i++) {
178: array[i][0] = (Ring.Member) matrix[i][0].subtract(m
179: .getElement(i, 0));
180: for (j = 1; j < numCols; j++)
181: array[i][j] = (Ring.Member) matrix[i][j].subtract(m
182: .getElement(i, j));
183: }
184: return new RingMatrix(array);
185: } else
186: throw new MatrixDimensionException(
187: "Matrices are different sizes.");
188: }
189:
190: // SCALAR MULTIPLICATION
191:
192: /**
193: * Returns the multiplication of this matrix by a scalar.
194: * @param r a ring element.
195: */
196: public Module.Member scalarMultiply(Ring.Member r) {
197: final Ring.Member array[][] = new Ring.Member[numRows][numCols];
198: for (int j, i = 0; i < numRows; i++) {
199: array[i][0] = r.multiply(matrix[i][0]);
200: for (j = 1; j < numCols; j++)
201: array[i][j] = r.multiply(matrix[i][j]);
202: }
203: return new RingMatrix(array);
204: }
205:
206: // SCALAR DIVISON
207:
208: /**
209: * Returns the division of this matrix by a scalar.
210: * @param x a field element.
211: */
212: public VectorSpace.Member scalarDivide(Field.Member x) {
213: final Ring.Member array[][] = new Ring.Member[numRows][numCols];
214: for (int j, i = 0; i < numRows; i++) {
215: array[i][0] = ((Field.Member) matrix[i][0]).divide(x);
216: for (j = 1; j < numCols; j++)
217: array[i][j] = ((Field.Member) matrix[i][j]).divide(x);
218: }
219: return new RingMatrix(array);
220: }
221:
222: // MATRIX MULTIPLICATION
223:
224: /**
225: * Returns the multiplication of this matrix and another.
226: */
227: public final Ring.Member multiply(final Ring.Member m) {
228: if (m instanceof RingMatrix)
229: return multiply((RingMatrix) m);
230: else
231: throw new IllegalArgumentException(
232: "Member class not recognised by this method.");
233: }
234:
235: /**
236: * Returns the multiplication of this matrix and another.
237: * @param m a matrix
238: * @exception MatrixDimensionException If the matrices are incompatible.
239: */
240: public RingMatrix multiply(final RingMatrix m) {
241: if (numCols == m.numRows) {
242: int n, k;
243: final Ring.Member array[][] = new Ring.Member[numRows][m.numCols];
244: for (int j = 0; j < numRows; j++) {
245: for (k = 0; k < m.numCols; k++) {
246: AbelianGroup.Member g = matrix[j][0].multiply(m
247: .getElement(0, k));
248: for (n = 1; n < numCols; n++)
249: g = g.add(matrix[j][n].multiply(m.getElement(n,
250: k)));
251: array[j][k] = (Ring.Member) g;
252: }
253: }
254: return new RingMatrix(array);
255: } else
256: throw new MatrixDimensionException("Incompatible matrices.");
257: }
258:
259: // DIRECT SUM
260:
261: /**
262: * Returns the direct sum of this matrix and another.
263: */
264: public RingMatrix directSum(final RingMatrix m) {
265: final Ring.Member array[][] = new Ring.Member[numRows
266: + m.numRows][numCols + m.numCols];
267: for (int j, i = 0; i < numRows; i++) {
268: for (j = 0; j < numCols; j++)
269: array[i][j] = matrix[i][j];
270: }
271: for (int j, i = 0; i < m.numRows; i++) {
272: for (j = 0; j < m.numCols; j++)
273: array[i + numRows][j + numCols] = m.getElement(i, j);
274: }
275: return new RingMatrix(array);
276: }
277:
278: // TENSOR PRODUCT
279:
280: /**
281: * Returns the tensor product of this matrix and another.
282: */
283: public RingMatrix tensor(final RingMatrix m) {
284: final Ring.Member array[][] = new Ring.Member[numRows
285: * m.numRows][numCols * m.numCols];
286: for (int i = 0; i < numRows; i++) {
287: for (int j = 0; j < numCols; j++) {
288: for (int k = 0; k < m.numRows; j++) {
289: for (int l = 0; l < m.numCols; l++)
290: array[i * m.numRows + k][j * m.numCols + l] = matrix[i][j]
291: .multiply(m.getElement(k, l));
292: }
293: }
294: }
295: return new RingMatrix(array);
296: }
297:
298: // TRANSPOSE
299:
300: /**
301: * Returns the transpose of this matrix.
302: * @return a matrix
303: */
304: public Matrix transpose() {
305: final Ring.Member array[][] = new Ring.Member[numCols][numRows];
306: for (int j, i = 0; i < numRows; i++) {
307: array[0][i] = matrix[i][0];
308: for (j = 1; j < numCols; j++)
309: array[j][i] = matrix[i][j];
310: }
311: return new RingMatrix(array);
312: }
313: }
|