Matrix.java
Download: project files
This is a Java implementation of a Matrix class, similar to our C++ version
001: //package Jama; 002: 003: import java.util.Locale; 004: import java.text.FieldPosition; 005: import java.io.PrintWriter; 006: import java.io.BufferedReader; 007: import java.io.StreamTokenizer; 008: 009: /** 010: Jama = Java Matrix class. 011: <P> 012: The Java Matrix Class provides the fundamental operations of numerical 013: linear algebra. Various constructors create Matrices from two dimensional 014: arrays of double precision floating point numbers. Various "gets" and 015: "sets" provide access to submatrices and matrix elements. Several methods 016: implement basic matrix arithmetic, including matrix addition and 017: multiplication, matrix norms, and element-by-element array operations. 018: Methods for reading and printing matrices are also included. All the 019: operations in this version of the Matrix Class involve real matrices. 020: Complex matrices may be handled in a future version. 021: <P> 022: Five fundamental matrix decompositions, which consist of pairs or triples 023: of matrices, permutation vectors, and the like, produce results in five 024: decomposition classes. These decompositions are accessed by the Matrix 025: class to compute solutions of simultaneous linear equations, determinants, 026: inverses and other matrix functions. The five decompositions are: 027: <P><UL> 028: <LI>Cholesky Decomposition of symmetric, positive definite matrices. 029: <LI>LU Decomposition of rectangular matrices. 030: <LI>QR Decomposition of rectangular matrices. 031: <LI>Singular Value Decomposition of rectangular matrices. 032: <LI>Eigenvalue Decomposition of both symmetric and nonsymmetric square matrices. 033: </UL> 034: <DL> 035: <DT><B>Example of use:</B></DT> 036: <P> 037: <DD>Solve a linear system A x = b and compute the residual norm, ||b - A x||. 038: <P><PRE> 039: double[][] vals = {{1.,2.,3},{4.,5.,6.},{7.,8.,10.}}; 040: Matrix A = new Matrix(vals); 041: Matrix b = Matrix.random(3,1); 042: Matrix x = A.solve(b); 043: Matrix r = A.times(x).minus(b); 044: double rnorm = r.normInf(); 045: </PRE></DD> 046: </DL> 047: 048: @author The MathWorks, Inc. and the National Institute of Standards and Technology. 049: @version 5 August 1998 050: */ 051: 052: public class Matrix implements Cloneable, java.io.Serializable { 053: 054: /* ------------------------ 055: Class variables 056: * ------------------------ */ 057: 058: /** Array for internal storage of elements. 059: @serial internal array storage. 060: */ 061: private double[][] A; 062: 063: /** Row and column dimensions. 064: @serial row dimension. 065: @serial column dimension. 066: */ 067: private int m, n; 068: 069: /* ------------------------ 070: Constructors 071: * ------------------------ */ 072: 073: /** Construct an m-by-n matrix of zeros. 074: @param m Number of rows. 075: @param n Number of colums. 076: */ 077: 078: public Matrix (int m, int n) { 079: this.m = m; 080: this.n = n; 081: A = new double[m][n]; 082: } 083: 084: /** Construct an m-by-n constant matrix. 085: @param m Number of rows. 086: @param n Number of colums. 087: @param s Fill the matrix with this scalar value. 088: */ 089: 090: public Matrix (int m, int n, double s) { 091: this.m = m; 092: this.n = n; 093: A = new double[m][n]; 094: for (int i = 0; i < m; i++) { 095: for (int j = 0; j < n; j++) { 096: A[i][j] = s; 097: } 098: } 099: } 100: 101: /** Construct a matrix from a 2-D array. 102: @param A Two-dimensional array of doubles. 103: @exception IllegalArgumentException All rows must have the same length 104: @see #constructWithCopy 105: */ 106: 107: public Matrix (double[][] A) { 108: m = A.length; 109: n = A[0].length; 110: for (int i = 0; i < m; i++) { 111: if (A[i].length != n) { 112: throw new IllegalArgumentException("All rows must have the same length."); 113: } 114: } 115: this.A = A; 116: } 117: 118: /** Construct a matrix quickly without checking arguments. 119: @param A Two-dimensional array of doubles. 120: @param m Number of rows. 121: @param n Number of colums. 122: */ 123: 124: public Matrix (double[][] A, int m, int n) { 125: this.A = A; 126: this.m = m; 127: this.n = n; 128: } 129: 130: /** Construct a matrix from a 1-D array. 131: @param A one-dimensional array of doubles. 132: * 133: * This constructs a column vector [m x 1] 134: */ 135: 136: public Matrix (double[] column) { 137: m = column.length; 138: n = 1; 139: A = new double[m][1]; 140: for (int i = 0; i < m; i++) A[i][0] = column[i]; 141: } 142: 143: /** Construct a matrix from a one-dimensional packed array 144: @param vals One-dimensional array of doubles, packed by columns (ala Fortran). 145: @param m Number of rows. 146: @exception IllegalArgumentException Array length must be a multiple of m. 147: */ 148: 149: public Matrix (double vals[], int m) { 150: this.m = m; 151: n = (m != 0 ? vals.length/m : 0); 152: if (m*n != vals.length) { 153: throw new IllegalArgumentException("Array length must be a multiple of m."); 154: } 155: A = new double[m][n]; 156: for (int i = 0; i < m; i++) { 157: for (int j = 0; j < n; j++) { 158: A[i][j] = vals[i+j*m]; 159: } 160: } 161: } 162: 163: /* ------------------------ 164: Public Methods 165: * ------------------------ */ 166: 167: /** Construct a matrix from a copy of a 2-D array. 168: @param A Two-dimensional array of doubles. 169: @exception IllegalArgumentException All rows must have the same length 170: */ 171: 172: public static Matrix constructWithCopy(double[][] A) { 173: int m = A.length; 174: int n = A[0].length; 175: Matrix X = new Matrix(m,n); 176: double[][] C = X.getArray(); 177: for (int i = 0; i < m; i++) { 178: if (A[i].length != n) { 179: throw new IllegalArgumentException 180: ("All rows must have the same length."); 181: } 182: for (int j = 0; j < n; j++) { 183: C[i][j] = A[i][j]; 184: } 185: } 186: return X; 187: } 188: 189: /** Make a deep copy of a matrix 190: */ 191: 192: public Matrix copy () { 193: Matrix X = new Matrix(m,n); 194: double[][] C = X.getArray(); 195: for (int i = 0; i < m; i++) { 196: for (int j = 0; j < n; j++) { 197: C[i][j] = A[i][j]; 198: } 199: } 200: return X; 201: } 202: 203: /** Clone the Matrix object. 204: */ 205: 206: public Object clone () { 207: return this.copy(); 208: } 209: 210: /** Access the internal two-dimensional array. 211: @return Pointer to the two-dimensional array of matrix elements. 212: */ 213: 214: public double[][] getArray () { 215: return A; 216: } 217: 218: /** Copy the internal two-dimensional array. 219: @return Two-dimensional array copy of matrix elements. 220: */ 221: 222: public double[][] getArrayCopy () { 223: double[][] C = new double[m][n]; 224: for (int i = 0; i < m; i++) { 225: for (int j = 0; j < n; j++) { 226: C[i][j] = A[i][j]; 227: } 228: } 229: return C; 230: } 231: 232: /** Make a one-dimensional column packed copy of the internal array. 233: @return Matrix elements packed in a one-dimensional array by columns. 234: */ 235: 236: public double[] getColumnPackedCopy () { 237: double[] vals = new double[m*n]; 238: for (int i = 0; i < m; i++) { 239: for (int j = 0; j < n; j++) { 240: vals[i+j*m] = A[i][j]; 241: } 242: } 243: return vals; 244: } 245: 246: /** Make a one-dimensional row packed copy of the internal array. 247: @return Matrix elements packed in a one-dimensional array by rows. 248: */ 249: 250: public double[] getRowPackedCopy () { 251: double[] vals = new double[m*n]; 252: for (int i = 0; i < m; i++) { 253: for (int j = 0; j < n; j++) { 254: vals[i*n+j] = A[i][j]; 255: } 256: } 257: return vals; 258: } 259: 260: /** Get row dimension. 261: @return m, the number of rows. 262: */ 263: 264: public int getRowDimension () { 265: return m; 266: } 267: 268: /** Get column dimension. 269: @return n, the number of columns. 270: */ 271: 272: public int getColumnDimension () { 273: return n; 274: } 275: 276: /** Get a single element. 277: @param i Row index. 278: @param j Column index. 279: @return A(i,j) 280: @exception ArrayIndexOutOfBoundsException 281: */ 282: 283: public double get (int i, int j) { 284: return A[i][j]; 285: } 286: 287: /** Get a submatrix. 288: @param i0 Initial row index 289: @param i1 Final row index 290: @param j0 Initial column index 291: @param j1 Final column index 292: @return A(i0:i1,j0:j1) 293: @exception ArrayIndexOutOfBoundsException Submatrix indices 294: */ 295: 296: public Matrix getMatrix (int i0, int i1, int j0, int j1) { 297: Matrix X = new Matrix(i1-i0+1,j1-j0+1); 298: double[][] B = X.getArray(); 299: try { 300: for (int i = i0; i <= i1; i++) { 301: for (int j = j0; j <= j1; j++) { 302: B[i-i0][j-j0] = A[i][j]; 303: } 304: } 305: } catch(ArrayIndexOutOfBoundsException e) { 306: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 307: } 308: return X; 309: } 310: 311: /** Get a submatrix. 312: @param r Array of row indices. 313: @param c Array of column indices. 314: @return A(r(:),c(:)) 315: @exception ArrayIndexOutOfBoundsException Submatrix indices 316: */ 317: 318: public Matrix getMatrix (int[] r, int[] c) { 319: Matrix X = new Matrix(r.length,c.length); 320: double[][] B = X.getArray(); 321: try { 322: for (int i = 0; i < r.length; i++) { 323: for (int j = 0; j < c.length; j++) { 324: B[i][j] = A[r[i]][c[j]]; 325: } 326: } 327: } catch(ArrayIndexOutOfBoundsException e) { 328: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 329: } 330: return X; 331: } 332: 333: /** Get a submatrix. 334: @param i0 Initial row index 335: @param i1 Final row index 336: @param c Array of column indices. 337: @return A(i0:i1,c(:)) 338: @exception ArrayIndexOutOfBoundsException Submatrix indices 339: */ 340: 341: public Matrix getMatrix (int i0, int i1, int[] c) { 342: Matrix X = new Matrix(i1-i0+1,c.length); 343: double[][] B = X.getArray(); 344: try { 345: for (int i = i0; i <= i1; i++) { 346: for (int j = 0; j < c.length; j++) { 347: B[i-i0][j] = A[i][c[j]]; 348: } 349: } 350: } catch(ArrayIndexOutOfBoundsException e) { 351: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 352: } 353: return X; 354: } 355: 356: /** Get a submatrix. 357: @param r Array of row indices. 358: @param i0 Initial column index 359: @param i1 Final column index 360: @return A(r(:),j0:j1) 361: @exception ArrayIndexOutOfBoundsException Submatrix indices 362: */ 363: 364: public Matrix getMatrix (int[] r, int j0, int j1) { 365: Matrix X = new Matrix(r.length,j1-j0+1); 366: double[][] B = X.getArray(); 367: try { 368: for (int i = 0; i < r.length; i++) { 369: for (int j = j0; j <= j1; j++) { 370: B[i][j-j0] = A[r[i]][j]; 371: } 372: } 373: } catch(ArrayIndexOutOfBoundsException e) { 374: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 375: } 376: return X; 377: } 378: 379: /** Set a single element. 380: @param i Row index. 381: @param j Column index. 382: @param s A(i,j). 383: @exception ArrayIndexOutOfBoundsException 384: */ 385: 386: public void set (int i, int j, double s) { 387: A[i][j] = s; 388: } 389: 390: /** Set a submatrix. 391: @param i0 Initial row index 392: @param i1 Final row index 393: @param j0 Initial column index 394: @param j1 Final column index 395: @param X A(i0:i1,j0:j1) 396: @exception ArrayIndexOutOfBoundsException Submatrix indices 397: */ 398: 399: public void setMatrix (int i0, int i1, int j0, int j1, Matrix X) { 400: try { 401: for (int i = i0; i <= i1; i++) { 402: for (int j = j0; j <= j1; j++) { 403: A[i][j] = X.get(i-i0,j-j0); 404: } 405: } 406: } catch(ArrayIndexOutOfBoundsException e) { 407: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 408: } 409: } 410: 411: /** Set a submatrix. 412: @param r Array of row indices. 413: @param c Array of column indices. 414: @param X A(r(:),c(:)) 415: @exception ArrayIndexOutOfBoundsException Submatrix indices 416: */ 417: 418: public void setMatrix (int[] r, int[] c, Matrix X) { 419: try { 420: for (int i = 0; i < r.length; i++) { 421: for (int j = 0; j < c.length; j++) { 422: A[r[i]][c[j]] = X.get(i,j); 423: } 424: } 425: } catch(ArrayIndexOutOfBoundsException e) { 426: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 427: } 428: } 429: 430: /** Set a submatrix. 431: @param r Array of row indices. 432: @param j0 Initial column index 433: @param j1 Final column index 434: @param X A(r(:),j0:j1) 435: @exception ArrayIndexOutOfBoundsException Submatrix indices 436: */ 437: 438: public void setMatrix (int[] r, int j0, int j1, Matrix X) { 439: try { 440: for (int i = 0; i < r.length; i++) { 441: for (int j = j0; j <= j1; j++) { 442: A[r[i]][j] = X.get(i,j-j0); 443: } 444: } 445: } catch(ArrayIndexOutOfBoundsException e) { 446: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 447: } 448: } 449: 450: /** Set a submatrix. 451: @param i0 Initial row index 452: @param i1 Final row index 453: @param c Array of column indices. 454: @param X A(i0:i1,c(:)) 455: @exception ArrayIndexOutOfBoundsException Submatrix indices 456: */ 457: 458: public void setMatrix (int i0, int i1, int[] c, Matrix X) { 459: try { 460: for (int i = i0; i <= i1; i++) { 461: for (int j = 0; j < c.length; j++) { 462: A[i][c[j]] = X.get(i-i0,j); 463: } 464: } 465: } catch(ArrayIndexOutOfBoundsException e) { 466: throw new ArrayIndexOutOfBoundsException("Submatrix indices"); 467: } 468: } 469: 470: /** Matrix transpose. 471: @return A' 472: */ 473: 474: public Matrix transpose () { 475: Matrix X = new Matrix(n,m); 476: double[][] C = X.getArray(); 477: for (int i = 0; i < m; i++) { 478: for (int j = 0; j < n; j++) { 479: C[j][i] = A[i][j]; 480: } 481: } 482: return X; 483: } 484: 485: /** One norm 486: @return maximum column sum. 487: */ 488: 489: public double norm1 () { 490: double f = 0; 491: for (int j = 0; j < n; j++) { 492: double s = 0; 493: for (int i = 0; i < m; i++) { 494: s += Math.abs(A[i][j]); 495: } 496: f = Math.max(f,s); 497: } 498: return f; 499: } 500: 501: 502: /** Infinity norm 503: @return maximum row sum. 504: */ 505: 506: public double normInf () { 507: double f = 0; 508: for (int i = 0; i < m; i++) { 509: double s = 0; 510: for (int j = 0; j < n; j++) { 511: s += Math.abs(A[i][j]); 512: } 513: f = Math.max(f,s); 514: } 515: return f; 516: } 517: 518: /** Frobenius norm 519: @return sqrt of sum of squares of all elements. 520: */ 521: 522: public double normF () { 523: double f = 0; 524: for (int i = 0; i < m; i++) { 525: for (int j = 0; j < n; j++) { 526: f = hypot(f,A[i][j]); 527: } 528: } 529: return f; 530: } 531: 532: /** Unary minus 533: @return -A 534: */ 535: 536: public Matrix uminus () { 537: Matrix X = new Matrix(m,n); 538: double[][] C = X.getArray(); 539: for (int i = 0; i < m; i++) { 540: for (int j = 0; j < n; j++) { 541: C[i][j] = -A[i][j]; 542: } 543: } 544: return X; 545: } 546: 547: /** C = A + B 548: @param B another matrix 549: @return A + B 550: */ 551: 552: public Matrix plus (Matrix B) { 553: checkMatrixDimensions(B); 554: Matrix X = new Matrix(m,n); 555: double[][] C = X.getArray(); 556: for (int i = 0; i < m; i++) { 557: for (int j = 0; j < n; j++) { 558: C[i][j] = A[i][j] + B.A[i][j]; 559: } 560: } 561: return X; 562: } 563: 564: /** A = A + B 565: @param B another matrix 566: @return A + B 567: */ 568: 569: public Matrix plusEquals (Matrix B) { 570: checkMatrixDimensions(B); 571: for (int i = 0; i < m; i++) { 572: for (int j = 0; j < n; j++) { 573: A[i][j] = A[i][j] + B.A[i][j]; 574: } 575: } 576: return this; 577: } 578: 579: /** C = A - B 580: @param B another matrix 581: @return A - B 582: */ 583: 584: public Matrix minus (Matrix B) { 585: checkMatrixDimensions(B); 586: Matrix X = new Matrix(m,n); 587: double[][] C = X.getArray(); 588: for (int i = 0; i < m; i++) { 589: for (int j = 0; j < n; j++) { 590: C[i][j] = A[i][j] - B.A[i][j]; 591: } 592: } 593: return X; 594: } 595: 596: /** A = A - B 597: @param B another matrix 598: @return A - B 599: */ 600: 601: public Matrix minusEquals (Matrix B) { 602: checkMatrixDimensions(B); 603: for (int i = 0; i < m; i++) { 604: for (int j = 0; j < n; j++) { 605: A[i][j] = A[i][j] - B.A[i][j]; 606: } 607: } 608: return this; 609: } 610: 611: /** Element-by-element multiplication, C = A.*B 612: @param B another matrix 613: @return A.*B 614: */ 615: 616: public Matrix arrayTimes (Matrix B) { 617: checkMatrixDimensions(B); 618: Matrix X = new Matrix(m,n); 619: double[][] C = X.getArray(); 620: for (int i = 0; i < m; i++) { 621: for (int j = 0; j < n; j++) { 622: C[i][j] = A[i][j] * B.A[i][j]; 623: } 624: } 625: return X; 626: } 627: 628: /** Element-by-element multiplication in place, A = A.*B 629: @param B another matrix 630: @return A.*B 631: */ 632: 633: public Matrix arrayTimesEquals (Matrix B) { 634: checkMatrixDimensions(B); 635: for (int i = 0; i < m; i++) { 636: for (int j = 0; j < n; j++) { 637: A[i][j] = A[i][j] * B.A[i][j]; 638: } 639: } 640: return this; 641: } 642: 643: /** Element-by-element right division, C = A./B 644: @param B another matrix 645: @return A./B 646: */ 647: 648: public Matrix arrayRightDivide (Matrix B) { 649: checkMatrixDimensions(B); 650: Matrix X = new Matrix(m,n); 651: double[][] C = X.getArray(); 652: for (int i = 0; i < m; i++) { 653: for (int j = 0; j < n; j++) { 654: C[i][j] = A[i][j] / B.A[i][j]; 655: } 656: } 657: return X; 658: } 659: 660: /** Element-by-element right division in place, A = A./B 661: @param B another matrix 662: @return A./B 663: */ 664: 665: public Matrix arrayRightDivideEquals (Matrix B) { 666: checkMatrixDimensions(B); 667: for (int i = 0; i < m; i++) { 668: for (int j = 0; j < n; j++) { 669: A[i][j] = A[i][j] / B.A[i][j]; 670: } 671: } 672: return this; 673: } 674: 675: /** Element-by-element left division, C = A.\B 676: @param B another matrix 677: @return A.\B 678: */ 679: 680: public Matrix arrayLeftDivide (Matrix B) { 681: checkMatrixDimensions(B); 682: Matrix X = new Matrix(m,n); 683: double[][] C = X.getArray(); 684: for (int i = 0; i < m; i++) { 685: for (int j = 0; j < n; j++) { 686: C[i][j] = B.A[i][j] / A[i][j]; 687: } 688: } 689: return X; 690: } 691: 692: /** Element-by-element left division in place, A = A.\B 693: @param B another matrix 694: @return A.\B 695: */ 696: 697: public Matrix arrayLeftDivideEquals (Matrix B) { 698: checkMatrixDimensions(B); 699: for (int i = 0; i < m; i++) { 700: for (int j = 0; j < n; j++) { 701: A[i][j] = B.A[i][j] / A[i][j]; 702: } 703: } 704: return this; 705: } 706: 707: /** Multiply a matrix by a scalar, C = s*A 708: @param s scalar 709: @return s*A 710: */ 711: 712: public Matrix times (double s) { 713: Matrix X = new Matrix(m,n); 714: double[][] C = X.getArray(); 715: for (int i = 0; i < m; i++) { 716: for (int j = 0; j < n; j++) { 717: C[i][j] = s*A[i][j]; 718: } 719: } 720: return X; 721: } 722: 723: /** Multiply a matrix by a scalar in place, A = s*A 724: @param s scalar 725: @return replace A by s*A 726: */ 727: 728: public Matrix timesEquals (double s) { 729: for (int i = 0; i < m; i++) { 730: for (int j = 0; j < n; j++) { 731: A[i][j] = s*A[i][j]; 732: } 733: } 734: return this; 735: } 736: 737: /** Linear algebraic matrix multiplication, A * B 738: @param B another matrix 739: @return Matrix product, A * B 740: @exception IllegalArgumentException Matrix inner dimensions must agree. 741: */ 742: 743: public Matrix times (Matrix B) { 744: if (B.m != n) { 745: throw new IllegalArgumentException("Matrix inner dimensions must agree."); 746: } 747: Matrix X = new Matrix(m,B.n); 748: double[][] C = X.getArray(); 749: double[] Bcolj = new double[n]; 750: for (int j = 0; j < B.n; j++) { 751: for (int k = 0; k < n; k++) { 752: Bcolj[k] = B.A[k][j]; 753: } 754: for (int i = 0; i < m; i++) { 755: double[] Arowi = A[i]; 756: double s = 0; 757: for (int k = 0; k < n; k++) { 758: s += Arowi[k]*Bcolj[k]; 759: } 760: C[i][j] = s; 761: } 762: } 763: return X; 764: } 765: 766: /** Matrix trace. 767: @return sum of the diagonal elements. 768: */ 769: 770: public double trace () { 771: double t = 0; 772: for (int i = 0; i < Math.min(m,n); i++) { 773: t += A[i][i]; 774: } 775: return t; 776: } 777: 778: /** Generate matrix with random elements 779: @param m Number of rows. 780: @param n Number of colums. 781: @return An m-by-n matrix with uniformly distributed random elements. 782: */ 783: 784: public static Matrix random (int m, int n) { 785: Matrix A = new Matrix(m,n); 786: double[][] X = A.getArray(); 787: for (int i = 0; i < m; i++) { 788: for (int j = 0; j < n; j++) { 789: X[i][j] = Math.random(); 790: } 791: } 792: return A; 793: } 794: 795: /** Generate identity matrix 796: @param m Number of rows. 797: @param n Number of colums. 798: @return An m-by-n matrix with ones on the diagonal and zeros elsewhere. 799: */ 800: 801: public static Matrix identity (int m, int n) { 802: Matrix A = new Matrix(m,n); 803: double[][] X = A.getArray(); 804: for (int i = 0; i < m; i++) { 805: for (int j = 0; j < n; j++) { 806: X[i][j] = (i == j ? 1.0 : 0.0); 807: } 808: } 809: return A; 810: } 811: 812: 813: /** sqrt(a^2 + b^2) without under/overflow. **/ 814: 815: public static double hypot(double a, double b) { 816: double r; 817: a = Math.abs(a); 818: b = Math.abs(b); 819: if (b > a) { 820: r = (b>0.0? a/b: 0.0); 821: a = b; 822: } 823: else r = (a>0.0? b/a : 0.0); 824: r = a*Math.sqrt(1.0+r*r); 825: return r; 826: } 827: 828: 829: /** Print the matrix to stdout. Line the elements up in columns 830: * with a Fortran-like 'Fw.d' style format. 831: @param w Column width. 832: @param d Number of digits after the decimal. 833: */ 834: 835: public void print (String format) { 836: print(new PrintWriter(System.out,true),format); } 837: 838: /** Print the matrix to the output stream. Line the elements up in columns. 839: * Use the format object, and right justify within columns of width 840: * characters. 841: * Note that is the matrix is to be read back in, you probably will want 842: * to use a NumberFormat that is set to US Locale. 843: @param output the output stream. 844: @param format A formatting object to format the matrix elements 845: @param width Column width. 846: @see java.text.DecimalFormat#setDecimalFormatSymbols 847: */ 848: 849: public void print (PrintWriter output, String format) { 850: output.println(); // start on new line. 851: for (int i = 0; i < m; i++) { 852: for (int j = 0; j < n; j++) { 853: output.printf(format,A[i][j]); 854: } 855: output.println(); 856: } 857: output.println(); // end with blank line. 858: } 859: 860: /** Read a matrix from a stream. The format is the same the print method, 861: * so printed matrices can be read back in (provided they were printed using 862: * US Locale). Elements are separated by 863: * whitespace, all the elements for each row appear on a single line, 864: * the last row is followed by a blank line. 865: @param input the input stream. 866: */ 867: 868: public static Matrix read (BufferedReader input) throws java.io.IOException { 869: StreamTokenizer tokenizer= new StreamTokenizer(input); 870: 871: // Although StreamTokenizer will parse numbers, it doesn't recognize 872: // scientific notation (E or D); however, Double.valueOf does. 873: // The strategy here is to disable StreamTokenizer's number parsing. 874: // We'll only get whitespace delimited words, EOL's and EOF's. 875: // These words should all be numbers, for Double.valueOf to parse. 876: 877: tokenizer.resetSyntax(); 878: tokenizer.wordChars(0,255); 879: tokenizer.whitespaceChars(0, ' '); 880: tokenizer.eolIsSignificant(true); 881: java.util.Vector<Double> u = new java.util.Vector<Double>(); 882: 883: // Ignore initial empty lines 884: while (tokenizer.nextToken() == StreamTokenizer.TT_EOL); 885: if (tokenizer.ttype == StreamTokenizer.TT_EOF) 886: throw new java.io.IOException("Unexpected EOF on matrix read."); 887: do { 888: Double d = Double.valueOf(tokenizer.sval); 889: u.addElement(d); // Read & store 1st row. 890: } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD); 891: 892: int n = u.size(); // Now we've got the number of columns! 893: 894: java.util.Vector<Double[]> v = new java.util.Vector<Double[]>(); 895: Double row[] = new Double[n]; 896: for (int j=0; j<n; j++) // extract the elements of the 1st row. 897: row[j]=u.elementAt(j); 898: v.addElement(row); // Start storing rows instead of columns. 899: while (tokenizer.nextToken() == StreamTokenizer.TT_WORD) { 900: // While non-empty lines 901: row = new Double[n]; 902: v.addElement(row); 903: int j = 0; 904: do { 905: if (j >= n) throw new java.io.IOException 906: ("Row " + v.size() + " is too long."); 907: row[j++] = Double.valueOf(tokenizer.sval); 908: } while (tokenizer.nextToken() == StreamTokenizer.TT_WORD); 909: if (j < n) throw new java.io.IOException 910: ("Row " + v.size() + " is too short."); 911: } 912: int m = v.size(); // Now we've got the number of rows. 913: double[][] A = new double[m][n]; 914: for (int i=0; i<m; i++) { 915: row = v.get(i); 916: for (int j=0; j<n; j++) A[i][j] = row[j]; 917: } 918: return new Matrix(A); 919: } 920: 921: 922: /* ------------------------ 923: Private Methods 924: * ------------------------ */ 925: 926: /** Check if size(A) == size(B) **/ 927: 928: private void checkMatrixDimensions (Matrix B) { 929: if (B.m != m || B.n != n) { 930: throw new IllegalArgumentException("Matrix dimensions must agree."); 931: } 932: } 933: }
mtest.java
01: import java.io.*; 02: 03: public class mtest { 04: public static void main(String args[]) 05: { 06: if (args.length>0) { 07: FileInputStream instream; 08: BufferedReader in; 09: try { 10: String filename = args[0]; 11: System.out.println("Filename: " + filename); 12: instream = new FileInputStream(filename); 13: in = new BufferedReader(new InputStreamReader(instream)); 14: Matrix A = Matrix.read(in); 15: A.print("\t%.2g"); 16: } catch (IOException e) { 17: System.out.println( e); 18: } 19: } 20: else { 21: double a[][] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; 22: Matrix A = new Matrix(a); 23: A.print("\t%.1g"); 24: System.out.println("Test hypot(3,4): " + Matrix.hypot(3,4) + " " + Matrix.hypot(4,3)); 25: } 26: } 27: }
Command:
java mtest
Results:
1 2 3 4 5 6 7 8 9 Test hypot(3,4): 5.0 5.0
Maintained by John Loomis, updated Mon Mar 24 13:38:14 2008