// Matrix.java
// a simple java file for a standard class

package math.utils;

// Imports

/**
 * class Matrix
 */
public class Matrix {

    // ===================================================================
    // constants

	/** The tolerance used for solving linear equations. Equal to 1e-14 by default.*/
	public static double tolerance = 1e-14;
	
    // ===================================================================
    // class variables

    /** The number of rows. */
    private int        nRows;
    /** The number of columns. */
    private int        nCols;

    /** The element array of the matrix. */
    private double[][] el;

    // ===================================================================
    // constructors

    /** Main constructor */

    /**
     * Constructs a new Matrix, with 1 row and 1 column, initialized to 1.
     */
    public Matrix() {
        this(1, 1);
    }

    /** Initializes a new Matrix with the given number of rows and columns. */
    public Matrix(int nbRows, int nbCols) {
        nRows = nbRows;
        nCols = nbCols;
        el = new double[nRows][nCols];
        setToIdentity();
    }

    /**
     * Constructs a new Matrix, initialized with the given coefficients.
     */
    public Matrix(double[][] coef) {
		if (coef == null) {
			nRows = 1;
			nCols = 1;
			el = new double[nRows][nCols];
			setToIdentity();
			return;
        }

		nRows = coef.length;
		nCols = coef[0].length;
		el = new double[nRows][nCols];
		for (int r = 0; r < nRows; r++)
			for (int c = 0; c < nCols; c++)
				el[r][c] = coef[r][c];
    }

    // ===================================================================
    // accessors

    /**
     * Returns the coef. row and col are between 1 and the number of rows and
     * columns.
     */
    public double getCoef(int row, int col) {
		return el[row - 1][col - 1];
    }

    /** Returns the number of rows. */
    public int getRows() {
        return nRows;
    }

    /** Returns the number of columns. */
    public int getColumns() {
        return nCols;
    }

    /**
     * Returns true if the matrix is square, i.e. the number of rows equals the
     * number of columns.
     */
    public boolean isSquare() {
		return (nCols == nRows);
    }

    // ===================================================================
    // modifiers

    /**
     * Sets the coef to the given value. row and col are between 1 and the number
     * of rows and columns.
     */
    public void setCoef(int row, int col, double coef) {
		el[row - 1][col - 1] = coef;
    }

    // ===================================================================
    // computation methods

    /**
     * Returns the result of the multiplication of the matrix with another one.
     * The content of the matrix is not modified.
     * @throws IllegalArgumentException if the size of matrices do not match
     */
    public Matrix multiplyWith(Matrix matrix) {

		// check sizes of the matrices
		if (nCols != matrix.nRows)
			throw new IllegalArgumentException("Matrix sizes do not match");
		
		double sum;
		Matrix m = new Matrix(nRows, matrix.nCols);

		for (int r = 0; r < m.nRows; r++)
			for (int c = 0; c < m.nCols; c++) {
				sum = 0;
				for (int i = 0; i < nCols; i++)
					sum += el[r][i] * matrix.el[i][c];
				m.el[r][c] = sum;
			}

        return m;
    }

    /**
     * Returns the result of the multiplication of the matrix with the given
     * vector. The content of the matrix is not modified.
     * @throws NullPointerException if input array is null
     * @throws IllegalArgumentException if size of vector and of matrix do not match
     */
    public double[] multiplyWith(double[] coefs) {

		if (coefs == null) {
			throw new NullPointerException();
		}

		// check sizes of matrix and vector
		if (coefs.length != nCols)
			throw new IllegalArgumentException("Matrix sizes do not match");

		double sum;
		double[] res = new double[nRows];

		for (int r = 0; r < nRows; r++) {
			sum = 0;
			for (int c = 0; c < nCols; c++)
				sum += el[r][c] * coefs[c];
			res[r] = sum;
		}
		return res;
    }

    /**
     * Returns the result of the multiplication of the matrix with the given
     * vector. The content of the matrix is not modified.
     * @throws NullPointerException if input vector is null
     * @throws IllegalArgumentException if size of vector and of matrix do not match
     */
    public double[] multiplyWith(double[] src, double[] res) {

		if (src == null)
			throw new NullPointerException();
		
		// check sizes of matrix and vector
		if (src.length != nCols) 
			throw new IllegalArgumentException("Matrix sizes do not match");

		if (src.length != res.length)
			res = new double[nRows];

		double sum;

		for (int r = 0; r < nRows; r++) {
			sum = 0;
			for (int c = 0; c < nCols; c++)
				sum += el[r][c] * src[c];
			res[r] = sum;
		}
		return res;
    }

    /** Transposes the matrix, changing the inner coefficients. */
    public void transpose() {
		int tmp = nCols;
		nCols = nRows;
		nRows = tmp;
		double[][] oldData = el;
		el = new double[nRows][nCols];

		for (int r = 0; r < nRows; r++)
			for (int c = 0; c < nCols; c++)
				el[r][c] = oldData[c][r];
    }

    /**
     * Returns the transposed matrix, without changing the inner coefficients
     * of the original matrix.
     */
    public Matrix getTranspose() {
        Matrix mat = new Matrix(nCols, nRows);

		for (int r = 0; r < nRows; r++)
			for (int c = 0; c < nCols; c++)
				mat.el[c][r] = el[r][c];
		return mat;
    }

    /**
     * Computes the solution of a linear system, using the Gauss-Jordan
     * algorithm. The inner coefficients of the matrix are not modified.
     * @throws NullPointerException if input vector is null
     * @throws IllegalArgumentException if size of vector and of matrix do not match
     * @throws UnsupportedOperationException if the matrix is not square
     * @throws ArithmeticException if the algorithm could not find pivot greater than tolerance
     */
    public double[] solve(double vector[]) {

		if (vector == null)
			throw new NullPointerException();
		
		if (vector.length != nRows) 
			throw new IllegalArgumentException("Matrix and vector dimensions do not match");
		
		if (nCols != nRows)
			throw new UnsupportedOperationException("Try to invert non square Matrix");
		
		double[] res = new double[vector.length];
		for (int i = 0; i < nRows; i++)
			res[i] = vector[i];

		// copy the matrix
        Matrix mat = new Matrix(el);

        int r, c; // row and column indices
        int p, r2; // pivot index, and secondary row index
        double pivot, tmp;

        // iterate on matrix lines
		for (r = 0; r < nRows; r++) {

            p = r;
            // look for the first non-null pivot
			while ((Math.abs(mat.el[p][r]) < Matrix.tolerance) && (p < nRows))
                p++;

			if (p == nRows)
				throw new ArithmeticException("Degenerated linear system");

            // swap the current line and the pivot
			for (c = 0; c < nRows; c++) {
				tmp = mat.el[r][c];
				mat.el[r][c] = mat.el[p][c];
				mat.el[p][c] = tmp;
			}

            // swap the corresponding values in the vector
            tmp = res[r];
            res[r] = res[p];
            res[p] = tmp;

            pivot = mat.el[r][r];

			// divide elements of the current line by the pivot
			for (c = r + 1; c < nRows; c++)
				mat.el[r][c] /= pivot;
			res[r] /= pivot;
			mat.el[r][r] = 1;

			// update other lines, before current line...
			for (r2 = 0; r2 < r; r2++) {
				pivot = mat.el[r2][r];
				for (c = r + 1; c < nRows; c++)
					mat.el[r2][c] -= pivot * mat.el[r][c];
				res[r2] -= pivot * res[r];
				mat.el[r2][r] = 0;
			}

            // and after current line
			for (r2 = r + 1; r2 < nRows; r2++) {
				pivot = mat.el[r2][r];
				for (c = r + 1; c < nRows; c++)
					mat.el[r2][c] -= pivot * mat.el[r][c];
				res[r2] -= pivot * res[r];
				mat.el[r2][r] = 0;
			}
		}

        return res;
    }

    // ===================================================================
    // general methods

    /**
     * Fills the matrix with zeros everywhere, except on the main diagonal,
     * filled with ones.
     */
	public void setToIdentity() {
		for (int r = 0; r < nRows; r++)
			for (int c = 0; c < nCols; c++)
				el[r][c] = 0;
		for (int i = Math.min(nRows, nCols) - 1; i >= 0; i--)
			el[i][i] = 1;
	}

    /**
     * Returns a String representation of the elements of the Matrix
     */
    @Override
	public String toString() {
		String res = new String("");
		res = res.concat("Matrix size : " + Integer.toString(nRows)
				+ " rows and " + Integer.toString(nCols) + " columns.\n");
		for (int r = 0; r < nRows; r++) {
			for (int c = 0; c < nCols; c++)
				res = res.concat(Double.toString(el[r][c])).concat(" ");
			res = res.concat(new String("\n"));
		}
		return res;
    }
}
 

Ads help maintain this website.