001: /* AUTO-GENERATED */
002: package JSci.maths.matrices;
003:
004: import JSci.GlobalSettings;
005: import JSci.maths.MathDouble;
006: import JSci.maths.MathInteger;
007: import JSci.maths.Complex;
008: import JSci.maths.ComplexMapping;
009: import JSci.maths.DimensionException;
010: import JSci.maths.vectors.AbstractComplexVector;
011: import JSci.maths.vectors.ComplexVector;
012: import JSci.maths.groups.AbelianGroup;
013: import JSci.maths.algebras.*;
014: import JSci.maths.fields.*;
015:
016: /**
017: * The AbstractComplexMatrix class provides an object for encapsulating matrices containing complex numbers.
018: * @version 2.2
019: * @author Mark Hale
020: */
021: public abstract class AbstractComplexMatrix extends Matrix {
022: /**
023: * Constructs a matrix.
024: */
025: protected AbstractComplexMatrix(final int rows, final int cols) {
026: super (rows, cols);
027: }
028:
029: /**
030: * Compares two complex matrices for equality.
031: * @param obj a complex matrix
032: */
033: public final boolean equals(Object obj) {
034: if (obj instanceof AbstractComplexMatrix) {
035: return equals((AbstractComplexMatrix) obj);
036: } else {
037: return false;
038: }
039: }
040:
041: /**
042: * Compares two complex matrices for equality.
043: * Two matrices are considered to be equal if the Frobenius norm of their difference is within the zero tolerance.
044: * @param m a complex matrix
045: */
046: public final boolean equals(AbstractComplexMatrix m) {
047: return equals(m, GlobalSettings.ZERO_TOL);
048: }
049:
050: public boolean equals(AbstractComplexMatrix m, double tol) {
051: if (m != null && numRows == m.rows() && numCols == m.columns()) {
052: double sumSqr = 0.0;
053: for (int i = 0; i < numRows; i++) {
054: for (int j = 0; j < numCols; j++) {
055: double deltaRe = getRealElement(i, j)
056: - m.getRealElement(i, j);
057: double deltaIm = getImagElement(i, j)
058: - m.getImagElement(i, j);
059: sumSqr += deltaRe * deltaRe + deltaIm * deltaIm;
060: }
061: }
062: return (sumSqr <= tol * tol);
063: } else {
064: return false;
065: }
066: }
067:
068: /**
069: * Returns a string representing this matrix.
070: */
071: public String toString() {
072: final StringBuffer buf = new StringBuffer(5 * numRows * numCols);
073: for (int i = 0; i < numRows; i++) {
074: for (int j = 0; j < numCols; j++) {
075: buf.append(getElement(i, j));
076: buf.append(' ');
077: }
078: buf.append('\n');
079: }
080: return buf.toString();
081: }
082:
083: /**
084: * Returns a hashcode for this matrix.
085: */
086: public int hashCode() {
087: return (int) Math.exp(infNorm());
088: }
089:
090: /**
091: * Returns the real part of this complex matrix.
092: * @return a double matrix
093: */
094: public AbstractDoubleMatrix real() {
095: final double ans[][] = new double[numRows][numCols];
096: for (int i = 0; i < numRows; i++) {
097: for (int j = 0; j < numCols; j++)
098: ans[i][j] = getElement(i, j).real();
099: }
100: return new DoubleMatrix(ans);
101: }
102:
103: /**
104: * Returns the imaginary part of this complex matrix.
105: * @return a double matrix
106: */
107: public AbstractDoubleMatrix imag() {
108: final double ans[][] = new double[numRows][numCols];
109: for (int i = 0; i < numRows; i++) {
110: for (int j = 0; j < numCols; j++)
111: ans[i][j] = getElement(i, j).imag();
112: }
113: return new DoubleMatrix(ans);
114: }
115:
116: /**
117: * Returns an element of the matrix.
118: * @param i row index of the element
119: * @param j column index of the element
120: * @exception MatrixDimensionException If attempting to access an invalid element.
121: */
122: public abstract Complex getElement(final int i, final int j);
123:
124: /**
125: * Returns the real part of an element of the matrix.
126: * @param i row index of the element
127: * @param j column index of the element
128: * @exception MatrixDimensionException If attempting to access an invalid element.
129: */
130: public abstract double getRealElement(final int i, final int j);
131:
132: /**
133: * Returns the imag part of an element of the matrix.
134: * @param i row index of the element
135: * @param j column index of the element
136: * @exception MatrixDimensionException If attempting to access an invalid element.
137: */
138: public abstract double getImagElement(final int i, final int j);
139:
140: /**
141: * Sets the value of an element of the matrix.
142: * Should only be used to initialise this matrix.
143: * @param i row index of the element
144: * @param j column index of the element
145: * @param z a complex number
146: * @exception MatrixDimensionException If attempting to access an invalid element.
147: */
148: public abstract void setElement(final int i, final int j,
149: final Complex z);
150:
151: /**
152: * Sets the value of an element of the matrix.
153: * Should only be used to initialise this matrix.
154: * @param i row index of the element
155: * @param j column index of the element
156: * @param x the real part of a complex number
157: * @param y the imaginary part of a complex number
158: * @exception MatrixDimensionException If attempting to access an invalid element.
159: */
160: public abstract void setElement(final int i, final int j,
161: final double x, final double y);
162:
163: public Object getSet() {
164: throw new RuntimeException("Not implemented: file bug");
165: }
166:
167: /**
168: * Returns the l<sup><img border=0 alt="infinity" src="doc-files/infinity.gif"></sup>-norm.
169: * @author Taber Smith
170: */
171: public double infNorm() {
172: double result = 0.0, tmpResult;
173: for (int i = 0; i < numRows; i++) {
174: tmpResult = 0.0;
175: for (int j = 0; j < numCols; j++)
176: tmpResult += getElement(i, j).norm();
177: if (tmpResult > result)
178: result = tmpResult;
179: }
180: return result;
181: }
182:
183: /**
184: * Returns the Frobenius or Hilbert-Schmidt (l<sup>2</sup>) norm.
185: * @jsci.planetmath FrobeniusMatrixNorm
186: * @author Taber Smith
187: */
188: public double frobeniusNorm() {
189: double result = 0.0;
190: for (int i = 0; i < numRows; i++) {
191: for (int j = 0; j < numCols; j++)
192: result += getRealElement(i, j) * getRealElement(i, j)
193: + getImagElement(i, j) * getImagElement(i, j);
194: }
195: return Math.sqrt(result);
196: }
197:
198: //============
199: // OPERATIONS
200: //============
201:
202: /**
203: * Returns the negative of this matrix.
204: */
205: public AbelianGroup.Member negate() {
206: final double arrayRe[][] = new double[numRows][numCols];
207: final double arrayIm[][] = new double[numRows][numCols];
208: for (int i = 0; i < numRows; i++) {
209: arrayRe[i][0] = -getRealElement(i, 0);
210: arrayIm[i][0] = -getImagElement(i, 0);
211: for (int j = 1; j < numCols; j++) {
212: arrayRe[i][j] = -getRealElement(i, j);
213: arrayIm[i][j] = -getImagElement(i, j);
214: }
215: }
216: return new ComplexMatrix(arrayRe, arrayIm);
217: }
218:
219: // ADDITION
220:
221: /**
222: * Returns the addition of this matrix and another.
223: */
224: public final AbelianGroup.Member add(final AbelianGroup.Member m) {
225: if (m instanceof AbstractComplexMatrix)
226: return add((AbstractComplexMatrix) m);
227: else
228: throw new IllegalArgumentException(
229: "Member class not recognised by this method.");
230: }
231:
232: /**
233: * Returns the addition of this matrix and another.
234: * @param m a complex matrix
235: * @exception MatrixDimensionException If the matrices are different sizes.
236: */
237: public AbstractComplexMatrix add(final AbstractComplexMatrix m) {
238: if (numRows == m.rows() && numCols == m.columns()) {
239: final double arrayRe[][] = new double[numRows][numCols];
240: final double arrayIm[][] = new double[numRows][numCols];
241: for (int i = 0; i < numRows; i++) {
242: arrayRe[i][0] = getRealElement(i, 0)
243: + m.getRealElement(i, 0);
244: arrayIm[i][0] = getImagElement(i, 0)
245: + m.getImagElement(i, 0);
246: for (int j = 1; j < numCols; j++) {
247: arrayRe[i][j] = getRealElement(i, j)
248: + m.getRealElement(i, j);
249: arrayIm[i][j] = getImagElement(i, j)
250: + m.getImagElement(i, j);
251: }
252: }
253: return new ComplexMatrix(arrayRe, arrayIm);
254: } else
255: throw new MatrixDimensionException(
256: "Matrices are different sizes.");
257: }
258:
259: // SUBTRACTION
260:
261: /**
262: * Returns the subtraction of this matrix by another.
263: */
264: public final AbelianGroup.Member subtract(
265: final AbelianGroup.Member m) {
266: if (m instanceof AbstractComplexMatrix)
267: return subtract((AbstractComplexMatrix) m);
268: else
269: throw new IllegalArgumentException(
270: "Member class not recognised by this method.");
271: }
272:
273: /**
274: * Returns the subtraction of this matrix by another.
275: * @param m a complex matrix
276: * @exception MatrixDimensionException If the matrices are different sizes.
277: */
278: public AbstractComplexMatrix subtract(final AbstractComplexMatrix m) {
279: if (numRows == m.rows() && numCols == m.columns()) {
280: final double arrayRe[][] = new double[numRows][numCols];
281: final double arrayIm[][] = new double[numRows][numCols];
282: for (int i = 0; i < numRows; i++) {
283: arrayRe[i][0] = getRealElement(i, 0)
284: - m.getRealElement(i, 0);
285: arrayIm[i][0] = getImagElement(i, 0)
286: - m.getImagElement(i, 0);
287: for (int j = 1; j < numCols; j++) {
288: arrayRe[i][j] = getRealElement(i, j)
289: - m.getRealElement(i, j);
290: arrayIm[i][j] = getImagElement(i, j)
291: - m.getImagElement(i, j);
292: }
293: }
294: return new ComplexMatrix(arrayRe, arrayIm);
295: } else
296: throw new MatrixDimensionException(
297: "Matrices are different sizes.");
298: }
299:
300: // SCALAR MULTIPLICATION
301:
302: /**
303: * Returns the multiplication of this matrix by a scalar.
304: */
305: public final Module.Member scalarMultiply(Ring.Member x) {
306: if (x instanceof Complex)
307: return scalarMultiply((Complex) x);
308: else if (x instanceof MathDouble)
309: return scalarMultiply(((MathDouble) x).value());
310: else if (x instanceof MathInteger)
311: return scalarMultiply(((MathInteger) x).value());
312: else
313: throw new IllegalArgumentException(
314: "Member class not recognised by this method.");
315: }
316:
317: /**
318: * Returns the multiplication of this matrix by a scalar.
319: * @param z a complex number
320: * @return a complex matrix
321: */
322: public AbstractComplexMatrix scalarMultiply(final Complex z) {
323: final double real = z.real();
324: final double imag = z.imag();
325: final double arrayRe[][] = new double[numRows][numCols];
326: final double arrayIm[][] = new double[numRows][numCols];
327: for (int i = 0; i < numRows; i++) {
328: arrayRe[i][0] = real * getRealElement(i, 0) - imag
329: * getImagElement(i, 0);
330: arrayIm[i][0] = imag * getRealElement(i, 0) + real
331: * getImagElement(i, 0);
332: for (int j = 1; j < numCols; j++) {
333: arrayRe[i][j] = real * getRealElement(i, j) - imag
334: * getImagElement(i, j);
335: arrayIm[i][j] = imag * getRealElement(i, j) + real
336: * getImagElement(i, j);
337: }
338: }
339: return new ComplexMatrix(arrayRe, arrayIm);
340: }
341:
342: /**
343: * Returns the multiplication of this matrix by a scalar.
344: * @param x a double
345: * @return a complex matrix
346: */
347: public AbstractComplexMatrix scalarMultiply(final double x) {
348: final double arrayRe[][] = new double[numRows][numCols];
349: final double arrayIm[][] = new double[numRows][numCols];
350: for (int i = 0; i < numRows; i++) {
351: arrayRe[i][0] = x * getRealElement(i, 0);
352: arrayIm[i][0] = x * getImagElement(i, 0);
353: for (int j = 1; j < numCols; j++) {
354: arrayRe[i][j] = x * getRealElement(i, j);
355: arrayIm[i][j] = x * getImagElement(i, j);
356: }
357: }
358: return new ComplexMatrix(arrayRe, arrayIm);
359: }
360:
361: // SCALAR DIVISON
362:
363: /**
364: * Returns the division of this matrix by a scalar.
365: */
366: public final VectorSpace.Member scalarDivide(Field.Member x) {
367: if (x instanceof Complex)
368: return scalarDivide((Complex) x);
369: if (x instanceof MathDouble)
370: return scalarDivide(((MathDouble) x).value());
371: else
372: throw new IllegalArgumentException(
373: "Member class not recognised by this method.");
374: }
375:
376: /**
377: * Returns the division of this matrix by a scalar.
378: * @param z a complex number
379: * @return a complex matrix
380: */
381: public AbstractComplexMatrix scalarDivide(final Complex z) {
382: final Complex array[][] = new Complex[numRows][numCols];
383: for (int i = 0; i < numRows; i++) {
384: array[i][0] = getElement(i, 0).divide(z);
385: for (int j = 1; j < numCols; j++)
386: array[i][j] = getElement(i, j).divide(z);
387: }
388: return new ComplexMatrix(array);
389: }
390:
391: /**
392: * Returns the division of this matrix by a scalar.
393: * @param x a double
394: * @return a complex matrix
395: */
396: public AbstractComplexMatrix scalarDivide(final double x) {
397: final double arrayRe[][] = new double[numRows][numCols];
398: final double arrayIm[][] = new double[numRows][numCols];
399: for (int i = 0; i < numRows; i++) {
400: arrayRe[i][0] = getRealElement(i, 0) / x;
401: arrayIm[i][0] = getImagElement(i, 0) / x;
402: for (int j = 1; j < numCols; j++) {
403: arrayRe[i][j] = getRealElement(i, j) / x;
404: arrayIm[i][j] = getImagElement(i, j) / x;
405: }
406: }
407: return new ComplexMatrix(arrayRe, arrayIm);
408: }
409:
410: // SCALAR PRODUCT
411:
412: /**
413: * Returns the scalar product of this matrix and another.
414: * @param m a complex matrix.
415: * @exception MatrixDimensionException If the matrices are different sizes.
416: */
417: public Complex scalarProduct(final AbstractComplexMatrix m) {
418: if (numRows == m.rows() && numCols == m.columns()) {
419: double real = 0.0, imag = 0.0;
420: for (int i = 0; i < numRows; i++) {
421: real += getRealElement(i, 0) * m.getRealElement(i, 0)
422: + getImagElement(i, 0) * m.getImagElement(i, 0);
423: imag += getImagElement(i, 0) * m.getRealElement(i, 0)
424: - getRealElement(i, 0) * m.getImagElement(i, 0);
425: for (int j = 1; j < numCols; j++) {
426: real += getRealElement(i, j)
427: * m.getRealElement(i, j)
428: + getImagElement(i, j)
429: * m.getImagElement(i, j);
430: imag += getImagElement(i, j)
431: * m.getRealElement(i, j)
432: - getRealElement(i, j)
433: * m.getImagElement(i, j);
434: }
435: }
436: return new Complex(real, imag);
437: } else {
438: throw new MatrixDimensionException(
439: "Matrices are different sizes.");
440: }
441: }
442:
443: // MATRIX MULTIPLICATION
444:
445: /**
446: * Returns the multiplication of a vector by this matrix.
447: * @param v a complex vector
448: * @exception DimensionException If the matrix and vector are incompatible.
449: */
450: public AbstractComplexVector multiply(final AbstractComplexVector v) {
451: if (numCols == v.dimension()) {
452: final double arrayRe[] = new double[numRows];
453: final double arrayIm[] = new double[numRows];
454: Complex tmp;
455: for (int i = 0; i < numRows; i++) {
456: tmp = getElement(i, 0).multiply(v.getComponent(0));
457: arrayRe[i] = tmp.real();
458: arrayIm[i] = tmp.imag();
459: for (int j = 1; j < numCols; j++) {
460: tmp = getElement(i, j).multiply(v.getComponent(j));
461: arrayRe[i] += tmp.real();
462: arrayIm[i] += tmp.imag();
463: }
464: }
465: return new ComplexVector(arrayRe, arrayIm);
466: } else
467: throw new DimensionException(
468: "Matrix and vector are incompatible.");
469: }
470:
471: /**
472: * Returns the multiplication of this matrix and another.
473: */
474: public final Ring.Member multiply(final Ring.Member m) {
475: if (m instanceof AbstractComplexMatrix)
476: return multiply((AbstractComplexMatrix) m);
477: else
478: throw new IllegalArgumentException(
479: "Matrix class not recognised by this method.");
480: }
481:
482: /**
483: * Returns the multiplication of this matrix and another.
484: * @param m a complex matrix
485: * @return an AbstractComplexMatrix or an AbstractComplexSquareMatrix as appropriate
486: * @exception MatrixDimensionException If the matrices are incompatible.
487: */
488: public AbstractComplexMatrix multiply(final AbstractComplexMatrix m) {
489: if (numCols == m.rows()) {
490: final double arrayRe[][] = new double[numRows][m.columns()];
491: final double arrayIm[][] = new double[numRows][m.columns()];
492: Complex tmp;
493: for (int j = 0; j < numRows; j++) {
494: for (int k = 0; k < m.columns(); k++) {
495: tmp = getElement(j, 0).multiply(m.getElement(0, k));
496: arrayRe[j][k] = tmp.real();
497: arrayIm[j][k] = tmp.imag();
498: for (int n = 1; n < numCols; n++) {
499: tmp = getElement(j, n).multiply(
500: m.getElement(n, k));
501: arrayRe[j][k] += tmp.real();
502: arrayIm[j][k] += tmp.imag();
503: }
504: }
505: }
506: if (numRows == m.columns())
507: return new ComplexSquareMatrix(arrayRe, arrayIm);
508: else
509: return new ComplexMatrix(arrayRe, arrayIm);
510: } else {
511: throw new MatrixDimensionException("Incompatible matrices.");
512: }
513: }
514:
515: // DIRECT SUM
516:
517: /**
518: * Returns the direct sum of this matrix and another.
519: */
520: public AbstractComplexMatrix directSum(final AbstractComplexMatrix m) {
521: final double arrayRe[][] = new double[numRows + m.numRows][numCols
522: + m.numCols];
523: final double arrayIm[][] = new double[numRows + m.numRows][numCols
524: + m.numCols];
525: for (int j, i = 0; i < numRows; i++) {
526: for (j = 0; j < numCols; j++) {
527: arrayRe[i][j] = getRealElement(i, j);
528: arrayIm[i][j] = getImagElement(i, j);
529: }
530: }
531: for (int j, i = 0; i < m.numRows; i++) {
532: for (j = 0; j < m.numCols; j++) {
533: arrayRe[i + numRows][j + numCols] = m.getRealElement(i,
534: j);
535: arrayIm[i + numRows][j + numCols] = m.getImagElement(i,
536: j);
537: }
538: }
539: return new ComplexMatrix(arrayRe, arrayIm);
540: }
541:
542: // TENSOR PRODUCT
543:
544: /**
545: * Returns the tensor product of this matrix and another.
546: */
547: public AbstractComplexMatrix tensor(final AbstractComplexMatrix m) {
548: final double arrayRe[][] = new double[numRows * m.numRows][numCols
549: * m.numCols];
550: final double arrayIm[][] = new double[numRows * m.numRows][numCols
551: * m.numCols];
552: for (int i = 0; i < numRows; i++) {
553: for (int j = 0; j < numCols; j++) {
554: for (int k = 0; k < m.numRows; j++) {
555: for (int l = 0; l < m.numCols; l++) {
556: Complex tmp = getElement(i, j).multiply(
557: m.getElement(k, l));
558: arrayRe[i * m.numRows + k][j * m.numCols + l] = tmp
559: .real();
560: arrayIm[i * m.numRows + k][j * m.numCols + l] = tmp
561: .imag();
562: }
563: }
564: }
565: }
566: return new ComplexMatrix(arrayRe, arrayIm);
567: }
568:
569: // HERMITIAN ADJOINT
570:
571: /**
572: * Returns the hermitian adjoint of this matrix.
573: * @return a complex matrix
574: */
575: public AbstractComplexMatrix hermitianAdjoint() {
576: final double arrayRe[][] = new double[numCols][numRows];
577: final double arrayIm[][] = new double[numCols][numRows];
578: for (int i = 0; i < numRows; i++) {
579: arrayRe[0][i] = getRealElement(i, 0);
580: arrayIm[0][i] = -getImagElement(i, 0);
581: for (int j = 1; j < numCols; j++) {
582: arrayRe[j][i] = getRealElement(i, j);
583: arrayIm[j][i] = -getImagElement(i, j);
584: }
585: }
586: return new ComplexMatrix(arrayRe, arrayIm);
587: }
588:
589: // CONJUGATE
590:
591: /**
592: * Returns the complex conjugate of this matrix.
593: * @return a complex matrix
594: */
595: public AbstractComplexMatrix conjugate() {
596: final double arrayRe[][] = new double[numCols][numRows];
597: final double arrayIm[][] = new double[numCols][numRows];
598: for (int i = 0; i < numRows; i++) {
599: arrayRe[i][0] = getRealElement(i, 0);
600: arrayIm[i][0] = -getImagElement(i, 0);
601: for (int j = 1; j < numCols; j++) {
602: arrayRe[i][j] = getRealElement(i, j);
603: arrayIm[i][j] = -getImagElement(i, j);
604: }
605: }
606: return new ComplexMatrix(arrayRe, arrayIm);
607: }
608:
609: // TRANSPOSE
610:
611: /**
612: * Returns the transpose of this matrix.
613: * @return a complex matrix
614: */
615: public Matrix transpose() {
616: final double arrayRe[][] = new double[numCols][numRows];
617: final double arrayIm[][] = new double[numCols][numRows];
618: for (int i = 0; i < numRows; i++) {
619: arrayRe[0][i] = getRealElement(i, 0);
620: arrayIm[0][i] = getImagElement(i, 0);
621: for (int j = 1; j < numCols; j++) {
622: arrayRe[j][i] = getRealElement(i, j);
623: arrayIm[j][i] = getImagElement(i, j);
624: }
625: }
626: return new ComplexMatrix(arrayRe, arrayIm);
627: }
628:
629: // MAP ELEMENTS
630:
631: /**
632: * Applies a function on all the matrix elements.
633: * @param f a user-defined function
634: * @return a complex matrix
635: */
636: public AbstractComplexMatrix mapElements(final ComplexMapping f) {
637: final Complex array[][] = new Complex[numRows][numCols];
638: for (int i = 0; i < numRows; i++) {
639: array[i][0] = f.map(getElement(i, 0));
640: for (int j = 1; j < numCols; j++)
641: array[i][j] = f.map(getElement(i, j));
642: }
643: return new ComplexMatrix(array);
644: }
645: }
|