/* Matrix.java Author: Bryan Lewis Kent State University Department of Mathematics & Computer Science mail: blewis@mcs.kent.edu url: http://www.mcs.kent.edu/~blewis/ Matrix is a *lightweight* set of linear algebra algorithms that work on double precision (real) dense arrays. Efficiency is generally traded for compactness and ease of use. The small set of algorithms was selected for wide applicability, particularly in statistical applications. A nice parsing constructor can generate a matrix from flexibly formatted text input. Note that "Matrix" represents an arbitrary array class including row and column vectors. This software is public domain and can be used, modified and distributed freely. Needs the following objects: java.util.Vector, java.lang.Math, Numeric Changes: 01.June, 99: Added 'diag' routine 10.Oct., 98: Added appendCols, appendRows, flipud methods 25.Sept., 98: Modified sort algorithm to sort arrays by first column. 19.Sept., 98: Changed the arguments a little in the divide method. divide(b, A) returns b/A where A is a scalar or an invertible matrix. 17.Sept., 98: Fixed toString to use OS-indep. line termination 17.Sept., 98: Extensive syntax changes for a more Java-like interface. Deprecated a binary operation constructor and added static .add, .multiply, .divide, and .subtract methods. 17-Sept., 98: modified the static divide operation to solve a general dense linear system using QR. 30-March, 98: modified QR for non-square matrices 18-March, 98: added a method (leig) to *estimate* the largest eigenvalue of a matrix that has positive entries 15-August, 97: added a sum of squares function for statistical applications 21-July, 97: modified QR decomposition (minor improvement) 21-July, 97: added QR method that returns 'em both in a (Java) vector 21-July, 97: added backsolve constructor method A\v 26-April-97: added average and rank 25-April-97: added quicksort 9-March-97: added the toHess function to transform a matrix to Hessenberg form 5-March-97: added *crude* LR and QR eigenvalue methods. 3-March-97: added the permutation method permute() 27-Feb-97: added Householder-QR factorization method Q() 27-Feb-97: added the default norm() method 25-Feb-97: added the transpose method transpose() 11-June-97: added submatrix selection method Still to do: add exceptions */ import java.util.Vector; import java.lang.Math; public class Matrix { public int rows, columns; public double[][] element; // the array containing the matrix public Matrix() { // Create a zero 1x1 matrix rows = 1; columns = 1; element = new double[rows][columns]; } public Matrix(int r, int c) { // creates an empty r by c matrix rows = r; columns = c; element = new double[rows][columns]; } public Matrix(double d) { // creates a 1x1 matrix of double d rows = 1; columns = 1; element = new double[1][1]; element[0][0] = d; } public Matrix(int r, int c, double fill) { // creates an r by c matrix with entries 'fill' rows = r; columns = c; element = new double[rows][columns]; int i, j; for (i=0; i1){ k=0; j=i; } else{ k=i; j=0; } t.element[i][k] = this.element[i][j]; } return t; } public static Matrix add(Matrix m1, Matrix m2){ // Return the matrix m = m1 + m2 Matrix m=new Matrix(m1.rows,m1.columns); if ((m1.rows == m2.rows)&&(m1.columns==m2.columns)) { int i,j; for (i=0; i= 0) { sum = 0; j = m.rows-1; while(j>=i+1) { sum = sum + R.element[i][j]*m.element[j][0]; j--; } m.element[i][0] = (b.element[i][0]-sum)/R.element[i][i]; i--; } } return m; } public Matrix sub(int r1, int r2, int c1, int c2) { // returns the submatrix (r1:r2,c1:c2) (Moeler notation) // requires r2>=r1, c2>=c1 Matrix A = new Matrix(r2 - r1 + 1, c2 - c1 + 1); int i, j; for (i = r1; i<=r2; i++) { for (j = c1; j<=c2; j++) { A.element[i - r1][j - c1] = this.element[i][j]; } } return A; } public Matrix appendCols(Matrix x){ // append the column vectors in x to this matrix Matrix M=new Matrix(rows,columns+x.columns); int i,j; for(i=0;i m){ m = this.element[i][j]; } } } return m; } public double sum() { /* returns the sum of all the elements in the matrix or vector */ double s = 0; int i, j; for (i = 0; i0) { for (i = 0; i0) { for (i = 0; i0) { for (i = 0; i d) { // System.out.println(U.element[i][j] +", "+i); d = Math.abs(U.element[i][j]); p = i; } } if (p > j) { U = U.permute(j, p, 'r'); P = P.permute(j, p, 'r'); // don't forget to track permutations } // end of partial pivot code. for (i = j+1; i < rows; i++) { if (U.element[j][j]!=0) { G.element[i][j] = -U.element[i][j]/U.element[j][j]; } } U = multiply(G, U); L = L.permute(j, p, 'r'); for (k = 0; k < j; k++) { L.element[k][j] = 0; } L.element[j][j] = 1; for (k = j+1; k < rows; k++) { L.element[k][j] = -G.element[k][j]; G.element[k][j] = 0; } } for (k = 0; k < rows; k++) { L.element[k][columns-1] = 0; } L.element[rows-1][columns-1] = 1; v.addElement(P); v.addElement(L); v.addElement(U); return v; } public double leig(double p) { /* Elementary QR method method to find the spectral radius of a positive valued matrix. Parameter p = precision desired. For example, if A is a Matrix of positive real numbers, then A.leig(0.01) returns the largest eigenvalue to at least two digits of accuracy. */ Vector qr; Matrix Q = new Matrix(rows, columns); Matrix R = new Matrix(rows, columns); Matrix A = new Matrix(this); // initialized int i = 1; int maxIter = 200-this.rows; if(maxIter<25){maxIter=25;} // set up a maximum iteration count double v = 99; // temporary result double res = 99; // residual while((ip)) { qr = A.qr(); Q = (Matrix)qr.elementAt(1); R = (Matrix)qr.elementAt(0); A = multiply(R,Q); i++; res = Math.abs(A.element[0][0] - v); v = A.element[0][0]; } return A.element[0][0]; } public String toString(int d) { /*Return a string representation of this matrix with 'd' displayed digits*/ String newln = System.getProperty("line.separator"); String outPut = new String(); String num = new String(); int i, j; for (i=0; i 1) { // sort the array by the first column a = new double[rows]; // contains the data for sorting indx = new int[rows]; // index array for (i=0; i lo0) { mid = a[ ( lo0 + hi0 ) / 2 ]; while( lo <= hi ) { while( ( lo < hi0 ) && ( a[lo] < mid ) ) ++lo; while( ( hi > lo0 ) && ( a[hi] > mid ) ) --hi; if( lo <= hi ) { swap(a, lo, hi); swap(index, lo, hi); ++lo; --hi; } } if( lo0 < hi ) qsort( a,index, lo0, hi ); if( lo < hi0 ) qsort( a,index, lo, hi0 ); } } private void swap(double a[], int i, int j){ double T; T = a[i]; a[i] = a[j]; a[j] = T; } private void swap(int a[], int i, int j){ int T; T = a[i]; a[i] = a[j]; a[j] = T; } }