View Javadoc

1   package Jama;
2   
3   import java.io.BufferedReader;
4   import java.io.PrintWriter;
5   import java.io.StreamTokenizer;
6   import java.text.DecimalFormat;
7   import java.text.DecimalFormatSymbols;
8   import java.text.NumberFormat;
9   import java.util.Locale;
10  
11  import Jama.util.Maths;
12  
13  /**
14     Jama = Java Matrix class.
15  <P>
16     The Java Matrix Class provides the fundamental operations of numerical
17     linear algebra.  Various constructors create Matrices from two dimensional
18     arrays of double precision floating point numbers.  Various "gets" and
19     "sets" provide access to submatrices and matrix elements.  Several methods 
20     implement basic matrix arithmetic, including matrix addition and
21     multiplication, matrix norms, and element-by-element array operations.
22     Methods for reading and printing matrices are also included.  All the
23     operations in this version of the Matrix Class involve real matrices.
24     Complex matrices may be handled in a future version.
25  <P>
26     Five fundamental matrix decompositions, which consist of pairs or triples
27     of matrices, permutation vectors, and the like, produce results in five
28     decomposition classes.  These decompositions are accessed by the Matrix
29     class to compute solutions of simultaneous linear equations, determinants,
30     inverses and other matrix functions.  The five decompositions are:
31  <P><UL>
32     <LI>Cholesky Decomposition of symmetric, positive definite matrices.
33     <LI>LU Decomposition of rectangular matrices.
34     <LI>QR Decomposition of rectangular matrices.
35     <LI>Singular Value Decomposition of rectangular matrices.
36     <LI>Eigenvalue Decomposition of both symmetric and nonsymmetric square matrices.
37  </UL>
38  <DL>
39  <DT><B>Example of use:</B></DT>
40  <P>
41  <DD>Solve a linear system A x = b and compute the residual norm, ||b - A x||.
42  <P><PRE>
43        double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}};
44        Matrix A = new Matrix(vals);
45        Matrix b = Matrix.random(3,1);
46        Matrix x = A.solve(b);
47        Matrix r = A.times(x).minus(b);
48        double rnorm = r.normInf();
49  </PRE></DD>
50  </DL>
51  
52  @author The MathWorks, Inc. and the National Institute of Standards and Technology.
53  @version 5 August 1998 $Id: Matrix.java,v 1.1.1.1 2010/11/30 21:31:59 jeremy Exp $
54  */
55  
56  public class Matrix implements Cloneable, java.io.Serializable {
57  
58  /* ------------------------
59     Class variables
60   * ------------------------ */
61  
62     /** Array for internal storage of elements.
63     @serial internal array storage.
64     */
65     private double[][] A;
66  
67     /** Row and column dimensions.
68     @serial row dimension.
69     @serial column dimension.
70     */
71     private int m, n;
72  
73  /* ------------------------
74     Constructors
75   * ------------------------ */
76  
77     /** Construct an m-by-n matrix of zeros. 
78     @param m    Number of rows.
79     @param n    Number of colums.
80     */
81  
82     public Matrix (int m, int n) {
83        this.m = m;
84        this.n = n;
85        A = new double[m][n];
86     }
87  
88     /** Construct an m-by-n constant matrix.
89     @param m    Number of rows.
90     @param n    Number of colums.
91     @param s    Fill the matrix with this scalar value.
92     */
93  
94     public Matrix (int m, int n, double s) {
95        this.m = m;
96        this.n = n;
97        A = new double[m][n];
98        for (int i = 0; i < m; i++) {
99           for (int j = 0; j < n; j++) {
100             A[i][j] = s;
101          }
102       }
103    }
104 
105    /** Construct a matrix from a 2-D array.
106    @param A    Two-dimensional array of doubles.
107    @exception  IllegalArgumentException All rows must have the same length
108    @see        #constructWithCopy
109    */
110 
111    public Matrix (double[][] A) {
112       m = A.length;
113       n = A[0].length;
114       for (int i = 0; i < m; i++) {
115          if (A[i].length != n) {
116             throw new IllegalArgumentException("All rows must have the same length.");
117          }
118       }
119       this.A = A;
120    }
121 
122    /** Construct a matrix quickly without checking arguments.
123    @param A    Two-dimensional array of doubles.
124    @param m    Number of rows.
125    @param n    Number of colums.
126    */
127 
128    public Matrix (double[][] A, int m, int n) {
129       this.A = A;
130       this.m = m;
131       this.n = n;
132    }
133 
134    /** Construct a matrix from a one-dimensional packed array
135    @param vals One-dimensional array of doubles, packed by columns (ala Fortran).
136    @param m    Number of rows.
137    @exception  IllegalArgumentException Array length must be a multiple of m.
138    */
139 
140    public Matrix (double vals[], int m) {
141       this.m = m;
142       n = (m != 0 ? vals.length/m : 0);
143       if (m*n != vals.length) {
144          throw new IllegalArgumentException("Array length must be a multiple of m.");
145       }
146       A = new double[m][n];
147       for (int i = 0; i < m; i++) {
148          for (int j = 0; j < n; j++) {
149             A[i][j] = vals[i+j*m];
150          }
151       }
152    }
153 
154 /* ------------------------
155    Public Methods
156  * ------------------------ */
157 
158    /** Construct a matrix from a copy of a 2-D array.
159    @param A    Two-dimensional array of doubles.
160    @exception  IllegalArgumentException All rows must have the same length
161    */
162 
163    public static Matrix constructWithCopy(double[][] A) {
164       int m = A.length;
165       int n = A[0].length;
166       Matrix X = new Matrix(m,n);
167       double[][] C = X.getArray();
168       for (int i = 0; i < m; i++) {
169          if (A[i].length != n) {
170             throw new IllegalArgumentException
171                ("All rows must have the same length.");
172          }
173          for (int j = 0; j < n; j++) {
174             C[i][j] = A[i][j];
175          }
176       }
177       return X;
178    }
179 
180    /** Make a deep copy of a matrix
181    */
182 
183    public Matrix copy () {
184       Matrix X = new Matrix(m,n);
185       double[][] C = X.getArray();
186       for (int i = 0; i < m; i++) {
187          for (int j = 0; j < n; j++) {
188             C[i][j] = A[i][j];
189          }
190       }
191       return X;
192    }
193 
194    /** Clone the Matrix object.
195    */
196 
197    public Object clone () {
198       return this.copy();
199    }
200 
201    /** Access the internal two-dimensional array.
202    @return     Pointer to the two-dimensional array of matrix elements.
203    */
204 
205    public double[][] getArray () {
206       return A;
207    }
208 
209    /** Copy the internal two-dimensional array.
210    @return     Two-dimensional array copy of matrix elements.
211    */
212 
213    public double[][] getArrayCopy () {
214       double[][] C = new double[m][n];
215       for (int i = 0; i < m; i++) {
216          for (int j = 0; j < n; j++) {
217             C[i][j] = A[i][j];
218          }
219       }
220       return C;
221    }
222 
223    /** Make a one-dimensional column packed copy of the internal array.
224    @return     Matrix elements packed in a one-dimensional array by columns.
225    */
226 
227    public double[] getColumnPackedCopy () {
228       double[] vals = new double[m*n];
229       for (int i = 0; i < m; i++) {
230          for (int j = 0; j < n; j++) {
231             vals[i+j*m] = A[i][j];
232          }
233       }
234       return vals;
235    }
236 
237    /** Make a one-dimensional row packed copy of the internal array.
238    @return     Matrix elements packed in a one-dimensional array by rows.
239    */
240 
241    public double[] getRowPackedCopy () {
242       double[] vals = new double[m*n];
243       for (int i = 0; i < m; i++) {
244          for (int j = 0; j < n; j++) {
245             vals[i*n+j] = A[i][j];
246          }
247       }
248       return vals;
249    }
250 
251    /** 
252    @return     the number of rows.
253    */
254 
255    public int getRowDimension () {
256       return m;
257    }
258 
259    /** 
260    @return     the number of columns.
261    */
262 
263    public int getColumnDimension () {
264       return n;
265    }
266 
267    /**  
268    @param i    Row index.
269    @param j    Column index.
270    @return     A(i,j)
271    @exception  ArrayIndexOutOfBoundsException
272    */
273 
274    public double get (int i, int j) {
275       return A[i][j];
276    }
277 
278    /** Returns a submatrix.
279    @param i0   Initial row index
280    @param i1   Final row index
281    @param j0   Initial column index
282    @param j1   Final column index
283    @return     A(i0:i1,j0:j1)
284    @exception  ArrayIndexOutOfBoundsException Submatrix indices
285    */
286 
287    public Matrix getMatrix (int i0, int i1, int j0, int j1) {
288       Matrix X = new Matrix(i1-i0+1,j1-j0+1);
289       double[][] B = X.getArray();
290       try {
291          for (int i = i0; i <= i1; i++) {
292             for (int j = j0; j <= j1; j++) {
293                B[i-i0][j-j0] = A[i][j];
294             }
295          }
296       } catch(ArrayIndexOutOfBoundsException e) {
297          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
298       }
299       return X;
300    }
301 
302    /** Returns a submatrix.
303    @param r    Array of row indices.
304    @param c    Array of column indices.
305    @return     A(r(:),c(:))
306    @exception  ArrayIndexOutOfBoundsException Submatrix indices
307    */
308 
309    public Matrix getMatrix (int[] r, int[] c) {
310       Matrix X = new Matrix(r.length,c.length);
311       double[][] B = X.getArray();
312       try {
313          for (int i = 0; i < r.length; i++) {
314             for (int j = 0; j < c.length; j++) {
315                B[i][j] = A[r[i]][c[j]];
316             }
317          }
318       } catch(ArrayIndexOutOfBoundsException e) {
319          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
320       }
321       return X;
322    }
323 
324    /** Returns a submatrix.
325    @param i0   Initial row index
326    @param i1   Final row index
327    @param c    Array of column indices.
328    @return     A(i0:i1,c(:))
329    @exception  ArrayIndexOutOfBoundsException Submatrix indices
330    */
331 
332    public Matrix getMatrix (int i0, int i1, int[] c) {
333       Matrix X = new Matrix(i1-i0+1,c.length);
334       double[][] B = X.getArray();
335       try {
336          for (int i = i0; i <= i1; i++) {
337             for (int j = 0; j < c.length; j++) {
338                B[i-i0][j] = A[i][c[j]];
339             }
340          }
341       } catch(ArrayIndexOutOfBoundsException e) {
342          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
343       }
344       return X;
345    }
346 
347    /** Returns a submatrix.
348    @param r    Array of row indices.
349    @param j0   Initial column index
350    @param j1   Final column index
351    @return     A(r(:),j0:j1)
352    @exception  ArrayIndexOutOfBoundsException Submatrix indices
353    */
354 
355    public Matrix getMatrix (int[] r, int j0, int j1) {
356       Matrix X = new Matrix(r.length,j1-j0+1);
357       double[][] B = X.getArray();
358       try {
359          for (int i = 0; i < r.length; i++) {
360             for (int j = j0; j <= j1; j++) {
361                B[i][j-j0] = A[r[i]][j];
362             }
363          }
364       } catch(ArrayIndexOutOfBoundsException e) {
365          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
366       }
367       return X;
368    }
369 
370    /** Sets a single element.
371    @param i    Row index.
372    @param j    Column index.
373    @param s    A(i,j).
374    @exception  ArrayIndexOutOfBoundsException
375    */
376 
377    public void set (int i, int j, double s) {
378       A[i][j] = s;
379    }
380 
381    /** Sets a submatrix.
382    @param i0   Initial row index
383    @param i1   Final row index
384    @param j0   Initial column index
385    @param j1   Final column index
386    @param X    A(i0:i1,j0:j1)
387    @exception  ArrayIndexOutOfBoundsException Submatrix indices
388    */
389 
390    public void setMatrix (int i0, int i1, int j0, int j1, Matrix X) {
391       try {
392          for (int i = i0; i <= i1; i++) {
393             for (int j = j0; j <= j1; j++) {
394                A[i][j] = X.get(i-i0,j-j0);
395             }
396          }
397       } catch(ArrayIndexOutOfBoundsException e) {
398          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
399       }
400    }
401 
402    /** Sets a submatrix.
403    @param r    Array of row indices.
404    @param c    Array of column indices.
405    @param X    A(r(:),c(:))
406    @exception  ArrayIndexOutOfBoundsException Submatrix indices
407    */
408 
409    public void setMatrix (int[] r, int[] c, Matrix X) {
410       try {
411          for (int i = 0; i < r.length; i++) {
412             for (int j = 0; j < c.length; j++) {
413                A[r[i]][c[j]] = X.get(i,j);
414             }
415          }
416       } catch(ArrayIndexOutOfBoundsException e) {
417          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
418       }
419    }
420 
421    /** Sets a submatrix.
422    @param r    Array of row indices.
423    @param j0   Initial column index
424    @param j1   Final column index
425    @param X    A(r(:),j0:j1)
426    @exception  ArrayIndexOutOfBoundsException Submatrix indices
427    */
428 
429    public void setMatrix (int[] r, int j0, int j1, Matrix X) {
430       try {
431          for (int i = 0; i < r.length; i++) {
432             for (int j = j0; j <= j1; j++) {
433                A[r[i]][j] = X.get(i,j-j0);
434             }
435          }
436       } catch(ArrayIndexOutOfBoundsException e) {
437          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
438       }
439    }
440 
441    /** Sets a submatrix.
442    @param i0   Initial row index
443    @param i1   Final row index
444    @param c    Array of column indices.
445    @param X    A(i0:i1,c(:))
446    @exception  ArrayIndexOutOfBoundsException Submatrix indices
447    */
448 
449    public void setMatrix (int i0, int i1, int[] c, Matrix X) {
450       try {
451          for (int i = i0; i <= i1; i++) {
452             for (int j = 0; j < c.length; j++) {
453                A[i][c[j]] = X.get(i-i0,j);
454             }
455          }
456       } catch(ArrayIndexOutOfBoundsException e) {
457          throw new ArrayIndexOutOfBoundsException("Submatrix indices");
458       }
459    }
460 
461    /**
462     * Returns the transpose of the matrix. The elements of this matrix remain unchanged.
463     * @return    a new matrix A<sup>T</sup>
464    */
465 
466    public Matrix transpose () {
467       Matrix X = new Matrix(n,m);
468       double[][] C = X.getArray();
469       for (int i = 0; i < m; i++) {
470          for (int j = 0; j < n; j++) {
471             C[j][i] = A[i][j];
472          }
473       }
474       return X;
475    }
476 
477    /** One norm
478    @return    maximum column sum.
479    */
480 
481    public double norm1 () {
482       double f = 0;
483       for (int j = 0; j < n; j++) {
484          double s = 0;
485          for (int i = 0; i < m; i++) {
486             s += Math.abs(A[i][j]);
487          }
488          f = Math.max(f,s);
489       }
490       return f;
491    }
492 
493    /** Two norm
494    @return    maximum singular value.
495    */
496 
497    public double norm2 () {
498       return (new SingularValueDecomposition(this).norm2());
499    }
500 
501    /** Infinity norm
502    @return    maximum row sum.
503    */
504 
505    public double normInf () {
506       double f = 0;
507       for (int i = 0; i < m; i++) {
508          double s = 0;
509          for (int j = 0; j < n; j++) {
510             s += Math.abs(A[i][j]);
511          }
512          f = Math.max(f,s);
513       }
514       return f;
515    }
516 
517    /** Frobenius norm
518    @return    sqrt of sum of squares of all elements.
519    */
520 
521    public double normF () {
522       double f = 0;
523       for (int i = 0; i < m; i++) {
524          for (int j = 0; j < n; j++) {
525             f = Maths.hypot(f,A[i][j]);
526          }
527       }
528       return f;
529    }
530 
531    /**  Unary minus
532    @return    -A
533    */
534 
535    public Matrix uminus () {
536       Matrix X = new Matrix(m,n);
537       double[][] C = X.getArray();
538       for (int i = 0; i < m; i++) {
539          for (int j = 0; j < n; j++) {
540             C[i][j] = -A[i][j];
541          }
542       }
543       return X;
544    }
545 
546    /** C = A + B
547    @param B    another matrix
548    @return     A + B
549    */
550 
551    public Matrix plus (Matrix B) {
552       checkMatrixDimensions(B);
553       Matrix X = new Matrix(m,n);
554       double[][] C = X.getArray();
555       for (int i = 0; i < m; i++) {
556          for (int j = 0; j < n; j++) {
557             C[i][j] = A[i][j] + B.A[i][j];
558          }
559       }
560       return X;
561    }
562 
563    /** A = A + B
564    @param B    another matrix
565    @return     A + B
566    */
567 
568    public Matrix plusEquals (Matrix B) {
569       checkMatrixDimensions(B);
570       for (int i = 0; i < m; i++) {
571          for (int j = 0; j < n; j++) {
572             A[i][j] = A[i][j] + B.A[i][j];
573          }
574       }
575       return this;
576    }
577 
578    /** C = A - B
579    @param B    another matrix
580    @return     A - B
581    */
582 
583    public Matrix minus (Matrix B) {
584       checkMatrixDimensions(B);
585       Matrix X = new Matrix(m,n);
586       double[][] C = X.getArray();
587       for (int i = 0; i < m; i++) {
588          for (int j = 0; j < n; j++) {
589             C[i][j] = A[i][j] - B.A[i][j];
590          }
591       }
592       return X;
593    }
594 
595    /** A = A - B
596    @param B    another matrix
597    @return     A - B
598    */
599 
600    public Matrix minusEquals (Matrix B) {
601       checkMatrixDimensions(B);
602       for (int i = 0; i < m; i++) {
603          for (int j = 0; j < n; j++) {
604             A[i][j] = A[i][j] - B.A[i][j];
605          }
606       }
607       return this;
608    }
609 
610    /** Element-by-element multiplication, C = A.*B
611    @param B    another matrix
612    @return     A.*B
613    */
614 
615    public Matrix arrayTimes (Matrix B) {
616       checkMatrixDimensions(B);
617       Matrix X = new Matrix(m,n);
618       double[][] C = X.getArray();
619       for (int i = 0; i < m; i++) {
620          for (int j = 0; j < n; j++) {
621             C[i][j] = A[i][j] * B.A[i][j];
622          }
623       }
624       return X;
625    }
626 
627    /** Element-by-element multiplication in place, A = A.*B
628    @param B    another matrix
629    @return     A.*B
630    */
631 
632    public Matrix arrayTimesEquals (Matrix B) {
633       checkMatrixDimensions(B);
634       for (int i = 0; i < m; i++) {
635          for (int j = 0; j < n; j++) {
636             A[i][j] = A[i][j] * B.A[i][j];
637          }
638       }
639       return this;
640    }
641 
642    /** Element-by-element right division, C = A./B
643    @param B    another matrix
644    @return     A./B
645    */
646 
647    public Matrix arrayRightDivide (Matrix B) {
648       checkMatrixDimensions(B);
649       Matrix X = new Matrix(m,n);
650       double[][] C = X.getArray();
651       for (int i = 0; i < m; i++) {
652          for (int j = 0; j < n; j++) {
653             C[i][j] = A[i][j] / B.A[i][j];
654          }
655       }
656       return X;
657    }
658 
659    /** Element-by-element right division in place, A = A./B
660    @param B    another matrix
661    @return     A./B
662    */
663 
664    public Matrix arrayRightDivideEquals (Matrix B) {
665       checkMatrixDimensions(B);
666       for (int i = 0; i < m; i++) {
667          for (int j = 0; j < n; j++) {
668             A[i][j] = A[i][j] / B.A[i][j];
669          }
670       }
671       return this;
672    }
673 
674    /** Element-by-element left division, C = A.\B
675    @param B    another matrix
676    @return     A.\B
677    */
678 
679    public Matrix arrayLeftDivide (Matrix B) {
680       checkMatrixDimensions(B);
681       Matrix X = new Matrix(m,n);
682       double[][] C = X.getArray();
683       for (int i = 0; i < m; i++) {
684          for (int j = 0; j < n; j++) {
685             C[i][j] = B.A[i][j] / A[i][j];
686          }
687       }
688       return X;
689    }
690 
691    /** Element-by-element left division in place, A = A.\B
692    @param B    another matrix
693    @return     A.\B
694    */
695 
696    public Matrix arrayLeftDivideEquals (Matrix B) {
697       checkMatrixDimensions(B);
698       for (int i = 0; i < m; i++) {
699          for (int j = 0; j < n; j++) {
700             A[i][j] = B.A[i][j] / A[i][j];
701          }
702       }
703       return this;
704    }
705 
706    /** Multiply a matrix by a scalar, C = s*A
707    @param s    scalar
708    @return     s*A
709    */
710 
711    public Matrix times (double s) {
712       Matrix X = new Matrix(m,n);
713       double[][] C = X.getArray();
714       for (int i = 0; i < m; i++) {
715          for (int j = 0; j < n; j++) {
716             C[i][j] = s*A[i][j];
717          }
718       }
719       return X;
720    }
721 
722    /** Multiply a matrix by a scalar in place, A = s*A
723    @param s    scalar
724    @return     replace A by s*A
725    */
726 
727    public Matrix timesEquals (double s) {
728       for (int i = 0; i < m; i++) {
729          for (int j = 0; j < n; j++) {
730             A[i][j] = s*A[i][j];
731          }
732       }
733       return this;
734    }
735 
736    /** Linear algebraic matrix multiplication, A * B
737    @param B    another matrix
738    @return     Matrix product, A * B
739    @exception  IllegalArgumentException Matrix inner dimensions must agree.
740    */
741 
742    public Matrix times (Matrix B) {
743       if (B.m != n) {
744          throw new IllegalArgumentException("Matrix inner dimensions must agree.");
745       }
746       Matrix X = new Matrix(m,B.n);
747       double[][] C = X.getArray();
748       double[] Bcolj = new double[n];
749       for (int j = 0; j < B.n; j++) {
750          for (int k = 0; k < n; k++) {
751             Bcolj[k] = B.A[k][j];
752          }
753          for (int i = 0; i < m; i++) {
754             double[] Arowi = A[i];
755             double s = 0;
756             for (int k = 0; k < n; k++) {
757                s += Arowi[k]*Bcolj[k];
758             }
759             C[i][j] = s;
760          }
761       }
762       return X;
763    }
764    
765    /**
766     * Calculates the vector y = A.x
767     * @param x
768     * @return a new vector y
769     */
770    public double[] times(double[] x) {
771 	   if (n != x.length)
772 			throw new IllegalArgumentException("dimensions do not match");
773 		double[] result = new double[m];
774 		
775 		for (int i=0; i<m; i++) {
776 			for (int j=0; j<n; j++) {
777 				result[i] += A[i][j] * x[j];
778 			}
779 		}
780 		return result;
781    	}
782 
783    /** LU Decomposition
784    @return     LUDecomposition
785    @see LUDecomposition
786    */
787 
788    public LUDecomposition lu () {
789       return new LUDecomposition(this);
790    }
791 
792    /** QR Decomposition
793    @return     QRDecomposition
794    @see QRDecomposition
795    */
796 
797    public QRDecomposition qr () {
798       return new QRDecomposition(this);
799    }
800 
801    /** Cholesky Decomposition
802    @return     CholeskyDecomposition
803    @see CholeskyDecomposition
804    */
805 
806    public CholeskyDecomposition chol () {
807       return new CholeskyDecomposition(this);
808    }
809 
810    /** Singular Value Decomposition
811    @return     SingularValueDecomposition
812    @see SingularValueDecomposition
813    */
814 
815    public SingularValueDecomposition svd () {
816       return new SingularValueDecomposition(this);
817    }
818 
819    /** Eigenvalue Decomposition
820    @return     EigenvalueDecomposition
821    @see EigenvalueDecomposition
822    */
823 
824    public EigenvalueDecomposition eig () {
825       return new EigenvalueDecomposition(this);
826    }
827 
828    /** Solve A*X = B
829    @param B    right hand side
830    @return     solution if A is square, least squares solution otherwise
831    */
832 
833    public Matrix solve (Matrix B) {
834       return (m == n ? (new LUDecomposition(this)).solve(B) :
835                        (new QRDecomposition(this)).solve(B));
836    }
837 
838    /** Solve X*A = B, which is also A'*X' = B'
839    @param B    right hand side
840    @return     solution if A is square, least squares solution otherwise.
841    */
842 
843    public Matrix solveTranspose (Matrix B) {
844       return transpose().solve(B.transpose());
845    }
846 
847    /** Matrix inverse or pseudoinverse
848    @return     inverse(A) if A is square, pseudoinverse otherwise.
849    */
850 
851    public Matrix inverse () {
852       return solve(identity(m,m));
853    }
854 
855    /** Matrix determinant
856    @return     determinant
857    */
858 
859    public double det () {
860       return new LUDecomposition(this).det();
861    }
862 
863    /** Matrix rank
864    @return     effective numerical rank, obtained from SVD.
865    */
866 
867    public int rank () {
868       return new SingularValueDecomposition(this).rank();
869    }
870 
871    /** Matrix condition (2 norm)
872    @return     ratio of largest to smallest singular value.
873    */
874 
875    public double cond () {
876       return new SingularValueDecomposition(this).cond();
877    }
878 
879    /** Matrix trace.
880    @return     sum of the diagonal elements.
881    */
882 
883    public double trace () {
884       double t = 0;
885       for (int i = 0; i < Math.min(m,n); i++) {
886          t += A[i][i];
887       }
888       return t;
889    }
890    
891    /** Matrix absolute maximum element.
892    @return     absolute value of largest element.
893    */
894 
895    public double amax () {
896       double amax = Math.abs(A[0][0]);
897       for (int i = 0; i < m; ++i) 
898 	  {
899 	  	for (int j = 0; j < n; ++j)
900 	  	{
901          if ( Math.abs(A[i][j])>amax ) amax = Math.abs(A[i][j]);
902 	  	}
903       }
904       return amax;
905    }
906  
907    /** Matrix absolute minimum element.
908    @return     absolute value of smallest element.
909    */
910 
911    public double amin() {
912       double amin = Math.abs(A[0][0]);
913       for (int i = 0; i < m; ++i) 
914 	  {
915 	  	for (int j = 0; j < n; ++j)
916 	  	{
917          if ( Math.abs(A[i][j])<amin ) amin = Math.abs(A[i][j]);
918 	  	}
919       }
920       return amin;
921    }   
922 
923    /** Matrix  maximum element.
924    @return     value of largest element.
925    */
926 
927    public double max () {
928       double max =  A[0][0];
929       for (int i = 0; i < m; ++i) 
930 	  {
931 	  	for (int j = 0; j < n; ++j)
932 	  	{
933          if ( A[i][j]>max ) max = A[i][j];
934 	  	}
935       }
936       return max;
937    }   
938    
939    /** Matrix minimum element.
940    @return      value of smallest element.
941    */
942 
943    public double min () {
944       double min = A[0][0];
945       for (int i = 0; i < m; ++i) 
946 	  {
947 	  	for (int j = 0; j < n; ++j)
948 	  	{
949          if ( A[i][j]<min ) min =  A[i][j];
950 	  	}
951       }
952       return min;
953    }   
954 
955    /** Generate matrix with random elements
956    @param m    Number of rows.
957    @param n    Number of colums.
958    @return     An m-by-n matrix with uniformly distributed random elements.
959    */
960 
961    public static Matrix random (int m, int n) {
962       Matrix A = new Matrix(m,n);
963       double[][] X = A.getArray();
964       for (int i = 0; i < m; i++) {
965          for (int j = 0; j < n; j++) {
966             X[i][j] = Math.random();
967          }
968       }
969       return A;
970    }
971 
972    /** Generate identity matrix
973    @param m    Number of rows.
974    @param n    Number of colums.
975    @return     An m-by-n matrix with ones on the diagonal and zeros elsewhere.
976    */
977 
978    public static Matrix identity (int m, int n) {
979       Matrix A = new Matrix(m,n);
980       double[][] X = A.getArray();
981       for (int i = 0; i < m; i++) {
982          for (int j = 0; j < n; j++) {
983             X[i][j] = (i == j ? 1.0 : 0.0);
984          }
985       }
986       return A;
987    }
988 
989 
990    /** Print the matrix to stdout.   Line the elements up in columns
991      * with a Fortran-like 'Fw.d' style format.
992    @param w    Column width.
993    @param d    Number of digits after the decimal.
994    */
995 
996    public void print (int w, int d) {
997       print(new PrintWriter(System.out,true),w,d); }
998 
999    /** Print the matrix to the output stream.   Line the elements up in
1000      * columns with a Fortran-like 'Fw.d' style format.
1001    @param output Output stream.
1002    @param w      Column width.
1003    @param d      Number of digits after the decimal.
1004    */
1005 
1006    public void print (PrintWriter output, int w, int d) {
1007       DecimalFormat format = new DecimalFormat();
1008       format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
1009       format.setMinimumIntegerDigits(1);
1010       format.setMaximumFractionDigits(d);
1011       format.setMinimumFractionDigits(d);
1012       format.setGroupingUsed(false);
1013       print(output,format,w+2);
1014    }
1015 
1016    /** Print the matrix to stdout.  Line the elements up in columns.
1017      * Use the format object, and right justify within columns of width
1018      * characters.
1019      * Note that is the matrix is to be read back in, you probably will want
1020      * to use a NumberFormat that is set to US Locale.
1021    @param format A  Formatting object for individual elements.
1022    @param width     Field width for each column.
1023    @see java.text.DecimalFormat#setDecimalFormatSymbols
1024    */
1025 
1026    public void print (NumberFormat format, int width) {
1027       print(new PrintWriter(System.out,true),format,width); }
1028 
1029    // DecimalFormat is a little disappointing coming from Fortran or C's printf.
1030    // Since it doesn't pad on the left, the elements will come out different
1031    // widths.  Consequently, we'll pass the desired column width in as an
1032    // argument and do the extra padding ourselves.
1033 
1034    /** Print the matrix to the output stream.  Line the elements up in columns.
1035      * Use the format object, and right justify within columns of width
1036      * characters.
1037      * Note that is the matrix is to be read back in, you probably will want
1038      * to use a NumberFormat that is set to US Locale.
1039    @param output the output stream.
1040    @param format A formatting object to format the matrix elements 
1041    @param width  Column width.
1042    @see java.text.DecimalFormat#setDecimalFormatSymbols
1043    */
1044 
1045    public void print (PrintWriter output, NumberFormat format, int width) {
1046       output.println();  // start on new line.
1047       for (int i = 0; i < m; i++) {
1048          for (int j = 0; j < n; j++) {
1049             String s = format.format(A[i][j]); // format the number
1050             int padding = Math.max(1,width-s.length()); // At _least_ 1 space
1051             for (int k = 0; k < padding; k++)
1052                output.print(' ');
1053             output.print(s);
1054          }
1055          output.println();
1056       }
1057       output.println();   // end with blank line.
1058    }
1059    
1060   /**
1061    * String representation for this Object.
1062    * @return string representation of this object.
1063    */
1064   public String toString()
1065   {
1066   	StringBuffer tmp = new StringBuffer();
1067 	for(int i = 0; i<m; ++i)
1068 	{
1069 		for(int j = 0; j<n; ++j)
1070 		{
1071 			tmp.append(" "+A[i][j]);
1072 		}
1073 		tmp.append("\n");
1074 	}
1075 	tmp.append("\n");
1076 	return tmp.toString();
1077   }
1078    
1079 
1080    /** Read a matrix from a stream.  The format is the same the print method,
1081      * so printed matrices can be read back in (provided they were printed using
1082      * US Locale).  Elements are separated by
1083      * whitespace, all the elements for each row appear on a single line,
1084      * the last row is followed by a blank line.
1085    @param input the input stream.
1086    */
1087 
1088    public static Matrix read (BufferedReader input) throws java.io.IOException {
1089       StreamTokenizer tokenizer= new StreamTokenizer(input);
1090 
1091       // Although StreamTokenizer will parse numbers, it doesn't recognize
1092       // scientific notation (E or D); however, Double.valueOf does.
1093       // The strategy here is to disable StreamTokenizer's number parsing.
1094       // We'll only get whitespace delimited words, EOL's and EOF's.
1095       // These words should all be numbers, for Double.valueOf to parse.
1096 
1097       tokenizer.resetSyntax();
1098       tokenizer.wordChars(0,255);
1099       tokenizer.whitespaceChars(0, ' ');
1100       tokenizer.eolIsSignificant(true);
1101       java.util.Vector v = new java.util.Vector();
1102 
1103       // Ignore initial empty lines
1104       while (tokenizer.nextToken() == StreamTokenizer.TT_EOL);
1105       if (tokenizer.ttype == StreamTokenizer.TT_EOF)
1106 	throw new java.io.IOException("Unexpected EOF on matrix read.");
1107       do {
1108          v.addElement(Double.valueOf(tokenizer.sval)); // Read & store 1st row.
1109       } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD);
1110 
1111       int n = v.size();  // Now we've got the number of columns!
1112       double row[] = new double[n];
1113       for (int j=0; j<n; j++)  // extract the elements of the 1st row.
1114          row[j]=((Double)v.elementAt(j)).doubleValue();
1115       v.removeAllElements();
1116       v.addElement(row);  // Start storing rows instead of columns.
1117       while (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
1118          // While non-empty lines
1119          v.addElement(row = new double[n]);
1120          int j = 0;
1121          do {
1122             if (j >= n) throw new java.io.IOException
1123                ("Row " + v.size() + " is too long.");
1124             row[j++] = Double.valueOf(tokenizer.sval).doubleValue();
1125          } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD);
1126          if (j < n) throw new java.io.IOException
1127             ("Row " + v.size() + " is too short.");
1128       }
1129       int m = v.size();  // Now we've got the number of rows.
1130       double[][] A = new double[m][];
1131       v.copyInto(A);  // copy the rows out of the vector
1132       return new Matrix(A);
1133    }
1134 
1135 
1136 /* ------------------------
1137    Private Methods
1138  * ------------------------ */
1139 
1140    /** Check if size(A) == size(B) **/
1141 
1142    private void checkMatrixDimensions (Matrix B) {
1143       if (B.m != m || B.n != n) {
1144          throw new IllegalArgumentException("Matrix dimensions must agree.");
1145       }
1146    }
1147 
1148 }