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