/******************************* FILE HEADER **********************************
    Main Class File:  MatrixOps.java
    File:             MatrixOps.java
    
    Authors:          Patrick Votruba  email:  votruba@cs.wisc.edu
                      Nathan Burnett   email:  ncb@cs.wisc.edu
    
    Completion Date:  December 1, 2000
    Revision History: May 3, 2001, Nathan Burnett, added isRectangular()
                         Modified display() to handle non-rectangular arrays


    Course:           CS 302, Fall 2000
    TA:               N/A

    Compiler:         JDK 1.2
    Platform:         Solaris x86
 **************************** 80 columns wide *********************************/

class MatrixOps {
 
    /**
     * Tests a 2-D array for rectangularness     
     * @param array an array of ints to be tested
     * @return true iff all of the rows of array are the same length
     */

    public static boolean isRectangular(double [][] array) {
	int length = array[0].length;
	
	for (int i = 1; i < array.length; i++)
	    if (array[i].length != length) return false;
	return true;
    }

    /**
     * Adds two matrices of the same dimensions.  The two matrices
     * must have the same dimensions per the definition of matrix addition.
     * @param m1 first matrix
     * @param m2 second matrix
     * @return sum of m1 and m2
     */
    public static double[][] add (double[][] m1, double[][] m2) {
	
	double [][] temp = new double[m1.length][m1[0].length];

	for (int row = 0; row < m1.length; row++)
	    for (int col = 0; col < m1[0].length; col++)
		temp[row][col] = m1[row][col] + m2[row][col];

	return temp;
    }

    /**
     * Multiplies two matrices of the same dimensions.  The number of
     * columns in the first matrix must be equal to the number of rows
     * in the second matrix per the definition of matrix multiplication.
     * @param m1 first matrix
     * @param m2 second matrix
     * @return product of m1 and m2
     */
    public static double[][] multiply (double[][] m1, double[][] m2) {

	double[][] temp = new double[m2.length][m2[0].length];

	for (int i = 0; i < m2.length; i++)
	    for (int j = 0; j < m2[0].length; j++)
		for (int k = 0; k < m1.length; k++)
		    temp[i][j]+=(m1[i][k] * m2[k][j]);

	return temp;
    }

    /**
     * Displays a matrix to the console.
     * @param m the matrix to be displayed
     */
    public static void display (double[][] m) {
	System.out.println();
	for (int row = 0; row < m.length; row++) {
	    System.out.print("| ");
	    for (int col = 0; col < m[row].length; col++) {
		System.out.print(m[row][col] + " ");
	    }
	    System.out.println("|");
	}
	System.out.println();
    }

    public static void main (String [] args) {
	double[][] m1, m2, m3, result;

	int numRows, numCols;
	
	numRows = numCols = 3;

	m1 = new double[numRows][numCols];
	m2 = new double[numRows][numCols];

	// m3 will be an odd shape to test isRectangular
	m3 = new double[numRows][numCols];
	m3[1] = new double[10];
	m3[2] = new double[2];

	int num = 0;
	for (int row = 0; row < m1.length; row++)
	    for (int col = 0; col < m1[row].length; col++)
		m1[row][col] = ++num;

	for (int row = 0; row < m2.length; row++)
	    for (int col = 0; col < m2[row].length; col++)
		m2[row][col] = ++num;

	for (int row = 0; row < m3.length; row++)
	    for (int col = 0; col < m3[row].length; col++)
		m3[row][col] = ++num;

	System.out.println("Matrix M1");
	display(m1);
	if (isRectangular(m1))
	    System.out.println("M1 is rectangular");
	else
	    System.out.println("M1 is not rectangular");

	System.out.println("Matrix M2");
	display(m2);
	if (isRectangular(m2))
	    System.out.println("M2 is rectangular");
	else
	    System.out.println("M2 is not rectangular");

	System.out.println("Matrix M3");
	display(m3);
	if (isRectangular(m3))
	    System.out.println("M3 is rectangular");
	else
	    System.out.println("M3 is not rectangular");


	System.out.println("-----------------");
	System.out.println("Addition Example:");
	System.out.println("-----------------");
	display(m1);
	System.out.println("plus");
	display(m2);
	System.out.println("equals");
	result = add(m1, m2);
	display(result);

	num = 0;
	numCols = 2;
	m2 = new double[numRows][numCols];

	for (int i = 0; i < m2.length; i++)
	    for (int j = 0; j < m2[0].length; j++)
		m2[i][j] = ++num;

	System.out.println("-----------------------");
	System.out.println("Multiplication Example:");
	System.out.println("-----------------------");
	display(m1);
	System.out.println("times");
	display(m2);
	System.out.println("equals");
	result = multiply(m1, m2);
	display(result);

    } // end main

} // end class MatrixOps

