///////////////////////////////////////////////////////////////////////////////////////////// // // MatrixMultiply.java // Multiplies any number of matrices. // // 1. Save this file as MatrixMultiply.java on any system with the javac compiler, available // from Sun Microsystems: http://java.sun.com/javase/downloads/index.jsp // 2. If you're on a unix system also save the file "Makefile" in the same directory, then // 3. Compile by typing "make" or "gmake" at the command line (leave out the quotes). // 4. Run the executable by doing "MatrixMultiply infile outfile", where "infile" is // a properly formated (described below) input file. // 5. Else if you're on any other system, then // 6. Compile by typing "javac MatrixMultiply.java" at the command line (leave out quotes). // 7. Run the executable by doing "java MatrixMultiply infile outfile, where "infile" is // a properly formated (described below) input file. // // Input file format. // The first line of an input file consists of two integers n and p, separated by a space, // giving the number of rows and columns of the first matrix. The next n lines of the input // file specify the n rows of the first matrix. Each line is a space separated list of p real // numbers. (Note that the number of spaces separating the numbers in each row is irrelevant.) // The next line of the input file consists of two integers p and m, separated by a space, giving // the number of rows and columns of the second matrix. Necessarily the number of columns of // the first matrix, and the number of rows of the second matrix must be one and the same, // namely p. The next p lines of input specify the p rows of the second matrix, each of which // is a space separated list of m real numbers. Each subsequent matrix is specified in the same // way, with the number of columns of one matrix equals the number of rows of the next. The // input is terminated by either a blank line, or by the eof character. // // Output file format: // The output file will be formated in the same way as the input file, i.e. two integers on // a line, giving the number of rows and columns, followed by each row of the product matrix, // and terminated by eof. Note that unlike the GaussJordan programs, this program does not // overwrite a pre existing output file. If the output file does not already exist, it is // created. If it does exist, output is appended to the existing lines. Thus one can build up // several products into one output file, and if the resulting matrices have the proper // dimensions, that output file can be used as input to another run of the program. // // Example 1 (Save the following lines as a text file called in1.) // 3 5 // 2 0 4 2 9 // 3 4 0 0 -7 // 0 1 0 5 0 // 5 4 // 1 3 8 1 // 2 6 7 0 // 1 -3 5 0 // 0 5 -2 6 // -1 2 0 10 // // Example 2 (Save as text file in2.) // 4 4 // 3.1 4.2 7.9 0.0 // -6.7 1.2 3.4 5.6 // 9.8 7.6 5.4 3.2 // 6.7 8.8 -9.1 2.5 // 4 3 // 0.0 1.1 8.2 // 7.8 0.0 0.0 // 2.1 2.3 4.5 // 3.6 4.7 -5.5 // 3 2 // 2.3 3.4 // 5.1 9.0 // 2.2 -1.3 // // The result of Example 1 is a 3x4 matrix, while Example 2 yields a 4x2. Run the // program on the two files in succession, with the output file name in3. Then in3 // is a properly formated input file, on which you can run the program again. Do // // % MatrixMultiply in1 in3 // % MatrixMultiply in2 in3 // % MatrixMultiply in3 out // // File out will then contain the product of all five matrices, which is a 3x2. // ///////////////////////////////////////////////////////////////////////////////////////////// import java.io.*; import java.util.StringTokenizer; class MatrixMultiply{ // mult() // Return a new matrix which is the product of matrices A and B. // pre: #columns(A)=#rows(B) static double[][] mult(double[][] A, double[][] B){ int i, k, j, n, p, q, m; n = A.length - 1; p = A[0].length - 1; q = B.length - 1; m = B[0].length - 1; if( p!=q ){ throw new RuntimeException("MatrixMultiply: mult: matrix dimensions do not match"); } double[][] P = new double[n+1][m+1]; for(i=1; i<=n; i++){ for(j=1; j<=m; j++){ P[i][j] = 0; for(k=1; k<=p; k++) P[i][j] += A[i][k]*B[k][j]; } } return P; } // printMatrix() // print Matrix A to file out static void printMatrix(FileOutputStream out, double[][] A) throws IOException{ int n = A.length - 1; int m = A[0].length - 1; StringBuffer sb = new StringBuffer(n + " " + m + "\n"); for(int i=1; i<=n; i++){ for(int j=1; j<=m; j++) sb.append(A[i][j] + " "); sb.append("\n"); } out.write(sb.toString().getBytes()); } // main() // read input file, build up the product one factor at a time, then append // the resulting matrix to the output file. public static void main(String[] args) throws IOException { int n, p, m, i, k, j; String line; StringTokenizer st; double[][] Product; double[][] A; // check command line arguments, open input and output files if( args.length!=2 ){ System.out.println("Usage: MatrixMultiply infile outfile"); System.exit(1); } BufferedReader in = new BufferedReader(new FileReader(args[0])); FileOutputStream out = new FileOutputStream(args[1], true); // read in first matrix, get it's dimensions st = new StringTokenizer(in.readLine()); n = Integer.parseInt(st.nextToken()); p = Integer.parseInt(st.nextToken()); // allocate Product to be of size (n+1)x(p+1), don't use index 0 Product = new double[n+1][p+1]; // read in each row for(i=1; i<=n; i++){ st = new StringTokenizer(in.readLine()); for(k=1; k<=p; k++){ Product[i][k] = Double.parseDouble(st.nextToken()); } } // read in remaining matrices, and build up Product st = new StringTokenizer((line=in.readLine())==null?" ":line); while(st.countTokens()>=2){ // there is another matrix to read // get it's dimensions p = Integer.parseInt(st.nextToken()); m = Integer.parseInt(st.nextToken()); // check that dimensions are compatible if( p != (Product[0].length - 1) ){ throw new RuntimeException("MatrixMultiply: matrix dimensions do not match"); } // allocate A to be of size (p+1)x(m+1), don't use index 0 A = new double[p+1][m+1]; // read in each row for(k=1; k<=p; k++){ st = new StringTokenizer(in.readLine()); for(j=1; j<=m; j++){ A[k][j] = Double.parseDouble(st.nextToken()); } } // build up Product by multiplying by A Product = mult(Product, A); // get dimensiions of the next matrix st = new StringTokenizer( (line=in.readLine())==null?" ":line ); } // close input file in.close(); // print Product to output file printMatrix(out, Product); // close output file out.close(); } }