jama-1.0.3/ 0000775 0001750 0001750 00000000000 12201203453 011745 5 ustar ebourg ebourg jama-1.0.3/src/ 0000775 0001750 0001750 00000000000 12201203425 012533 5 ustar ebourg ebourg jama-1.0.3/src/Jama/ 0000755 0001750 0001750 00000000000 12201203453 013402 5 ustar ebourg ebourg jama-1.0.3/src/Jama/Matrix.java 0000600 0001750 0001750 00000070341 12047301256 015516 0 ustar ebourg ebourg package Jama; import java.text.NumberFormat; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import java.text.FieldPosition; import java.io.PrintWriter; import java.io.BufferedReader; import java.io.StreamTokenizer; import Jama.util.*; /** Jama = Java Matrix class.
The Java Matrix Class provides the fundamental operations of numerical linear algebra. Various constructors create Matrices from two dimensional arrays of double precision floating point numbers. Various "gets" and "sets" provide access to submatrices and matrix elements. Several methods implement basic matrix arithmetic, including matrix addition and multiplication, matrix norms, and element-by-element array operations. Methods for reading and printing matrices are also included. All the operations in this version of the Matrix Class involve real matrices. Complex matrices may be handled in a future version.
Five fundamental matrix decompositions, which consist of pairs or triples of matrices, permutation vectors, and the like, produce results in five decomposition classes. These decompositions are accessed by the Matrix class to compute solutions of simultaneous linear equations, determinants, inverses and other matrix functions. The five decompositions are:
double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}}; Matrix A = new Matrix(vals); Matrix b = Matrix.random(3,1); Matrix x = A.solve(b); Matrix r = A.times(x).minus(b); double rnorm = r.normInf();
For a symmetric, positive definite matrix A, the Cholesky decomposition is an lower triangular matrix L so that A = L*L'.
If the matrix is not symmetric or positive definite, the constructor returns a partial decomposition and sets an internal flag that may be queried by the isSPD() method. */ public class CholeskyDecomposition implements java.io.Serializable { /* ------------------------ Class variables * ------------------------ */ /** Array for internal storage of decomposition. @serial internal array storage. */ private double[][] L; /** Row and column dimension (square matrix). @serial matrix dimension. */ private int n; /** Symmetric and positive definite flag. @serial is symmetric and positive definite flag. */ private boolean isspd; /* ------------------------ Constructor * ------------------------ */ /** Cholesky algorithm for symmetric and positive definite matrix. Structure to access L and isspd flag. @param Arg Square, symmetric matrix. */ public CholeskyDecomposition (Matrix Arg) { // Initialize. double[][] A = Arg.getArray(); n = Arg.getRowDimension(); L = new double[n][n]; isspd = (Arg.getColumnDimension() == n); // Main loop. for (int j = 0; j < n; j++) { double[] Lrowj = L[j]; double d = 0.0; for (int k = 0; k < j; k++) { double[] Lrowk = L[k]; double s = 0.0; for (int i = 0; i < k; i++) { s += Lrowk[i]*Lrowj[i]; } Lrowj[k] = s = (A[j][k] - s)/L[k][k]; d = d + s*s; isspd = isspd & (A[k][j] == A[j][k]); } d = A[j][j] - d; isspd = isspd & (d > 0.0); L[j][j] = Math.sqrt(Math.max(d,0.0)); for (int k = j+1; k < n; k++) { L[j][k] = 0.0; } } } /* ------------------------ Temporary, experimental code. * ------------------------ *\ \** Right Triangular Cholesky Decomposition.
For a symmetric, positive definite matrix A, the Right Cholesky decomposition is an upper triangular matrix R so that A = R'*R. This constructor computes R with the Fortran inspired column oriented algorithm used in LINPACK and MATLAB. In Java, we suspect a row oriented, lower triangular decomposition is faster. We have temporarily included this constructor here until timing experiments confirm this suspicion. *\ \** Array for internal storage of right triangular decomposition. **\ private transient double[][] R; \** Cholesky algorithm for symmetric and positive definite matrix. @param A Square, symmetric matrix. @param rightflag Actual value ignored. @return Structure to access R and isspd flag. *\ public CholeskyDecomposition (Matrix Arg, int rightflag) { // Initialize. double[][] A = Arg.getArray(); n = Arg.getColumnDimension(); R = new double[n][n]; isspd = (Arg.getColumnDimension() == n); // Main loop. for (int j = 0; j < n; j++) { double d = 0.0; for (int k = 0; k < j; k++) { double s = A[k][j]; for (int i = 0; i < k; i++) { s = s - R[i][k]*R[i][j]; } R[k][j] = s = s/R[k][k]; d = d + s*s; isspd = isspd & (A[k][j] == A[j][k]); } d = A[j][j] - d; isspd = isspd & (d > 0.0); R[j][j] = Math.sqrt(Math.max(d,0.0)); for (int k = j+1; k < n; k++) { R[k][j] = 0.0; } } } \** Return upper triangular factor. @return R *\ public Matrix getR () { return new Matrix(R,n,n); } \* ------------------------ End of temporary code. * ------------------------ */ /* ------------------------ Public Methods * ------------------------ */ /** Is the matrix symmetric and positive definite? @return true if A is symmetric and positive definite. */ public boolean isSPD () { return isspd; } /** Return triangular factor. @return L */ public Matrix getL () { return new Matrix(L,n,n); } /** Solve A*X = B @param B A Matrix with as many rows as A and any number of columns. @return X so that L*L'*X = B @exception IllegalArgumentException Matrix row dimensions must agree. @exception RuntimeException Matrix is not symmetric positive definite. */ public Matrix solve (Matrix B) { if (B.getRowDimension() != n) { throw new IllegalArgumentException("Matrix row dimensions must agree."); } if (!isspd) { throw new RuntimeException("Matrix is not symmetric positive definite."); } // Copy right hand side. double[][] X = B.getArrayCopy(); int nx = B.getColumnDimension(); // Solve L*Y = B; for (int k = 0; k < n; k++) { for (int j = 0; j < nx; j++) { for (int i = 0; i < k ; i++) { X[k][j] -= X[i][j]*L[k][i]; } X[k][j] /= L[k][k]; } } // Solve L'*X = Y; for (int k = n-1; k >= 0; k--) { for (int j = 0; j < nx; j++) { for (int i = k+1; i < n ; i++) { X[k][j] -= X[i][j]*L[i][k]; } X[k][j] /= L[k][k]; } } return new Matrix(X,n,nx); } private static final long serialVersionUID = 1; } jama-1.0.3/src/Jama/QRDecomposition.java 0000600 0001750 0001750 00000013370 12047301326 017326 0 ustar ebourg ebourg package Jama; import Jama.util.*; /** QR Decomposition.
For an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n orthogonal matrix Q and an n-by-n upper triangular matrix R so that A = Q*R.
The QR decompostion always exists, even if the matrix does not have full rank, so the constructor will never fail. The primary use of the QR decomposition is in the least squares solution of nonsquare systems of simultaneous linear equations. This will fail if isFullRank() returns false. */ public class QRDecomposition implements java.io.Serializable { /* ------------------------ Class variables * ------------------------ */ /** Array for internal storage of decomposition. @serial internal array storage. */ private double[][] QR; /** Row and column dimensions. @serial column dimension. @serial row dimension. */ private int m, n; /** Array for internal storage of diagonal of R. @serial diagonal of R. */ private double[] Rdiag; /* ------------------------ Constructor * ------------------------ */ /** QR Decomposition, computed by Householder reflections. Structure to access R and the Householder vectors and compute Q. @param A Rectangular matrix */ public QRDecomposition (Matrix A) { // Initialize. QR = A.getArrayCopy(); m = A.getRowDimension(); n = A.getColumnDimension(); Rdiag = new double[n]; // Main loop. for (int k = 0; k < n; k++) { // Compute 2-norm of k-th column without under/overflow. double nrm = 0; for (int i = k; i < m; i++) { nrm = Maths.hypot(nrm,QR[i][k]); } if (nrm != 0.0) { // Form k-th Householder vector. if (QR[k][k] < 0) { nrm = -nrm; } for (int i = k; i < m; i++) { QR[i][k] /= nrm; } QR[k][k] += 1.0; // Apply transformation to remaining columns. for (int j = k+1; j < n; j++) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i][k]*QR[i][j]; } s = -s/QR[k][k]; for (int i = k; i < m; i++) { QR[i][j] += s*QR[i][k]; } } } Rdiag[k] = -nrm; } } /* ------------------------ Public Methods * ------------------------ */ /** Is the matrix full rank? @return true if R, and hence A, has full rank. */ public boolean isFullRank () { for (int j = 0; j < n; j++) { if (Rdiag[j] == 0) return false; } return true; } /** Return the Householder vectors @return Lower trapezoidal matrix whose columns define the reflections */ public Matrix getH () { Matrix X = new Matrix(m,n); double[][] H = X.getArray(); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (i >= j) { H[i][j] = QR[i][j]; } else { H[i][j] = 0.0; } } } return X; } /** Return the upper triangular factor @return R */ public Matrix getR () { Matrix X = new Matrix(n,n); double[][] R = X.getArray(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i < j) { R[i][j] = QR[i][j]; } else if (i == j) { R[i][j] = Rdiag[i]; } else { R[i][j] = 0.0; } } } return X; } /** Generate and return the (economy-sized) orthogonal factor @return Q */ public Matrix getQ () { Matrix X = new Matrix(m,n); double[][] Q = X.getArray(); for (int k = n-1; k >= 0; k--) { for (int i = 0; i < m; i++) { Q[i][k] = 0.0; } Q[k][k] = 1.0; for (int j = k; j < n; j++) { if (QR[k][k] != 0) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i][k]*Q[i][j]; } s = -s/QR[k][k]; for (int i = k; i < m; i++) { Q[i][j] += s*QR[i][k]; } } } } return X; } /** Least squares solution of A*X = B @param B A Matrix with as many rows as A and any number of columns. @return X that minimizes the two norm of Q*R*X-B. @exception IllegalArgumentException Matrix row dimensions must agree. @exception RuntimeException Matrix is rank deficient. */ public Matrix solve (Matrix B) { if (B.getRowDimension() != m) { throw new IllegalArgumentException("Matrix row dimensions must agree."); } if (!this.isFullRank()) { throw new RuntimeException("Matrix is rank deficient."); } // Copy right hand side int nx = B.getColumnDimension(); double[][] X = B.getArrayCopy(); // Compute Y = transpose(Q)*B for (int k = 0; k < n; k++) { for (int j = 0; j < nx; j++) { double s = 0.0; for (int i = k; i < m; i++) { s += QR[i][k]*X[i][j]; } s = -s/QR[k][k]; for (int i = k; i < m; i++) { X[i][j] += s*QR[i][k]; } } } // Solve R*X = Y; for (int k = n-1; k >= 0; k--) { for (int j = 0; j < nx; j++) { X[k][j] /= Rdiag[k]; } for (int i = 0; i < k; i++) { for (int j = 0; j < nx; j++) { X[i][j] -= X[k][j]*QR[i][k]; } } } return (new Matrix(X,n,nx).getMatrix(0,n-1,0,nx-1)); } private static final long serialVersionUID = 1; } jama-1.0.3/src/Jama/test/ 0000755 0001750 0001750 00000000000 12201202461 014357 5 ustar ebourg ebourg jama-1.0.3/src/Jama/test/TestMatrix.java 0000644 0001750 0001750 00000122354 12051250527 017346 0 ustar ebourg ebourg package Jama.test; import Jama.*; import java.io.*; import java.util.zip.GZIPInputStream; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; /** TestMatrix tests the functionality of the Jama Matrix class and associated decompositions.
Run the test from the command line using
Detailed output is provided indicating the functionality being tested and whether the functionality is correctly implemented. Exception handling is also tested.java Jama.test.TestMatrix
The test is designed to run to completion and give a summary of any implementation errors encountered. The final output should be:
If the test does not run to completion, this indicates that there is a substantial problem within the implementation that was not anticipated in the test design. The stopping point should give an indication of where the problem exists. **/ public class TestMatrix { public static void main (String argv[]) { Matrix A,B,C,Z,O,I,R,S,X,SUB,M,T,SQ,DEF,SOL; // Uncomment this to test IO in a different locale. // Locale.setDefault(Locale.GERMAN); int errorCount=0; int warningCount=0; double tmp, s; double[] columnwise = {1.,2.,3.,4.,5.,6.,7.,8.,9.,10.,11.,12.}; double[] rowwise = {1.,4.,7.,10.,2.,5.,8.,11.,3.,6.,9.,12.}; double[][] avals = {{1.,4.,7.,10.},{2.,5.,8.,11.},{3.,6.,9.,12.}}; double[][] rankdef = avals; double[][] tvals = {{1.,2.,3.},{4.,5.,6.},{7.,8.,9.},{10.,11.,12.}}; double[][] subavals = {{5.,8.,11.},{6.,9.,12.}}; double[][] rvals = {{1.,4.,7.},{2.,5.,8.,11.},{3.,6.,9.,12.}}; double[][] pvals = {{4.,1.,1.},{1.,2.,3.},{1.,3.,6.}}; double[][] ivals = {{1.,0.,0.,0.},{0.,1.,0.,0.},{0.,0.,1.,0.}}; double[][] evals = {{0.,1.,0.,0.},{1.,0.,2.e-7,0.},{0.,-2.e-7,0.,1.},{0.,0.,1.,0.}}; double[][] square = {{166.,188.,210.},{188.,214.,240.},{210.,240.,270.}}; double[][] sqSolution = {{13.},{15.}}; double[][] condmat = {{1.,3.},{7.,9.}}; double[][] badeigs = {{0,0,0,0,0}, {0,0,0,0,1},{0,0,0,1,0}, {1,1,0,0,1},{1,0,1,0,1}}; int rows=3,cols=4; int invalidld=5;/* should trigger bad shape for construction with val */ int raggedr=0; /* (raggedr,raggedc) should be out of bounds in ragged array */ int raggedc=4; int validld=3; /* leading dimension of intended test Matrices */ int nonconformld=4; /* leading dimension which is valid, but nonconforming */ int ib=1,ie=2,jb=1,je=3; /* index ranges for sub Matrix */ int[] rowindexset = {1,2}; int[] badrowindexset = {1,3}; int[] columnindexset = {1,2,3}; int[] badcolumnindexset = {1,2,4}; double columnsummax = 33.; double rowsummax = 30.; double sumofdiagonals = 15; double sumofsquares = 650; /** Constructors and constructor-like methods: double[], int double[][] int, int int, int, double int, int, double[][] constructWithCopy(double[][]) random(int,int) identity(int) **/ print("\nTesting constructors and constructor-like methods...\n"); try{ /** check that exception is thrown in packed constructor with invalid length **/ A = new Matrix(columnwise,invalidld); errorCount = try_failure(errorCount,"Catch invalid length in packed constructor... ", "exception not thrown for invalid input"); } catch ( IllegalArgumentException e ) { try_success("Catch invalid length in packed constructor... ", e.getMessage()); } try{ /** check that exception is thrown in default constructor if input array is 'ragged' **/ A = new Matrix(rvals); tmp = A.get(raggedr,raggedc); } catch ( IllegalArgumentException e ) { try_success("Catch ragged input to default constructor... ", e.getMessage()); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"Catch ragged input to constructor... ", "exception not thrown in construction...ArrayIndexOutOfBoundsException thrown later"); } try{ /** check that exception is thrown in constructWithCopy if input array is 'ragged' **/ A = Matrix.constructWithCopy(rvals); tmp = A.get(raggedr,raggedc); } catch ( IllegalArgumentException e ) { try_success("Catch ragged input to constructWithCopy... ",e.getMessage()); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"Catch ragged input to constructWithCopy... ","exception not thrown in construction...ArrayIndexOutOfBoundsException thrown later"); } A = new Matrix(columnwise,validld); B = new Matrix(avals); tmp = B.get(0,0); avals[0][0] = 0.0; C = B.minus(A); avals[0][0] = tmp; B = Matrix.constructWithCopy(avals); tmp = B.get(0,0); avals[0][0] = 0.0; if ( ( tmp - B.get(0,0) ) != 0.0 ) { /** check that constructWithCopy behaves properly **/ errorCount = try_failure(errorCount,"constructWithCopy... ","copy not effected... data visible outside"); } else { try_success("constructWithCopy... ",""); } avals[0][0] = columnwise[0]; I = new Matrix(ivals); try { check(I,Matrix.identity(3,4)); try_success("identity... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"identity... ","identity Matrix not successfully created"); } /** Access Methods: getColumnDimension() getRowDimension() getArray() getArrayCopy() getColumnPackedCopy() getRowPackedCopy() get(int,int) getMatrix(int,int,int,int) getMatrix(int,int,int[]) getMatrix(int[],int,int) getMatrix(int[],int[]) set(int,int,double) setMatrix(int,int,int,int,Matrix) setMatrix(int,int,int[],Matrix) setMatrix(int[],int,int,Matrix) setMatrix(int[],int[],Matrix) **/ print("\nTesting access methods...\n"); /** Various get methods: **/ B = new Matrix(avals); if (B.getRowDimension() != rows) { errorCount = try_failure(errorCount,"getRowDimension... ",""); } else { try_success("getRowDimension... ",""); } if (B.getColumnDimension() != cols) { errorCount = try_failure(errorCount,"getColumnDimension... ",""); } else { try_success("getColumnDimension... ",""); } B = new Matrix(avals); double[][] barray = B.getArray(); if ( barray != avals ) { errorCount = try_failure(errorCount,"getArray... ",""); } else { try_success("getArray... ",""); } barray = B.getArrayCopy(); if ( barray == avals ) { errorCount = try_failure(errorCount,"getArrayCopy... ","data not (deep) copied"); } try { check(barray,avals); try_success("getArrayCopy... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getArrayCopy... ","data not successfully (deep) copied"); } double[] bpacked = B.getColumnPackedCopy(); try { check(bpacked,columnwise); try_success("getColumnPackedCopy... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getColumnPackedCopy... ","data not successfully (deep) copied by columns"); } bpacked = B.getRowPackedCopy(); try { check(bpacked,rowwise); try_success("getRowPackedCopy... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getRowPackedCopy... ","data not successfully (deep) copied by rows"); } try { tmp = B.get(B.getRowDimension(),B.getColumnDimension()-1); errorCount = try_failure(errorCount,"get(int,int)... ","OutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { tmp = B.get(B.getRowDimension()-1,B.getColumnDimension()); errorCount = try_failure(errorCount,"get(int,int)... ","OutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("get(int,int)... OutofBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"get(int,int)... ","OutOfBoundsException expected but not thrown"); } try { if (B.get(B.getRowDimension()-1,B.getColumnDimension()-1) != avals[B.getRowDimension()-1][B.getColumnDimension()-1] ) { errorCount = try_failure(errorCount,"get(int,int)... ","Matrix entry (i,j) not successfully retreived"); } else { try_success("get(int,int)... ",""); } } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"get(int,int)... ","Unexpected ArrayIndexOutOfBoundsException"); } SUB = new Matrix(subavals); try { M = B.getMatrix(ib,ie+B.getRowDimension()+1,jb,je); errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { M = B.getMatrix(ib,ie,jb,je+B.getColumnDimension()+1); errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("getMatrix(int,int,int,int)... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { M = B.getMatrix(ib,ie,jb,je); try { check(SUB,M); try_success("getMatrix(int,int,int,int)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","submatrix not successfully retreived"); } } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"getMatrix(int,int,int,int)... ","Unexpected ArrayIndexOutOfBoundsException"); } try { M = B.getMatrix(ib,ie,badcolumnindexset); errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { M = B.getMatrix(ib,ie+B.getRowDimension()+1,columnindexset); errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("getMatrix(int,int,int[])... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { M = B.getMatrix(ib,ie,columnindexset); try { check(SUB,M); try_success("getMatrix(int,int,int[])... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","submatrix not successfully retreived"); } } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"getMatrix(int,int,int[])... ","Unexpected ArrayIndexOutOfBoundsException"); } try { M = B.getMatrix(badrowindexset,jb,je); errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { M = B.getMatrix(rowindexset,jb,je+B.getColumnDimension()+1); errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("getMatrix(int[],int,int)... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { M = B.getMatrix(rowindexset,jb,je); try { check(SUB,M); try_success("getMatrix(int[],int,int)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","submatrix not successfully retreived"); } } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"getMatrix(int[],int,int)... ","Unexpected ArrayIndexOutOfBoundsException"); } try { M = B.getMatrix(badrowindexset,columnindexset); errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { M = B.getMatrix(rowindexset,badcolumnindexset); errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("getMatrix(int[],int[])... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { M = B.getMatrix(rowindexset,columnindexset); try { check(SUB,M); try_success("getMatrix(int[],int[])... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","submatrix not successfully retreived"); } } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { errorCount = try_failure(errorCount,"getMatrix(int[],int[])... ","Unexpected ArrayIndexOutOfBoundsException"); } /** Various set methods: **/ try { B.set(B.getRowDimension(),B.getColumnDimension()-1,0.); errorCount = try_failure(errorCount,"set(int,int,double)... ","OutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { B.set(B.getRowDimension()-1,B.getColumnDimension(),0.); errorCount = try_failure(errorCount,"set(int,int,double)... ","OutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("set(int,int,double)... OutofBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"set(int,int,double)... ","OutOfBoundsException expected but not thrown"); } try { B.set(ib,jb,0.); tmp = B.get(ib,jb); try { check(tmp,0.); try_success("set(int,int,double)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"set(int,int,double)... ","Matrix element not successfully set"); } } catch ( java.lang.ArrayIndexOutOfBoundsException e1) { errorCount = try_failure(errorCount,"set(int,int,double)... ","Unexpected ArrayIndexOutOfBoundsException"); } M = new Matrix(2,3,0.); try { B.setMatrix(ib,ie+B.getRowDimension()+1,jb,je,M); errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { B.setMatrix(ib,ie,jb,je+B.getColumnDimension()+1,M); errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("setMatrix(int,int,int,int,Matrix)... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { B.setMatrix(ib,ie,jb,je,M); try { check(M.minus(B.getMatrix(ib,ie,jb,je)),M); try_success("setMatrix(int,int,int,int,Matrix)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","submatrix not successfully set"); } B.setMatrix(ib,ie,jb,je,SUB); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int,int,int,int,Matrix)... ","Unexpected ArrayIndexOutOfBoundsException"); } try { B.setMatrix(ib,ie+B.getRowDimension()+1,columnindexset,M); errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { B.setMatrix(ib,ie,badcolumnindexset,M); errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("setMatrix(int,int,int[],Matrix)... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { B.setMatrix(ib,ie,columnindexset,M); try { check(M.minus(B.getMatrix(ib,ie,columnindexset)),M); try_success("setMatrix(int,int,int[],Matrix)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","submatrix not successfully set"); } B.setMatrix(ib,ie,jb,je,SUB); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int,int,int[],Matrix)... ","Unexpected ArrayIndexOutOfBoundsException"); } try { B.setMatrix(rowindexset,jb,je+B.getColumnDimension()+1,M); errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { B.setMatrix(badrowindexset,jb,je,M); errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("setMatrix(int[],int,int,Matrix)... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { B.setMatrix(rowindexset,jb,je,M); try { check(M.minus(B.getMatrix(rowindexset,jb,je)),M); try_success("setMatrix(int[],int,int,Matrix)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","submatrix not successfully set"); } B.setMatrix(ib,ie,jb,je,SUB); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int[],int,int,Matrix)... ","Unexpected ArrayIndexOutOfBoundsException"); } try { B.setMatrix(rowindexset,badcolumnindexset,M); errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e ) { try { B.setMatrix(badrowindexset,columnindexset,M); errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { try_success("setMatrix(int[],int[],Matrix)... ArrayIndexOutOfBoundsException... ",""); } } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","ArrayIndexOutOfBoundsException expected but not thrown"); } try { B.setMatrix(rowindexset,columnindexset,M); try { check(M.minus(B.getMatrix(rowindexset,columnindexset)),M); try_success("setMatrix(int[],int[],Matrix)... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","submatrix not successfully set"); } } catch ( java.lang.ArrayIndexOutOfBoundsException e1 ) { errorCount = try_failure(errorCount,"setMatrix(int[],int[],Matrix)... ","Unexpected ArrayIndexOutOfBoundsException"); } /** Array-like methods: minus minusEquals plus plusEquals arrayLeftDivide arrayLeftDivideEquals arrayRightDivide arrayRightDivideEquals arrayTimes arrayTimesEquals uminus **/ print("\nTesting array-like methods...\n"); S = new Matrix(columnwise,nonconformld); R = Matrix.random(A.getRowDimension(),A.getColumnDimension()); A = R; try { S = A.minus(S); errorCount = try_failure(errorCount,"minus conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("minus conformance check... ",""); } if (A.minus(R).norm1() != 0.) { errorCount = try_failure(errorCount,"minus... ","(difference of identical Matrices is nonzero,\nSubsequent use of minus should be suspect)"); } else { try_success("minus... ",""); } A = R.copy(); A.minusEquals(R); Z = new Matrix(A.getRowDimension(),A.getColumnDimension()); try { A.minusEquals(S); errorCount = try_failure(errorCount,"minusEquals conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("minusEquals conformance check... ",""); } if (A.minus(Z).norm1() != 0.) { errorCount = try_failure(errorCount,"minusEquals... ","(difference of identical Matrices is nonzero,\nSubsequent use of minus should be suspect)"); } else { try_success("minusEquals... ",""); } A = R.copy(); B = Matrix.random(A.getRowDimension(),A.getColumnDimension()); C = A.minus(B); try { S = A.plus(S); errorCount = try_failure(errorCount,"plus conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("plus conformance check... ",""); } try { check(C.plus(B),A); try_success("plus... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"plus... ","(C = A - B, but C + B != A)"); } C = A.minus(B); C.plusEquals(B); try { A.plusEquals(S); errorCount = try_failure(errorCount,"plusEquals conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("plusEquals conformance check... ",""); } try { check(C,A); try_success("plusEquals... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"plusEquals... ","(C = A - B, but C = C + B != A)"); } A = R.uminus(); try { check(A.plus(R),Z); try_success("uminus... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"uminus... ","(-A + A != zeros)"); } A = R.copy(); O = new Matrix(A.getRowDimension(),A.getColumnDimension(),1.0); C = A.arrayLeftDivide(R); try { S = A.arrayLeftDivide(S); errorCount = try_failure(errorCount,"arrayLeftDivide conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("arrayLeftDivide conformance check... ",""); } try { check(C,O); try_success("arrayLeftDivide... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"arrayLeftDivide... ","(M.\\M != ones)"); } try { A.arrayLeftDivideEquals(S); errorCount = try_failure(errorCount,"arrayLeftDivideEquals conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("arrayLeftDivideEquals conformance check... ",""); } A.arrayLeftDivideEquals(R); try { check(A,O); try_success("arrayLeftDivideEquals... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"arrayLeftDivideEquals... ","(M.\\M != ones)"); } A = R.copy(); try { A.arrayRightDivide(S); errorCount = try_failure(errorCount,"arrayRightDivide conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("arrayRightDivide conformance check... ",""); } C = A.arrayRightDivide(R); try { check(C,O); try_success("arrayRightDivide... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"arrayRightDivide... ","(M./M != ones)"); } try { A.arrayRightDivideEquals(S); errorCount = try_failure(errorCount,"arrayRightDivideEquals conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("arrayRightDivideEquals conformance check... ",""); } A.arrayRightDivideEquals(R); try { check(A,O); try_success("arrayRightDivideEquals... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"arrayRightDivideEquals... ","(M./M != ones)"); } A = R.copy(); B = Matrix.random(A.getRowDimension(),A.getColumnDimension()); try { S = A.arrayTimes(S); errorCount = try_failure(errorCount,"arrayTimes conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("arrayTimes conformance check... ",""); } C = A.arrayTimes(B); try { check(C.arrayRightDivideEquals(B),A); try_success("arrayTimes... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"arrayTimes... ","(A = R, C = A.*B, but C./B != A)"); } try { A.arrayTimesEquals(S); errorCount = try_failure(errorCount,"arrayTimesEquals conformance check... ","nonconformance not raised"); } catch ( IllegalArgumentException e ) { try_success("arrayTimesEquals conformance check... ",""); } A.arrayTimesEquals(B); try { check(A.arrayRightDivideEquals(B),R); try_success("arrayTimesEquals... ",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"arrayTimesEquals... ","(A = R, A = A.*B, but A./B != R)"); } /** I/O methods: read print serializable: writeObject readObject **/ print("\nTesting I/O methods...\n"); try { DecimalFormat fmt = new DecimalFormat("0.0000E00"); fmt.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US)); PrintWriter FILE = new PrintWriter(new FileOutputStream("JamaTestMatrix.out")); A.print(FILE,fmt,10); FILE.close(); R = Matrix.read(new BufferedReader(new FileReader("JamaTestMatrix.out"))); if (A.minus(R).norm1() < .001 ) { try_success("print()/read()...",""); } else { errorCount = try_failure(errorCount,"print()/read()...","Matrix read from file does not match Matrix printed to file"); } } catch ( java.io.IOException ioe ) { warningCount = try_warning(warningCount,"print()/read()...","unexpected I/O error, unable to run print/read test; check write permission in current directory and retry"); } catch(Exception e) { try { e.printStackTrace(System.out); warningCount = try_warning(warningCount,"print()/read()...","Formatting error... will try JDK1.1 reformulation..."); DecimalFormat fmt = new DecimalFormat("0.0000"); PrintWriter FILE = new PrintWriter(new FileOutputStream("JamaTestMatrix.out")); A.print(FILE,fmt,10); FILE.close(); R = Matrix.read(new BufferedReader(new FileReader("JamaTestMatrix.out"))); if (A.minus(R).norm1() < .001 ) { try_success("print()/read()...",""); } else { errorCount = try_failure(errorCount,"print()/read() (2nd attempt) ...","Matrix read from file does not match Matrix printed to file"); } } catch ( java.io.IOException ioe ) { warningCount = try_warning(warningCount,"print()/read()...","unexpected I/O error, unable to run print/read test; check write permission in current directory and retry"); } } R = Matrix.random(A.getRowDimension(),A.getColumnDimension()); String tmpname = "TMPMATRIX.serial"; try { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(tmpname)); out.writeObject(R); ObjectInputStream sin = new ObjectInputStream(new FileInputStream(tmpname)); A = (Matrix) sin.readObject(); try { check(A,R); try_success("writeObject(Matrix)/readObject(Matrix)...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"writeObject(Matrix)/readObject(Matrix)...","Matrix not serialized correctly"); } } catch ( java.io.IOException ioe ) { warningCount = try_warning(warningCount,"writeObject()/readObject()...","unexpected I/O error, unable to run serialization test; check write permission in current directory and retry"); } catch(Exception e) { errorCount = try_failure(errorCount,"writeObject(Matrix)/readObject(Matrix)...","unexpected error in serialization test"); } /** LA methods: transpose times cond rank det trace norm1 norm2 normF normInf solve solveTranspose inverse chol eig lu qr svd **/ print("\nTesting linear algebra methods...\n"); A = new Matrix(columnwise,3); T = new Matrix(tvals); T = A.transpose(); try { check(A.transpose(),T); try_success("transpose...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"transpose()...","transpose unsuccessful"); } A.transpose(); try { check(A.norm1(),columnsummax); try_success("norm1...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"norm1()...","incorrect norm calculation"); } try { check(A.normInf(),rowsummax); try_success("normInf()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"normInf()...","incorrect norm calculation"); } try { check(A.normF(),Math.sqrt(sumofsquares)); try_success("normF...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"normF()...","incorrect norm calculation"); } try { check(A.trace(),sumofdiagonals); try_success("trace()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"trace()...","incorrect trace calculation"); } try { check(A.getMatrix(0,A.getRowDimension()-1,0,A.getRowDimension()-1).det(),0.); try_success("det()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"det()...","incorrect determinant calculation"); } SQ = new Matrix(square); try { check(A.times(A.transpose()),SQ); try_success("times(Matrix)...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"times(Matrix)...","incorrect Matrix-Matrix product calculation"); } try { check(A.times(0.),Z); try_success("times(double)...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"times(double)...","incorrect Matrix-scalar product calculation"); } A = new Matrix(columnwise,4); QRDecomposition QR = A.qr(); R = QR.getR(); try { check(A,QR.getQ().times(R)); try_success("QRDecomposition...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"QRDecomposition...","incorrect QR decomposition calculation"); } SingularValueDecomposition SVD = A.svd(); try { check(A,SVD.getU().times(SVD.getS().times(SVD.getV().transpose()))); try_success("SingularValueDecomposition...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"SingularValueDecomposition...","incorrect singular value decomposition calculation"); } DEF = new Matrix(rankdef); try { check(DEF.rank(),Math.min(DEF.getRowDimension(),DEF.getColumnDimension())-1); try_success("rank()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"rank()...","incorrect rank calculation"); } B = new Matrix(condmat); SVD = B.svd(); double [] singularvalues = SVD.getSingularValues(); try { check(B.cond(),singularvalues[0]/singularvalues[Math.min(B.getRowDimension(),B.getColumnDimension())-1]); try_success("cond()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"cond()...","incorrect condition number calculation"); } int n = A.getColumnDimension(); A = A.getMatrix(0,n-1,0,n-1); A.set(0,0,0.); LUDecomposition LU = A.lu(); try { check(A.getMatrix(LU.getPivot(),0,n-1),LU.getL().times(LU.getU())); try_success("LUDecomposition...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"LUDecomposition...","incorrect LU decomposition calculation"); } X = A.inverse(); try { check(A.times(X),Matrix.identity(3,3)); try_success("inverse()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"inverse()...","incorrect inverse calculation"); } O = new Matrix(SUB.getRowDimension(),1,1.0); SOL = new Matrix(sqSolution); SQ = SUB.getMatrix(0,SUB.getRowDimension()-1,0,SUB.getRowDimension()-1); try { check(SQ.solve(SOL),O); try_success("solve()...",""); } catch ( java.lang.IllegalArgumentException e1 ) { errorCount = try_failure(errorCount,"solve()...",e1.getMessage()); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"solve()...",e.getMessage()); } A = new Matrix(pvals); CholeskyDecomposition Chol = A.chol(); Matrix L = Chol.getL(); try { check(A,L.times(L.transpose())); try_success("CholeskyDecomposition...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"CholeskyDecomposition...","incorrect Cholesky decomposition calculation"); } X = Chol.solve(Matrix.identity(3,3)); try { check(A.times(X),Matrix.identity(3,3)); try_success("CholeskyDecomposition solve()...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"CholeskyDecomposition solve()...","incorrect Choleskydecomposition solve calculation"); } EigenvalueDecomposition Eig = A.eig(); Matrix D = Eig.getD(); Matrix V = Eig.getV(); try { check(A.times(V),V.times(D)); try_success("EigenvalueDecomposition (symmetric)...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"EigenvalueDecomposition (symmetric)...","incorrect symmetric Eigenvalue decomposition calculation"); } A = new Matrix(evals); Eig = A.eig(); D = Eig.getD(); V = Eig.getV(); try { check(A.times(V),V.times(D)); try_success("EigenvalueDecomposition (nonsymmetric)...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"EigenvalueDecomposition (nonsymmetric)...","incorrect nonsymmetric Eigenvalue decomposition calculation"); } try { print("\nTesting Eigenvalue; If this hangs, we've failed\n"); Matrix bA = new Matrix(badeigs); EigenvalueDecomposition bEig = bA.eig(); try_success("EigenvalueDecomposition (hang)...",""); } catch ( java.lang.RuntimeException e ) { errorCount = try_failure(errorCount,"EigenvalueDecomposition (hang)...", "incorrect termination"); } print("\nTestMatrix completed.\n"); print("Total errors reported: " + Integer.toString(errorCount) + "\n"); print("Total warnings reported: " + Integer.toString(warningCount) + "\n"); } /** private utility routines **/ /** Check magnitude of difference of scalars. **/ private static void check(double x, double y) { double eps = Math.pow(2.0,-52.0); if (x == 0 & Math.abs(y) < 10*eps) return; if (y == 0 & Math.abs(x) < 10*eps) return; if (Math.abs(x-y) > 10*eps*Math.max(Math.abs(x),Math.abs(y))) { throw new RuntimeException("The difference x-y is too large: x = " + Double.toString(x) + " y = " + Double.toString(y)); } } /** Check norm of difference of "vectors". **/ private static void check(double[] x, double[] y) { if (x.length == y.length ) { for (int i=0;iTestMatrix completed. Total errors reported: n1 Total warning reported: n2
For an m-by-n matrix A with m >= n, the singular value decomposition is an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and an n-by-n orthogonal matrix V so that A = U*S*V'.
The singular values, sigma[k] = S[k][k], are ordered so that sigma[0] >= sigma[1] >= ... >= sigma[n-1].
The singular value decompostion always exists, so the constructor will
never fail. The matrix condition number and the effective numerical
rank can be computed from this decomposition.
*/
public class SingularValueDecomposition implements java.io.Serializable {
/* ------------------------
Class variables
* ------------------------ */
/** Arrays for internal storage of U and V.
@serial internal storage of U.
@serial internal storage of V.
*/
private double[][] U, V;
/** Array for internal storage of singular values.
@serial internal storage of singular values.
*/
private double[] s;
/** Row and column dimensions.
@serial row dimension.
@serial column dimension.
*/
private int m, n;
/* ------------------------
Constructor
* ------------------------ */
/** Construct the singular value decomposition
Structure to access U, S and V.
@param Arg Rectangular matrix
*/
public SingularValueDecomposition (Matrix Arg) {
// Derived from LINPACK code.
// Initialize.
double[][] A = Arg.getArrayCopy();
m = Arg.getRowDimension();
n = Arg.getColumnDimension();
/* Apparently the failing cases are only a proper subset of (m = -1; k--) {
if (k == -1) {
break;
}
if (Math.abs(e[k]) <=
tiny + eps*(Math.abs(s[k]) + Math.abs(s[k+1]))) {
e[k] = 0.0;
break;
}
}
if (k == p-2) {
kase = 4;
} else {
int ks;
for (ks = p-1; ks >= k; ks--) {
if (ks == k) {
break;
}
double t = (ks != p ? Math.abs(e[ks]) : 0.) +
(ks != k+1 ? Math.abs(e[ks-1]) : 0.);
if (Math.abs(s[ks]) <= tiny + eps*t) {
s[ks] = 0.0;
break;
}
}
if (ks == k) {
kase = 3;
} else if (ks == p-1) {
kase = 1;
} else {
kase = 2;
k = ks;
}
}
k++;
// Perform the task indicated by kase.
switch (kase) {
// Deflate negligible s(p).
case 1: {
double f = e[p-2];
e[p-2] = 0.0;
for (int j = p-2; j >= k; j--) {
double t = Maths.hypot(s[j],f);
double cs = s[j]/t;
double sn = f/t;
s[j] = t;
if (j != k) {
f = -sn*e[j-1];
e[j-1] = cs*e[j-1];
}
if (wantv) {
for (int i = 0; i < n; i++) {
t = cs*V[i][j] + sn*V[i][p-1];
V[i][p-1] = -sn*V[i][j] + cs*V[i][p-1];
V[i][j] = t;
}
}
}
}
break;
// Split at negligible s(k).
case 2: {
double f = e[k-1];
e[k-1] = 0.0;
for (int j = k; j < p; j++) {
double t = Maths.hypot(s[j],f);
double cs = s[j]/t;
double sn = f/t;
s[j] = t;
f = -sn*e[j];
e[j] = cs*e[j];
if (wantu) {
for (int i = 0; i < m; i++) {
t = cs*U[i][j] + sn*U[i][k-1];
U[i][k-1] = -sn*U[i][j] + cs*U[i][k-1];
U[i][j] = t;
}
}
}
}
break;
// Perform one qr step.
case 3: {
// Calculate the shift.
double scale = Math.max(Math.max(Math.max(Math.max(
Math.abs(s[p-1]),Math.abs(s[p-2])),Math.abs(e[p-2])),
Math.abs(s[k])),Math.abs(e[k]));
double sp = s[p-1]/scale;
double spm1 = s[p-2]/scale;
double epm1 = e[p-2]/scale;
double sk = s[k]/scale;
double ek = e[k]/scale;
double b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
double c = (sp*epm1)*(sp*epm1);
double shift = 0.0;
if ((b != 0.0) | (c != 0.0)) {
shift = Math.sqrt(b*b + c);
if (b < 0.0) {
shift = -shift;
}
shift = c/(b + shift);
}
double f = (sk + sp)*(sk - sp) + shift;
double g = sk*ek;
// Chase zeros.
for (int j = k; j < p-1; j++) {
double t = Maths.hypot(f,g);
double cs = f/t;
double sn = g/t;
if (j != k) {
e[j-1] = t;
}
f = cs*s[j] + sn*e[j];
e[j] = cs*e[j] - sn*s[j];
g = sn*s[j+1];
s[j+1] = cs*s[j+1];
if (wantv) {
for (int i = 0; i < n; i++) {
t = cs*V[i][j] + sn*V[i][j+1];
V[i][j+1] = -sn*V[i][j] + cs*V[i][j+1];
V[i][j] = t;
}
}
t = Maths.hypot(f,g);
cs = f/t;
sn = g/t;
s[j] = t;
f = cs*e[j] + sn*s[j+1];
s[j+1] = -sn*e[j] + cs*s[j+1];
g = sn*e[j+1];
e[j+1] = cs*e[j+1];
if (wantu && (j < m-1)) {
for (int i = 0; i < m; i++) {
t = cs*U[i][j] + sn*U[i][j+1];
U[i][j+1] = -sn*U[i][j] + cs*U[i][j+1];
U[i][j] = t;
}
}
}
e[p-2] = f;
iter = iter + 1;
}
break;
// Convergence.
case 4: {
// Make the singular values positive.
if (s[k] <= 0.0) {
s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
if (wantv) {
for (int i = 0; i <= pp; i++) {
V[i][k] = -V[i][k];
}
}
}
// Order the singular values.
while (k < pp) {
if (s[k] >= s[k+1]) {
break;
}
double t = s[k];
s[k] = s[k+1];
s[k+1] = t;
if (wantv && (k < n-1)) {
for (int i = 0; i < n; i++) {
t = V[i][k+1]; V[i][k+1] = V[i][k]; V[i][k] = t;
}
}
if (wantu && (k < m-1)) {
for (int i = 0; i < m; i++) {
t = U[i][k+1]; U[i][k+1] = U[i][k]; U[i][k] = t;
}
}
k++;
}
iter = 0;
p--;
}
break;
}
}
}
/* ------------------------
Public Methods
* ------------------------ */
/** Return the left singular vectors
@return U
*/
public Matrix getU () {
return new Matrix(U,m,Math.min(m+1,n));
}
/** Return the right singular vectors
@return V
*/
public Matrix getV () {
return new Matrix(V,n,n);
}
/** Return the one-dimensional array of singular values
@return diagonal of S.
*/
public double[] getSingularValues () {
return s;
}
/** Return the diagonal matrix of singular values
@return S
*/
public Matrix getS () {
Matrix X = new Matrix(n,n);
double[][] S = X.getArray();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
S[i][j] = 0.0;
}
S[i][i] = this.s[i];
}
return X;
}
/** Two norm
@return max(S)
*/
public double norm2 () {
return s[0];
}
/** Two norm condition number
@return max(S)/min(S)
*/
public double cond () {
return s[0]/s[Math.min(m,n)-1];
}
/** Effective numerical matrix rank
@return Number of nonnegligible singular values.
*/
public int rank () {
double eps = Math.pow(2.0,-52.0);
double tol = Math.max(m,n)*s[0]*eps;
int r = 0;
for (int i = 0; i < s.length; i++) {
if (s[i] > tol) {
r++;
}
}
return r;
}
private static final long serialVersionUID = 1;
}
jama-1.0.3/src/Jama/examples/ 0000755 0001750 0001750 00000000000 12201202461 015216 5 ustar ebourg ebourg jama-1.0.3/src/Jama/examples/MagicSquareExample.java 0000644 0001750 0001750 00000011673 06560231612 021621 0 ustar ebourg ebourg package Jama.examples;
import Jama.*;
import java.util.Date;
/** Example of use of Matrix Class, featuring magic squares. **/
public class MagicSquareExample {
/** Generate magic square test matrix. **/
public static Matrix magic (int n) {
double[][] M = new double[n][n];
// Odd order
if ((n % 2) == 1) {
int a = (n+1)/2;
int b = (n+1);
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
M[i][j] = n*((i+j+a) % n) + ((i+2*j+b) % n) + 1;
}
}
// Doubly Even Order
} else if ((n % 4) == 0) {
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
if (((i+1)/2)%2 == ((j+1)/2)%2) {
M[i][j] = n*n-n*i-j;
} else {
M[i][j] = n*i+j+1;
}
}
}
// Singly Even Order
} else {
int p = n/2;
int k = (n-2)/4;
Matrix A = magic(p);
for (int j = 0; j < p; j++) {
for (int i = 0; i < p; i++) {
double aij = A.get(i,j);
M[i][j] = aij;
M[i][j+p] = aij + 2*p*p;
M[i+p][j] = aij + 3*p*p;
M[i+p][j+p] = aij + p*p;
}
}
for (int i = 0; i < p; i++) {
for (int j = 0; j < k; j++) {
double t = M[i][j]; M[i][j] = M[i+p][j]; M[i+p][j] = t;
}
for (int j = n-k+1; j < n; j++) {
double t = M[i][j]; M[i][j] = M[i+p][j]; M[i+p][j] = t;
}
}
double t = M[k][0]; M[k][0] = M[k+p][0]; M[k+p][0] = t;
t = M[k][k]; M[k][k] = M[k+p][k]; M[k+p][k] = t;
}
return new Matrix(M);
}
/** Shorten spelling of print. **/
private static void print (String s) {
System.out.print(s);
}
/** Format double with Fw.d. **/
public static String fixedWidthDoubletoString (double x, int w, int d) {
java.text.DecimalFormat fmt = new java.text.DecimalFormat();
fmt.setMaximumFractionDigits(d);
fmt.setMinimumFractionDigits(d);
fmt.setGroupingUsed(false);
String s = fmt.format(x);
while (s.length() < w) {
s = " " + s;
}
return s;
}
/** Format integer with Iw. **/
public static String fixedWidthIntegertoString (int n, int w) {
String s = Integer.toString(n);
while (s.length() < w) {
s = " " + s;
}
return s;
}
public static void main (String argv[]) {
/*
| Tests LU, QR, SVD and symmetric Eig decompositions.
|
| n = order of magic square.
| trace = diagonal sum, should be the magic sum, (n^3 + n)/2.
| max_eig = maximum eigenvalue of (A + A')/2, should equal trace.
| rank = linear algebraic rank,
| should equal n if n is odd, be less than n if n is even.
| cond = L_2 condition number, ratio of singular values.
| lu_res = test of LU factorization, norm1(L*U-A(p,:))/(n*eps).
| qr_res = test of QR factorization, norm1(Q*R-A)/(n*eps).
*/
print("\n Test of Matrix Class, using magic squares.\n");
print(" See MagicSquareExample.main() for an explanation.\n");
print("\n n trace max_eig rank cond lu_res qr_res\n\n");
Date start_time = new Date();
double eps = Math.pow(2.0,-52.0);
for (int n = 3; n <= 32; n++) {
print(fixedWidthIntegertoString(n,7));
Matrix M = magic(n);
int t = (int) M.trace();
print(fixedWidthIntegertoString(t,10));
EigenvalueDecomposition E =
new EigenvalueDecomposition(M.plus(M.transpose()).times(0.5));
double[] d = E.getRealEigenvalues();
print(fixedWidthDoubletoString(d[n-1],14,3));
int r = M.rank();
print(fixedWidthIntegertoString(r,7));
double c = M.cond();
print(c < 1/eps ? fixedWidthDoubletoString(c,12,3) :
" Inf");
LUDecomposition LU = new LUDecomposition(M);
Matrix L = LU.getL();
Matrix U = LU.getU();
int[] p = LU.getPivot();
Matrix R = L.times(U).minus(M.getMatrix(p,0,n-1));
double res = R.norm1()/(n*eps);
print(fixedWidthDoubletoString(res,12,3));
QRDecomposition QR = new QRDecomposition(M);
Matrix Q = QR.getQ();
R = QR.getR();
R = Q.times(R).minus(M);
res = R.norm1()/(n*eps);
print(fixedWidthDoubletoString(res,12,3));
print("\n");
}
Date stop_time = new Date();
double etime = (stop_time.getTime() - start_time.getTime())/1000.;
print("\nElapsed Time = " +
fixedWidthDoubletoString(etime,12,3) + " seconds\n");
print("Adios\n");
}
}
jama-1.0.3/src/Jama/EigenvalueDecomposition.java 0000644 0001750 0001750 00000064271 12047301052 021102 0 ustar ebourg ebourg package Jama;
import Jama.util.*;
/** Eigenvalues and eigenvectors of a real matrix.
If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is
diagonal and the eigenvector matrix V is orthogonal.
I.e. A = V.times(D.times(V.transpose())) and
V.times(V.transpose()) equals the identity matrix.
If A is not symmetric, then the eigenvalue matrix D is block diagonal
with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
lambda + i*mu, in 2-by-2 blocks, [lambda, mu; -mu, lambda]. The
columns of V represent the eigenvectors in the sense that A*V = V*D,
i.e. A.times(V) equals V.times(D). The matrix V may be badly
conditioned, or even singular, so the validity of the equation
A = V*D*inverse(V) depends upon V.cond().
**/
public class EigenvalueDecomposition implements java.io.Serializable {
/* ------------------------
Class variables
* ------------------------ */
/** Row and column dimension (square matrix).
@serial matrix dimension.
*/
private int n;
/** Symmetry flag.
@serial internal symmetry flag.
*/
private boolean issymmetric;
/** Arrays for internal storage of eigenvalues.
@serial internal storage of eigenvalues.
*/
private double[] d, e;
/** Array for internal storage of eigenvectors.
@serial internal storage of eigenvectors.
*/
private double[][] V;
/** Array for internal storage of nonsymmetric Hessenberg form.
@serial internal storage of nonsymmetric Hessenberg form.
*/
private double[][] H;
/** Working storage for nonsymmetric algorithm.
@serial working storage for nonsymmetric algorithm.
*/
private double[] ort;
/* ------------------------
Private Methods
* ------------------------ */
// Symmetric Householder reduction to tridiagonal form.
private void tred2 () {
// This is derived from the Algol procedures tred2 by
// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
for (int j = 0; j < n; j++) {
d[j] = V[n-1][j];
}
// Householder reduction to tridiagonal form.
for (int i = n-1; i > 0; i--) {
// Scale to avoid under/overflow.
double scale = 0.0;
double h = 0.0;
for (int k = 0; k < i; k++) {
scale = scale + Math.abs(d[k]);
}
if (scale == 0.0) {
e[i] = d[i-1];
for (int j = 0; j < i; j++) {
d[j] = V[i-1][j];
V[i][j] = 0.0;
V[j][i] = 0.0;
}
} else {
// Generate Householder vector.
for (int k = 0; k < i; k++) {
d[k] /= scale;
h += d[k] * d[k];
}
double f = d[i-1];
double g = Math.sqrt(h);
if (f > 0) {
g = -g;
}
e[i] = scale * g;
h = h - f * g;
d[i-1] = f - g;
for (int j = 0; j < i; j++) {
e[j] = 0.0;
}
// Apply similarity transformation to remaining columns.
for (int j = 0; j < i; j++) {
f = d[j];
V[j][i] = f;
g = e[j] + V[j][j] * f;
for (int k = j+1; k <= i-1; k++) {
g += V[k][j] * d[k];
e[k] += V[k][j] * f;
}
e[j] = g;
}
f = 0.0;
for (int j = 0; j < i; j++) {
e[j] /= h;
f += e[j] * d[j];
}
double hh = f / (h + h);
for (int j = 0; j < i; j++) {
e[j] -= hh * d[j];
}
for (int j = 0; j < i; j++) {
f = d[j];
g = e[j];
for (int k = j; k <= i-1; k++) {
V[k][j] -= (f * e[k] + g * d[k]);
}
d[j] = V[i-1][j];
V[i][j] = 0.0;
}
}
d[i] = h;
}
// Accumulate transformations.
for (int i = 0; i < n-1; i++) {
V[n-1][i] = V[i][i];
V[i][i] = 1.0;
double h = d[i+1];
if (h != 0.0) {
for (int k = 0; k <= i; k++) {
d[k] = V[k][i+1] / h;
}
for (int j = 0; j <= i; j++) {
double g = 0.0;
for (int k = 0; k <= i; k++) {
g += V[k][i+1] * V[k][j];
}
for (int k = 0; k <= i; k++) {
V[k][j] -= g * d[k];
}
}
}
for (int k = 0; k <= i; k++) {
V[k][i+1] = 0.0;
}
}
for (int j = 0; j < n; j++) {
d[j] = V[n-1][j];
V[n-1][j] = 0.0;
}
V[n-1][n-1] = 1.0;
e[0] = 0.0;
}
// Symmetric tridiagonal QL algorithm.
private void tql2 () {
// This is derived from the Algol procedures tql2, by
// Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
// Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
for (int i = 1; i < n; i++) {
e[i-1] = e[i];
}
e[n-1] = 0.0;
double f = 0.0;
double tst1 = 0.0;
double eps = Math.pow(2.0,-52.0);
for (int l = 0; l < n; l++) {
// Find small subdiagonal element
tst1 = Math.max(tst1,Math.abs(d[l]) + Math.abs(e[l]));
int m = l;
while (m < n) {
if (Math.abs(e[m]) <= eps*tst1) {
break;
}
m++;
}
// If m == l, d[l] is an eigenvalue,
// otherwise, iterate.
if (m > l) {
int iter = 0;
do {
iter = iter + 1; // (Could check iteration count here.)
// Compute implicit shift
double g = d[l];
double p = (d[l+1] - g) / (2.0 * e[l]);
double r = Maths.hypot(p,1.0);
if (p < 0) {
r = -r;
}
d[l] = e[l] / (p + r);
d[l+1] = e[l] * (p + r);
double dl1 = d[l+1];
double h = g - d[l];
for (int i = l+2; i < n; i++) {
d[i] -= h;
}
f = f + h;
// Implicit QL transformation.
p = d[m];
double c = 1.0;
double c2 = c;
double c3 = c;
double el1 = e[l+1];
double s = 0.0;
double s2 = 0.0;
for (int i = m-1; i >= l; i--) {
c3 = c2;
c2 = c;
s2 = s;
g = c * e[i];
h = c * p;
r = Maths.hypot(p,e[i]);
e[i+1] = s * r;
s = e[i] / r;
c = p / r;
p = c * d[i] - s * g;
d[i+1] = h + s * (c * g + s * d[i]);
// Accumulate transformation.
for (int k = 0; k < n; k++) {
h = V[k][i+1];
V[k][i+1] = s * V[k][i] + c * h;
V[k][i] = c * V[k][i] - s * h;
}
}
p = -s * s2 * c3 * el1 * e[l] / dl1;
e[l] = s * p;
d[l] = c * p;
// Check for convergence.
} while (Math.abs(e[l]) > eps*tst1);
}
d[l] = d[l] + f;
e[l] = 0.0;
}
// Sort eigenvalues and corresponding vectors.
for (int i = 0; i < n-1; i++) {
int k = i;
double p = d[i];
for (int j = i+1; j < n; j++) {
if (d[j] < p) {
k = j;
p = d[j];
}
}
if (k != i) {
d[k] = d[i];
d[i] = p;
for (int j = 0; j < n; j++) {
p = V[j][i];
V[j][i] = V[j][k];
V[j][k] = p;
}
}
}
}
// Nonsymmetric reduction to Hessenberg form.
private void orthes () {
// This is derived from the Algol procedures orthes and ortran,
// by Martin and Wilkinson, Handbook for Auto. Comp.,
// Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutines in EISPACK.
int low = 0;
int high = n-1;
for (int m = low+1; m <= high-1; m++) {
// Scale column.
double scale = 0.0;
for (int i = m; i <= high; i++) {
scale = scale + Math.abs(H[i][m-1]);
}
if (scale != 0.0) {
// Compute Householder transformation.
double h = 0.0;
for (int i = high; i >= m; i--) {
ort[i] = H[i][m-1]/scale;
h += ort[i] * ort[i];
}
double g = Math.sqrt(h);
if (ort[m] > 0) {
g = -g;
}
h = h - ort[m] * g;
ort[m] = ort[m] - g;
// Apply Householder similarity transformation
// H = (I-u*u'/h)*H*(I-u*u')/h)
for (int j = m; j < n; j++) {
double f = 0.0;
for (int i = high; i >= m; i--) {
f += ort[i]*H[i][j];
}
f = f/h;
for (int i = m; i <= high; i++) {
H[i][j] -= f*ort[i];
}
}
for (int i = 0; i <= high; i++) {
double f = 0.0;
for (int j = high; j >= m; j--) {
f += ort[j]*H[i][j];
}
f = f/h;
for (int j = m; j <= high; j++) {
H[i][j] -= f*ort[j];
}
}
ort[m] = scale*ort[m];
H[m][m-1] = scale*g;
}
}
// Accumulate transformations (Algol's ortran).
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
V[i][j] = (i == j ? 1.0 : 0.0);
}
}
for (int m = high-1; m >= low+1; m--) {
if (H[m][m-1] != 0.0) {
for (int i = m+1; i <= high; i++) {
ort[i] = H[i][m-1];
}
for (int j = m; j <= high; j++) {
double g = 0.0;
for (int i = m; i <= high; i++) {
g += ort[i] * V[i][j];
}
// Double division avoids possible underflow
g = (g / ort[m]) / H[m][m-1];
for (int i = m; i <= high; i++) {
V[i][j] += g * ort[i];
}
}
}
}
}
// Complex scalar division.
private transient double cdivr, cdivi;
private void cdiv(double xr, double xi, double yr, double yi) {
double r,d;
if (Math.abs(yr) > Math.abs(yi)) {
r = yi/yr;
d = yr + r*yi;
cdivr = (xr + r*xi)/d;
cdivi = (xi - r*xr)/d;
} else {
r = yr/yi;
d = yi + r*yr;
cdivr = (r*xr + xi)/d;
cdivi = (r*xi - xr)/d;
}
}
// Nonsymmetric reduction from Hessenberg to real Schur form.
private void hqr2 () {
// This is derived from the Algol procedure hqr2,
// by Martin and Wilkinson, Handbook for Auto. Comp.,
// Vol.ii-Linear Algebra, and the corresponding
// Fortran subroutine in EISPACK.
// Initialize
int nn = this.n;
int n = nn-1;
int low = 0;
int high = nn-1;
double eps = Math.pow(2.0,-52.0);
double exshift = 0.0;
double p=0,q=0,r=0,s=0,z=0,t,w,x,y;
// Store roots isolated by balanc and compute matrix norm
double norm = 0.0;
for (int i = 0; i < nn; i++) {
if (i < low | i > high) {
d[i] = H[i][i];
e[i] = 0.0;
}
for (int j = Math.max(i-1,0); j < nn; j++) {
norm = norm + Math.abs(H[i][j]);
}
}
// Outer loop over eigenvalue index
int iter = 0;
while (n >= low) {
// Look for single small sub-diagonal element
int l = n;
while (l > low) {
s = Math.abs(H[l-1][l-1]) + Math.abs(H[l][l]);
if (s == 0.0) {
s = norm;
}
if (Math.abs(H[l][l-1]) < eps * s) {
break;
}
l--;
}
// Check for convergence
// One root found
if (l == n) {
H[n][n] = H[n][n] + exshift;
d[n] = H[n][n];
e[n] = 0.0;
n--;
iter = 0;
// Two roots found
} else if (l == n-1) {
w = H[n][n-1] * H[n-1][n];
p = (H[n-1][n-1] - H[n][n]) / 2.0;
q = p * p + w;
z = Math.sqrt(Math.abs(q));
H[n][n] = H[n][n] + exshift;
H[n-1][n-1] = H[n-1][n-1] + exshift;
x = H[n][n];
// Real pair
if (q >= 0) {
if (p >= 0) {
z = p + z;
} else {
z = p - z;
}
d[n-1] = x + z;
d[n] = d[n-1];
if (z != 0.0) {
d[n] = x - w / z;
}
e[n-1] = 0.0;
e[n] = 0.0;
x = H[n][n-1];
s = Math.abs(x) + Math.abs(z);
p = x / s;
q = z / s;
r = Math.sqrt(p * p+q * q);
p = p / r;
q = q / r;
// Row modification
for (int j = n-1; j < nn; j++) {
z = H[n-1][j];
H[n-1][j] = q * z + p * H[n][j];
H[n][j] = q * H[n][j] - p * z;
}
// Column modification
for (int i = 0; i <= n; i++) {
z = H[i][n-1];
H[i][n-1] = q * z + p * H[i][n];
H[i][n] = q * H[i][n] - p * z;
}
// Accumulate transformations
for (int i = low; i <= high; i++) {
z = V[i][n-1];
V[i][n-1] = q * z + p * V[i][n];
V[i][n] = q * V[i][n] - p * z;
}
// Complex pair
} else {
d[n-1] = x + p;
d[n] = x + p;
e[n-1] = z;
e[n] = -z;
}
n = n - 2;
iter = 0;
// No convergence yet
} else {
// Form shift
x = H[n][n];
y = 0.0;
w = 0.0;
if (l < n) {
y = H[n-1][n-1];
w = H[n][n-1] * H[n-1][n];
}
// Wilkinson's original ad hoc shift
if (iter == 10) {
exshift += x;
for (int i = low; i <= n; i++) {
H[i][i] -= x;
}
s = Math.abs(H[n][n-1]) + Math.abs(H[n-1][n-2]);
x = y = 0.75 * s;
w = -0.4375 * s * s;
}
// MATLAB's new ad hoc shift
if (iter == 30) {
s = (y - x) / 2.0;
s = s * s + w;
if (s > 0) {
s = Math.sqrt(s);
if (y < x) {
s = -s;
}
s = x - w / ((y - x) / 2.0 + s);
for (int i = low; i <= n; i++) {
H[i][i] -= s;
}
exshift += s;
x = y = w = 0.964;
}
}
iter = iter + 1; // (Could check iteration count here.)
// Look for two consecutive small sub-diagonal elements
int m = n-2;
while (m >= l) {
z = H[m][m];
r = x - z;
s = y - z;
p = (r * s - w) / H[m+1][m] + H[m][m+1];
q = H[m+1][m+1] - z - r - s;
r = H[m+2][m+1];
s = Math.abs(p) + Math.abs(q) + Math.abs(r);
p = p / s;
q = q / s;
r = r / s;
if (m == l) {
break;
}
if (Math.abs(H[m][m-1]) * (Math.abs(q) + Math.abs(r)) <
eps * (Math.abs(p) * (Math.abs(H[m-1][m-1]) + Math.abs(z) +
Math.abs(H[m+1][m+1])))) {
break;
}
m--;
}
for (int i = m+2; i <= n; i++) {
H[i][i-2] = 0.0;
if (i > m+2) {
H[i][i-3] = 0.0;
}
}
// Double QR step involving rows l:n and columns m:n
for (int k = m; k <= n-1; k++) {
boolean notlast = (k != n-1);
if (k != m) {
p = H[k][k-1];
q = H[k+1][k-1];
r = (notlast ? H[k+2][k-1] : 0.0);
x = Math.abs(p) + Math.abs(q) + Math.abs(r);
if (x == 0.0) {
continue;
}
p = p / x;
q = q / x;
r = r / x;
}
s = Math.sqrt(p * p + q * q + r * r);
if (p < 0) {
s = -s;
}
if (s != 0) {
if (k != m) {
H[k][k-1] = -s * x;
} else if (l != m) {
H[k][k-1] = -H[k][k-1];
}
p = p + s;
x = p / s;
y = q / s;
z = r / s;
q = q / p;
r = r / p;
// Row modification
for (int j = k; j < nn; j++) {
p = H[k][j] + q * H[k+1][j];
if (notlast) {
p = p + r * H[k+2][j];
H[k+2][j] = H[k+2][j] - p * z;
}
H[k][j] = H[k][j] - p * x;
H[k+1][j] = H[k+1][j] - p * y;
}
// Column modification
for (int i = 0; i <= Math.min(n,k+3); i++) {
p = x * H[i][k] + y * H[i][k+1];
if (notlast) {
p = p + z * H[i][k+2];
H[i][k+2] = H[i][k+2] - p * r;
}
H[i][k] = H[i][k] - p;
H[i][k+1] = H[i][k+1] - p * q;
}
// Accumulate transformations
for (int i = low; i <= high; i++) {
p = x * V[i][k] + y * V[i][k+1];
if (notlast) {
p = p + z * V[i][k+2];
V[i][k+2] = V[i][k+2] - p * r;
}
V[i][k] = V[i][k] - p;
V[i][k+1] = V[i][k+1] - p * q;
}
} // (s != 0)
} // k loop
} // check convergence
} // while (n >= low)
// Backsubstitute to find vectors of upper triangular form
if (norm == 0.0) {
return;
}
for (n = nn-1; n >= 0; n--) {
p = d[n];
q = e[n];
// Real vector
if (q == 0) {
int l = n;
H[n][n] = 1.0;
for (int i = n-1; i >= 0; i--) {
w = H[i][i] - p;
r = 0.0;
for (int j = l; j <= n; j++) {
r = r + H[i][j] * H[j][n];
}
if (e[i] < 0.0) {
z = w;
s = r;
} else {
l = i;
if (e[i] == 0.0) {
if (w != 0.0) {
H[i][n] = -r / w;
} else {
H[i][n] = -r / (eps * norm);
}
// Solve real equations
} else {
x = H[i][i+1];
y = H[i+1][i];
q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
t = (x * s - z * r) / q;
H[i][n] = t;
if (Math.abs(x) > Math.abs(z)) {
H[i+1][n] = (-r - w * t) / x;
} else {
H[i+1][n] = (-s - y * t) / z;
}
}
// Overflow control
t = Math.abs(H[i][n]);
if ((eps * t) * t > 1) {
for (int j = i; j <= n; j++) {
H[j][n] = H[j][n] / t;
}
}
}
}
// Complex vector
} else if (q < 0) {
int l = n-1;
// Last vector component imaginary so matrix is triangular
if (Math.abs(H[n][n-1]) > Math.abs(H[n-1][n])) {
H[n-1][n-1] = q / H[n][n-1];
H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
} else {
cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
H[n-1][n-1] = cdivr;
H[n-1][n] = cdivi;
}
H[n][n-1] = 0.0;
H[n][n] = 1.0;
for (int i = n-2; i >= 0; i--) {
double ra,sa,vr,vi;
ra = 0.0;
sa = 0.0;
for (int j = l; j <= n; j++) {
ra = ra + H[i][j] * H[j][n-1];
sa = sa + H[i][j] * H[j][n];
}
w = H[i][i] - p;
if (e[i] < 0.0) {
z = w;
r = ra;
s = sa;
} else {
l = i;
if (e[i] == 0) {
cdiv(-ra,-sa,w,q);
H[i][n-1] = cdivr;
H[i][n] = cdivi;
} else {
// Solve complex equations
x = H[i][i+1];
y = H[i+1][i];
vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
vi = (d[i] - p) * 2.0 * q;
if (vr == 0.0 & vi == 0.0) {
vr = eps * norm * (Math.abs(w) + Math.abs(q) +
Math.abs(x) + Math.abs(y) + Math.abs(z));
}
cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
H[i][n-1] = cdivr;
H[i][n] = cdivi;
if (Math.abs(x) > (Math.abs(z) + Math.abs(q))) {
H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
} else {
cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
H[i+1][n-1] = cdivr;
H[i+1][n] = cdivi;
}
}
// Overflow control
t = Math.max(Math.abs(H[i][n-1]),Math.abs(H[i][n]));
if ((eps * t) * t > 1) {
for (int j = i; j <= n; j++) {
H[j][n-1] = H[j][n-1] / t;
H[j][n] = H[j][n] / t;
}
}
}
}
}
}
// Vectors of isolated roots
for (int i = 0; i < nn; i++) {
if (i < low | i > high) {
for (int j = i; j < nn; j++) {
V[i][j] = H[i][j];
}
}
}
// Back transformation to get eigenvectors of original matrix
for (int j = nn-1; j >= low; j--) {
for (int i = low; i <= high; i++) {
z = 0.0;
for (int k = low; k <= Math.min(j,high); k++) {
z = z + V[i][k] * H[k][j];
}
V[i][j] = z;
}
}
}
/* ------------------------
Constructor
* ------------------------ */
/** Check for symmetry, then construct the eigenvalue decomposition
Structure to access D and V.
@param Arg Square matrix
*/
public EigenvalueDecomposition (Matrix Arg) {
double[][] A = Arg.getArray();
n = Arg.getColumnDimension();
V = new double[n][n];
d = new double[n];
e = new double[n];
issymmetric = true;
for (int j = 0; (j < n) & issymmetric; j++) {
for (int i = 0; (i < n) & issymmetric; i++) {
issymmetric = (A[i][j] == A[j][i]);
}
}
if (issymmetric) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
V[i][j] = A[i][j];
}
}
// Tridiagonalize.
tred2();
// Diagonalize.
tql2();
} else {
H = new double[n][n];
ort = new double[n];
for (int j = 0; j < n; j++) {
for (int i = 0; i < n; i++) {
H[i][j] = A[i][j];
}
}
// Reduce to Hessenberg form.
orthes();
// Reduce Hessenberg to real Schur form.
hqr2();
}
}
/* ------------------------
Public Methods
* ------------------------ */
/** Return the eigenvector matrix
@return V
*/
public Matrix getV () {
return new Matrix(V,n,n);
}
/** Return the real parts of the eigenvalues
@return real(diag(D))
*/
public double[] getRealEigenvalues () {
return d;
}
/** Return the imaginary parts of the eigenvalues
@return imag(diag(D))
*/
public double[] getImagEigenvalues () {
return e;
}
/** Return the block diagonal eigenvalue matrix
@return D
*/
public Matrix getD () {
Matrix X = new Matrix(n,n);
double[][] D = X.getArray();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
D[i][j] = 0.0;
}
D[i][i] = d[i];
if (e[i] > 0) {
D[i][i+1] = e[i];
} else if (e[i] < 0) {
D[i][i-1] = e[i];
}
}
return X;
}
private static final long serialVersionUID = 1;
}
jama-1.0.3/src/Jama/LUDecomposition.java 0000600 0001750 0001750 00000020024 12047301311 017310 0 ustar ebourg ebourg package Jama;
/** LU Decomposition.
For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
unit lower triangular matrix L, an n-by-n upper triangular matrix U,
and a permutation vector piv of length m so that A(piv,:) = L*U.
If m < n, then L is m-by-m and U is m-by-n.
The LU decompostion with pivoting always exists, even if the matrix is
singular, so the constructor will never fail. The primary use of the
LU decomposition is in the solution of square systems of simultaneous
linear equations. This will fail if isNonsingular() returns false.
*/
public class LUDecomposition implements java.io.Serializable {
/* ------------------------
Class variables
* ------------------------ */
/** Array for internal storage of decomposition.
@serial internal array storage.
*/
private double[][] LU;
/** Row and column dimensions, and pivot sign.
@serial column dimension.
@serial row dimension.
@serial pivot sign.
*/
private int m, n, pivsign;
/** Internal storage of pivot vector.
@serial pivot vector.
*/
private int[] piv;
/* ------------------------
Constructor
* ------------------------ */
/** LU Decomposition
Structure to access L, U and piv.
@param A Rectangular matrix
*/
public LUDecomposition (Matrix A) {
// Use a "left-looking", dot-product, Crout/Doolittle algorithm.
LU = A.getArrayCopy();
m = A.getRowDimension();
n = A.getColumnDimension();
piv = new int[m];
for (int i = 0; i < m; i++) {
piv[i] = i;
}
pivsign = 1;
double[] LUrowi;
double[] LUcolj = new double[m];
// Outer loop.
for (int j = 0; j < n; j++) {
// Make a copy of the j-th column to localize references.
for (int i = 0; i < m; i++) {
LUcolj[i] = LU[i][j];
}
// Apply previous transformations.
for (int i = 0; i < m; i++) {
LUrowi = LU[i];
// Most of the time is spent in the following dot product.
int kmax = Math.min(i,j);
double s = 0.0;
for (int k = 0; k < kmax; k++) {
s += LUrowi[k]*LUcolj[k];
}
LUrowi[j] = LUcolj[i] -= s;
}
// Find pivot and exchange if necessary.
int p = j;
for (int i = j+1; i < m; i++) {
if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p])) {
p = i;
}
}
if (p != j) {
for (int k = 0; k < n; k++) {
double t = LU[p][k]; LU[p][k] = LU[j][k]; LU[j][k] = t;
}
int k = piv[p]; piv[p] = piv[j]; piv[j] = k;
pivsign = -pivsign;
}
// Compute multipliers.
if (j < m & LU[j][j] != 0.0) {
for (int i = j+1; i < m; i++) {
LU[i][j] /= LU[j][j];
}
}
}
}
/* ------------------------
Temporary, experimental code.
------------------------ *\
\** LU Decomposition, computed by Gaussian elimination.
This constructor computes L and U with the "daxpy"-based elimination
algorithm used in LINPACK and MATLAB. In Java, we suspect the dot-product,
Crout algorithm will be faster. We have temporarily included this
constructor until timing experiments confirm this suspicion.
@param A Rectangular matrix
@param linpackflag Use Gaussian elimination. Actual value ignored.
@return Structure to access L, U and piv.
*\
public LUDecomposition (Matrix A, int linpackflag) {
// Initialize.
LU = A.getArrayCopy();
m = A.getRowDimension();
n = A.getColumnDimension();
piv = new int[m];
for (int i = 0; i < m; i++) {
piv[i] = i;
}
pivsign = 1;
// Main loop.
for (int k = 0; k < n; k++) {
// Find pivot.
int p = k;
for (int i = k+1; i < m; i++) {
if (Math.abs(LU[i][k]) > Math.abs(LU[p][k])) {
p = i;
}
}
// Exchange if necessary.
if (p != k) {
for (int j = 0; j < n; j++) {
double t = LU[p][j]; LU[p][j] = LU[k][j]; LU[k][j] = t;
}
int t = piv[p]; piv[p] = piv[k]; piv[k] = t;
pivsign = -pivsign;
}
// Compute multipliers and eliminate k-th column.
if (LU[k][k] != 0.0) {
for (int i = k+1; i < m; i++) {
LU[i][k] /= LU[k][k];
for (int j = k+1; j < n; j++) {
LU[i][j] -= LU[i][k]*LU[k][j];
}
}
}
}
}
\* ------------------------
End of temporary code.
* ------------------------ */
/* ------------------------
Public Methods
* ------------------------ */
/** Is the matrix nonsingular?
@return true if U, and hence A, is nonsingular.
*/
public boolean isNonsingular () {
for (int j = 0; j < n; j++) {
if (LU[j][j] == 0)
return false;
}
return true;
}
/** Return lower triangular factor
@return L
*/
public Matrix getL () {
Matrix X = new Matrix(m,n);
double[][] L = X.getArray();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i > j) {
L[i][j] = LU[i][j];
} else if (i == j) {
L[i][j] = 1.0;
} else {
L[i][j] = 0.0;
}
}
}
return X;
}
/** Return upper triangular factor
@return U
*/
public Matrix getU () {
Matrix X = new Matrix(n,n);
double[][] U = X.getArray();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i <= j) {
U[i][j] = LU[i][j];
} else {
U[i][j] = 0.0;
}
}
}
return X;
}
/** Return pivot permutation vector
@return piv
*/
public int[] getPivot () {
int[] p = new int[m];
for (int i = 0; i < m; i++) {
p[i] = piv[i];
}
return p;
}
/** Return pivot permutation vector as a one-dimensional double array
@return (double) piv
*/
public double[] getDoublePivot () {
double[] vals = new double[m];
for (int i = 0; i < m; i++) {
vals[i] = (double) piv[i];
}
return vals;
}
/** Determinant
@return det(A)
@exception IllegalArgumentException Matrix must be square
*/
public double det () {
if (m != n) {
throw new IllegalArgumentException("Matrix must be square.");
}
double d = (double) pivsign;
for (int j = 0; j < n; j++) {
d *= LU[j][j];
}
return d;
}
/** Solve A*X = B
@param B A Matrix with as many rows as A and any number of columns.
@return X so that L*U*X = B(piv,:)
@exception IllegalArgumentException Matrix row dimensions must agree.
@exception RuntimeException Matrix is singular.
*/
public Matrix solve (Matrix B) {
if (B.getRowDimension() != m) {
throw new IllegalArgumentException("Matrix row dimensions must agree.");
}
if (!this.isNonsingular()) {
throw new RuntimeException("Matrix is singular.");
}
// Copy right hand side with pivoting
int nx = B.getColumnDimension();
Matrix Xmat = B.getMatrix(piv,0,nx-1);
double[][] X = Xmat.getArray();
// Solve L*Y = B(piv,:)
for (int k = 0; k < n; k++) {
for (int i = k+1; i < n; i++) {
for (int j = 0; j < nx; j++) {
X[i][j] -= X[k][j]*LU[i][k];
}
}
}
// Solve U*X = Y;
for (int k = n-1; k >= 0; k--) {
for (int j = 0; j < nx; j++) {
X[k][j] /= LU[k][k];
}
for (int i = 0; i < k; i++) {
for (int j = 0; j < nx; j++) {
X[i][j] -= X[k][j]*LU[i][k];
}
}
}
return Xmat;
}
private static final long serialVersionUID = 1;
}
jama-1.0.3/ChangeLog 0000644 0001750 0001750 00000003135 12047304334 013527 0 ustar ebourg ebourg 2012-11-09 Bruce Miller
* Version 1.0.3 Released.
* Patched hqr2 method in Jama.EigenvalueDecomposition
to avoid infinite loop;
Thanks Frederic Devernay