001: /* AUTO-GENERATED */
002: package JSci.maths.matrices;
003:
004: import JSci.maths.ExtraMath;
005: import JSci.maths.Mapping;
006: import JSci.maths.DimensionException;
007: import JSci.maths.vectors.AbstractDoubleVector;
008: import JSci.maths.vectors.DoubleVector;
009: import JSci.maths.groups.AbelianGroup;
010: import JSci.maths.algebras.*;
011: import JSci.maths.fields.*;
012:
013: /**
014: * The DoubleMatrix class provides an object for encapsulating double matrices.
015: * @version 2.2
016: * @author Mark Hale
017: */
018: public class DoubleMatrix extends AbstractDoubleMatrix {
019: /**
020: * Array containing the elements of the matrix.
021: */
022: protected final double matrix[][];
023:
024: /**
025: * Constructs a matrix by wrapping an array.
026: * @param array an assigned value
027: */
028: public DoubleMatrix(final double array[][]) {
029: super (array.length, array[0].length);
030: matrix = array;
031: }
032:
033: /**
034: * Constructs an empty matrix.
035: */
036: public DoubleMatrix(final int rows, final int cols) {
037: this (new double[rows][cols]);
038: }
039:
040: /**
041: * Constructs a matrix from an array of vectors (columns).
042: * @param array an assigned value
043: */
044: public DoubleMatrix(final AbstractDoubleVector array[]) {
045: this (array[0].dimension(), array.length);
046: for (int i = 0; i < numRows; i++) {
047: for (int j = 0; j < numCols; j++)
048: matrix[i][j] = array[j].getComponent(i);
049: }
050: }
051:
052: /**
053: * Compares two ${nativeTyp} matrices for equality.
054: * @param m a double matrix
055: */
056: public boolean equals(AbstractDoubleMatrix m, double tol) {
057: if (m != null && numRows == m.rows() && numCols == m.columns()) {
058: double sumSqr = 0;
059: for (int i = 0; i < numRows; i++) {
060: for (int j = 0; j < numCols; j++) {
061: double delta = matrix[i][j] - m.getElement(i, j);
062: sumSqr += delta * delta;
063: }
064: }
065: return (sumSqr <= tol * tol);
066: } else {
067: return false;
068: }
069: }
070:
071: /**
072: * Returns a string representing this matrix.
073: */
074: public String toString() {
075: final StringBuffer buf = new StringBuffer(5 * numRows * numCols);
076: for (int i = 0; i < numRows; i++) {
077: for (int j = 0; j < numCols; j++) {
078: buf.append(matrix[i][j]);
079: buf.append(' ');
080: }
081: buf.append('\n');
082: }
083: return buf.toString();
084: }
085:
086: /**
087: * Converts this matrix to an integer matrix.
088: * @return an integer matrix
089: */
090: public AbstractIntegerMatrix toIntegerMatrix() {
091: final int ans[][] = new int[numRows][numCols];
092: for (int i = 0; i < numRows; i++) {
093: for (int j = 0; j < numCols; j++)
094: ans[i][j] = Math.round((float) matrix[i][j]);
095: }
096: return new IntegerMatrix(ans);
097: }
098:
099: /**
100: * Converts this matrix to a complex matrix.
101: * @return a complex matrix
102: */
103: public AbstractComplexMatrix toComplexMatrix() {
104: ComplexMatrix cm = new ComplexMatrix(numRows, numCols);
105: for (int i = 0; i < numRows; i++) {
106: for (int j = 0; j < numCols; j++)
107: cm.setElement(i, j, matrix[i][j], 0.0);
108: }
109: return cm;
110: }
111:
112: /**
113: * Returns an element of the matrix.
114: * @param i row index of the element
115: * @param j column index of the element
116: * @exception MatrixDimensionException If attempting to access an invalid element.
117: */
118: public double getElement(int i, int j) {
119: if (i >= 0 && i < numRows && j >= 0 && j < numCols)
120: return matrix[i][j];
121: else
122: throw new MatrixDimensionException(getInvalidElementMsg(i,
123: j));
124: }
125:
126: /**
127: * Sets the value of an element of the matrix.
128: * Should only be used to initialise this matrix.
129: * @param i row index of the element
130: * @param j column index of the element
131: * @param x a number
132: * @exception MatrixDimensionException If attempting to access an invalid element.
133: */
134: public void setElement(int i, int j, double x) {
135: if (i >= 0 && i < numRows && j >= 0 && j < numCols)
136: matrix[i][j] = x;
137: else
138: throw new MatrixDimensionException(getInvalidElementMsg(i,
139: j));
140: }
141:
142: /**
143: * Returns the l<sup><img border=0 alt="infinity" src="doc-files/infinity.gif"></sup>-norm.
144: * @author Taber Smith
145: */
146: public double infNorm() {
147: double result = 0, tmpResult;
148: for (int i = 0; i < numRows; i++) {
149: tmpResult = 0;
150: for (int j = 0; j < numCols; j++)
151: tmpResult += Math.abs(matrix[i][j]);
152: if (tmpResult > result)
153: result = tmpResult;
154: }
155: return result;
156: }
157:
158: /**
159: * Returns the Frobenius or Hilbert-Schmidt (l<sup>2</sup>) norm.
160: * @jsci.planetmath FrobeniusMatrixNorm
161: */
162: public double frobeniusNorm() {
163: double result = 0.0;
164: for (int j, i = 0; i < numRows; i++) {
165: for (j = 0; j < numCols; j++)
166: result = ExtraMath.hypot(result, matrix[i][j]);
167: }
168: return result;
169: }
170:
171: //============
172: // OPERATIONS
173: //============
174:
175: /**
176: * Returns the negative of this matrix.
177: */
178: public AbelianGroup.Member negate() {
179: final double array[][] = new double[numRows][numCols];
180: for (int i = 0; i < numRows; i++) {
181: array[i][0] = -matrix[i][0];
182: for (int j = 1; j < numCols; j++)
183: array[i][j] = -matrix[i][j];
184: }
185: return new DoubleMatrix(array);
186: }
187:
188: // ADDITION
189:
190: /**
191: * Returns the addition of this matrix and another.
192: * @param m a double matrix
193: * @exception MatrixDimensionException If the matrices are different sizes.
194: */
195: public AbstractDoubleMatrix add(final AbstractDoubleMatrix m) {
196: if (numRows == m.rows() && numCols == m.columns()) {
197: final double array[][] = new double[numRows][numCols];
198: for (int i = 0; i < numRows; i++) {
199: array[i][0] = matrix[i][0] + m.getElement(i, 0);
200: for (int j = 1; j < numCols; j++)
201: array[i][j] = matrix[i][j] + m.getElement(i, j);
202: }
203: return new DoubleMatrix(array);
204: } else {
205: throw new MatrixDimensionException(
206: "Matrices are different sizes.");
207: }
208: }
209:
210: // SUBTRACTION
211:
212: /**
213: * Returns the subtraction of this matrix by another.
214: * @param m a double matrix
215: * @exception MatrixDimensionException If the matrices are different sizes.
216: */
217: public AbstractDoubleMatrix subtract(final AbstractDoubleMatrix m) {
218: if (numRows == m.rows() && numCols == m.columns()) {
219: final double array[][] = new double[numRows][numCols];
220: for (int i = 0; i < numRows; i++) {
221: array[i][0] = matrix[i][0] - m.getElement(i, 0);
222: for (int j = 1; j < numCols; j++)
223: array[i][j] = matrix[i][j] - m.getElement(i, j);
224: }
225: return new DoubleMatrix(array);
226: } else {
227: throw new MatrixDimensionException(
228: "Matrices are different sizes.");
229: }
230: }
231:
232: // SCALAR MULTIPLICATION
233:
234: /**
235: * Returns the multiplication of this matrix by a scalar.
236: * @param x a double.
237: * @return a double matrix.
238: */
239: public AbstractDoubleMatrix scalarMultiply(final double x) {
240: final double array[][] = new double[numRows][numCols];
241: for (int i = 0; i < numRows; i++) {
242: array[i][0] = x * matrix[i][0];
243: for (int j = 1; j < numCols; j++)
244: array[i][j] = x * matrix[i][j];
245: }
246: return new DoubleMatrix(array);
247: }
248:
249: // SCALAR DIVISON
250:
251: /**
252: * Returns the division of this matrix by a scalar.
253: * @param x a double.
254: * @return a double matrix.
255: */
256: public AbstractDoubleMatrix scalarDivide(final double x) {
257: final double array[][] = new double[numRows][numCols];
258: for (int i = 0; i < numRows; i++) {
259: array[i][0] = matrix[i][0] / x;
260: for (int j = 1; j < numCols; j++)
261: array[i][j] = matrix[i][j] / x;
262: }
263: return new DoubleMatrix(array);
264: }
265:
266: // SCALAR PRODUCT
267:
268: /**
269: * Returns the scalar product of this matrix and another.
270: * @param m a double matrix.
271: * @exception MatrixDimensionException If the matrices are different sizes.
272: */
273: public double scalarProduct(final AbstractDoubleMatrix m) {
274: if (m instanceof DoubleMatrix)
275: return scalarProduct((DoubleMatrix) m);
276:
277: if (numRows == m.rows() && numCols == m.columns()) {
278: double ans = 0;
279: for (int i = 0; i < numRows; i++) {
280: ans += matrix[i][0] * m.getElement(i, 0);
281: for (int j = 1; j < numCols; j++)
282: ans += matrix[i][j] * m.getElement(i, j);
283: }
284: return ans;
285: } else {
286: throw new MatrixDimensionException(
287: "Matrices are different sizes.");
288: }
289: }
290:
291: public double scalarProduct(final DoubleMatrix m) {
292: if (numRows == m.numRows && numCols == m.numCols) {
293: double ans = 0;
294: for (int i = 0; i < numRows; i++) {
295: ans += matrix[i][0] * m.matrix[i][0];
296: for (int j = 1; j < numCols; j++)
297: ans += matrix[i][j] * m.matrix[i][j];
298: }
299: return ans;
300: } else
301: throw new MatrixDimensionException(
302: "Matrices are different sizes.");
303: }
304:
305: // MATRIX MULTIPLICATION
306:
307: /**
308: * Returns the multiplication of a vector by this matrix.
309: * @param v a double vector.
310: * @exception DimensionException If the matrix and vector are incompatible.
311: */
312: public AbstractDoubleVector multiply(final AbstractDoubleVector v) {
313: if (numCols == v.dimension()) {
314: final double array[] = new double[numRows];
315: for (int i = 0; i < numRows; i++) {
316: array[i] = matrix[i][0] * v.getComponent(0);
317: for (int j = 1; j < numCols; j++)
318: array[i] += matrix[i][j] * v.getComponent(j);
319: }
320: return new DoubleVector(array);
321: } else {
322: throw new DimensionException(
323: "Matrix and vector are incompatible.");
324: }
325: }
326:
327: /**
328: * Returns the multiplication of this matrix and another.
329: * @param m a double matrix
330: * @return a AbstractDoubleMatrix or a AbstractDoubleSquareMatrix as appropriate
331: * @exception MatrixDimensionException If the matrices are incompatible.
332: */
333: public AbstractDoubleMatrix multiply(final AbstractDoubleMatrix m) {
334: if (m instanceof DoubleMatrix)
335: return multiply((DoubleMatrix) m);
336:
337: if (numCols == m.rows()) {
338: final int mColumns = m.columns();
339: final double array[][] = new double[numRows][mColumns];
340: for (int j = 0; j < numRows; j++) {
341: for (int k = 0; k < mColumns; k++) {
342: array[j][k] = matrix[j][0] * m.getElement(0, k);
343: for (int n = 1; n < numCols; n++)
344: array[j][k] += matrix[j][n]
345: * m.getElement(n, k);
346: }
347: }
348: if (numRows == mColumns)
349: return new DoubleSquareMatrix(array);
350: else
351: return new DoubleMatrix(array);
352: } else {
353: throw new MatrixDimensionException("Incompatible matrices.");
354: }
355: }
356:
357: public AbstractDoubleMatrix multiply(final DoubleMatrix m) {
358: if (numCols == m.numRows) {
359: final double array[][] = new double[numRows][m.numCols];
360: for (int j = 0; j < numRows; j++) {
361: for (int k = 0; k < m.numCols; k++) {
362: array[j][k] = matrix[j][0] * m.matrix[0][k];
363: for (int n = 1; n < numCols; n++)
364: array[j][k] += matrix[j][n] * m.matrix[n][k];
365: }
366: }
367: if (numRows == m.numCols)
368: return new DoubleSquareMatrix(array);
369: else
370: return new DoubleMatrix(array);
371: } else
372: throw new MatrixDimensionException("Incompatible matrices.");
373: }
374:
375: // DIRECT SUM
376:
377: /**
378: * Returns the direct sum of this matrix and another.
379: */
380: public AbstractDoubleMatrix directSum(final AbstractDoubleMatrix m) {
381: final double array[][] = new double[numRows + m.numRows][numCols
382: + m.numCols];
383: for (int i = 0; i < numRows; i++) {
384: for (int j = 0; j < numCols; j++)
385: array[i][j] = matrix[i][j];
386: }
387: for (int i = 0; i < m.numRows; i++) {
388: for (int j = 0; j < m.numCols; j++)
389: array[i + numRows][j + numCols] = m.getElement(i, j);
390: }
391: return new DoubleMatrix(array);
392: }
393:
394: // TENSOR PRODUCT
395:
396: /**
397: * Returns the tensor product of this matrix and another.
398: */
399: public AbstractDoubleMatrix tensor(final AbstractDoubleMatrix m) {
400: final double array[][] = new double[numRows * m.numRows][numCols
401: * m.numCols];
402: for (int i = 0; i < numRows; i++) {
403: for (int j = 0; j < numCols; j++) {
404: for (int k = 0; k < m.numRows; j++) {
405: for (int l = 0; l < m.numCols; l++)
406: array[i * m.numRows + k][j * m.numCols + l] = matrix[i][j]
407: * m.getElement(k, l);
408: }
409: }
410: }
411: return new DoubleMatrix(array);
412: }
413:
414: // TRANSPOSE
415:
416: /**
417: * Returns the transpose of this matrix.
418: * @return a double matrix
419: */
420: public Matrix transpose() {
421: final double array[][] = new double[numCols][numRows];
422: for (int i = 0; i < numRows; i++) {
423: array[0][i] = matrix[i][0];
424: for (int j = 1; j < numCols; j++)
425: array[j][i] = matrix[i][j];
426: }
427: return new DoubleMatrix(array);
428: }
429:
430: // MAP ELEMENTS
431:
432: /**
433: * Applies a function on all the matrix elements.
434: * @param f a user-defined function
435: * @return a double matrix
436: */
437: public AbstractDoubleMatrix mapElements(final Mapping f) {
438: final double array[][] = new double[numRows][numCols];
439: for (int i = 0; i < numRows; i++) {
440: array[i][0] = f.map(matrix[i][0]);
441: for (int j = 1; j < numCols; j++)
442: array[i][j] = f.map(matrix[i][j]);
443: }
444: return new DoubleMatrix(array);
445: }
446: }
|