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