5 * streamlined and refined for Jmol by Bob Hanson
7 * from http://math.nist.gov/javanumerics/jama/
9 * Jama = Java Matrix class.
11 * @author The MathWorks, Inc. and the National Institute of Standards and
13 * @version 5 August 1998
16 public class Matrix implements Cloneable {
22 * Construct a matrix quickly without checking arguments.
25 * Two-dimensional array of doubles or null
32 public Matrix(double[][] a, int m, int n) {
33 this.a = (a == null ? new double[m][n] : a);
41 * @return m, the number of rows.
44 public int getRowDimension() {
49 * Get column dimension.
51 * @return n, the number of columns.
54 public int getColumnDimension() {
59 * Access the internal two-dimensional array.
61 * @return Pointer to the two-dimensional array of matrix elements.
64 public double[][] getArray() {
69 * Copy the internal two-dimensional array.
71 * @return Two-dimensional array copy of matrix elements.
74 public double[][] getArrayCopy() {
75 double[][] x = new double[m][n];
76 for (int i = m; --i >= 0;)
77 for (int j = n; --j >= 0;)
83 * Make a deep copy of a matrix
88 public Matrix copy() {
89 Matrix x = new Matrix(null, m, n);
91 for (int i = m; --i >= 0;)
92 for (int j = n; --j >= 0;)
98 * Clone the Matrix object.
102 public Object clone() {
112 * Initial column index
121 public Matrix getSubmatrix(int i0, int j0, int nrows, int ncols) {
122 Matrix x = new Matrix(null, nrows, ncols);
124 for (int i = nrows; --i >= 0;)
125 for (int j = ncols; --j >= 0;)
126 xa[i][j] = a[i0 + i][j0 + j];
131 * Get a submatrix for a give number of columns and selected row set.
134 * Array of row indices.
140 public Matrix getMatrixSelected(int[] r, int n) {
141 Matrix x = new Matrix(null, r.length, n);
143 for (int i = r.length; --i >= 0;) {
144 double[] b = a[r[i]];
145 for (int j = n; --j >= 0;)
157 public Matrix transpose() {
158 Matrix x = new Matrix(null, n, m);
160 for (int i = m; --i >= 0;)
161 for (int j = n; --j >= 0;)
169 * @return new Matrix this + b
171 public Matrix add(Matrix b) {
172 return scaleAdd(b, 1);
176 * subtract two matrices
178 * @return new Matrix this - b
180 public Matrix sub(Matrix b) {
181 return scaleAdd(b, -1);
191 public Matrix scaleAdd(Matrix b, double scale) {
192 Matrix x = new Matrix(null, m, n);
195 for (int i = m; --i >= 0;)
196 for (int j = n; --j >= 0;)
197 xa[i][j] = ba[i][j] * scale + a[i][j];
202 * Linear algebraic matrix multiplication, A * B
206 * @return Matrix product, A * B or null for wrong dimension
209 public Matrix mul(Matrix b) {
212 Matrix x = new Matrix(null, m, b.n);
215 for (int j = b.n; --j >= 0;)
216 for (int i = m; --i >= 0;) {
217 double[] arowi = a[i];
219 for (int k = n; --k >= 0;)
220 s += arowi[k] * ba[k][j];
227 * Matrix inverse or pseudoinverse
229 * @return inverse (m == n) or pseudoinverse (m != n)
232 public Matrix inverse() {
233 return new LUDecomp(m, n).solve(identity(m, m), n);
239 * @return sum of the diagonal elements.
242 public double trace() {
244 for (int i = Math.min(m, n); --i >= 0;)
250 * Generate identity matrix
256 * @return An m-by-n matrix with ones on the diagonal and zeros elsewhere.
259 public static Matrix identity(int m, int n) {
260 Matrix x = new Matrix(null, m, n);
262 for (int i = Math.min(m, n); --i >= 0;)
268 * similarly to M3/M4 standard rotation/translation matrix
269 * we set a rotationTranslation matrix to be:
271 * [ nxn rot nx1 trans
276 * @return rotation matrix
278 public Matrix getRotation() {
279 return getSubmatrix(0, 0, m - 1, n - 1);
282 public Matrix getTranslation() {
283 return getSubmatrix(0, n - 1, m - 1, 1);
286 public static Matrix newT(T3 r, boolean asColumn) {
287 return (asColumn ? new Matrix(new double[][] { new double[] { r.x },
288 new double[] { r.y }, new double[] { r.z } }, 3, 1) : new Matrix(
289 new double[][] { new double[] { r.x, r.y, r.z } }, 1, 3));
293 public String toString() {
295 for (int i = 0; i < m; i++) {
297 for (int j = 0; j < n; j++)
307 * Edited down by Bob Hanson for minimum needed by Jmol -- just constructor
312 * For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n unit
313 * lower triangular matrix L, an n-by-n upper triangular matrix U, and a
314 * permutation vector piv of length m so that A(piv,:) = L*U. If m < n, then L
315 * is m-by-m and U is m-by-n.
317 * The LU decompostion with pivoting always exists, even if the matrix is
318 * singular, so the constructor will never fail. The primary use of the LU
319 * decomposition is in the solution of square systems of simultaneous linear
320 * equations. This will fail if isNonsingular() returns false.
323 private class LUDecomp {
325 /* ------------------------
327 * ------------------------ */
330 * Array for internal storage of decomposition.
333 private double[][] LU;
336 * Internal storage of pivot vector.
343 /* ------------------------
345 * ------------------------ */
348 * LU Decomposition Structure to access L, U and piv.
354 protected LUDecomp(int m, int n) {
356 // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
360 for (int i = m; --i >= 0;)
364 double[] LUcolj = new double[m];
368 for (int j = 0; j < n; j++) {
370 // Make a copy of the j-th column to localize references.
372 for (int i = m; --i >= 0;)
373 LUcolj[i] = LU[i][j];
375 // Apply previous transformations.
377 for (int i = m; --i >= 0;) {
380 // Most of the time is spent in the following dot product.
382 int kmax = Math.min(i, j);
384 for (int k = kmax; --k >= 0;)
385 s += LUrowi[k] * LUcolj[k];
387 LUrowi[j] = LUcolj[i] -= s;
390 // Find pivot and exchange if necessary.
393 for (int i = m; --i > j;)
394 if (Math.abs(LUcolj[i]) > Math.abs(LUcolj[p]))
397 for (int k = n; --k >= 0;) {
408 // Compute multipliers.
410 if (j < m & LU[j][j] != 0.0)
411 for (int i = m; --i > j;)
412 LU[i][j] /= LU[j][j];
416 /* ------------------------
418 * ------------------------ */
424 * A Matrix with as many rows as A and any number of columns.
426 * @return X so that L*U*X = B(piv,:) or null for wrong size or singular matrix
429 protected Matrix solve(Matrix b, int n) {
430 for (int j = 0; j < n; j++)
432 return null; // matrix is singular
434 // Copy right hand side with pivoting
436 Matrix x = b.getMatrixSelected(piv, nx);
439 // Solve L*Y = B(piv,:)
440 for (int k = 0; k < n; k++)
441 for (int i = k + 1; i < n; i++)
442 for (int j = 0; j < nx; j++)
443 a[i][j] -= a[k][j] * LU[i][k];
446 for (int k = n; --k >= 0;) {
447 for (int j = nx; --j >= 0;)
449 for (int i = k; --i >= 0;)
450 for (int j = nx; --j >= 0;)
451 a[i][j] -= a[k][j] * LU[i][k];