package util.linalg;
import java.io.Serializable;
import java.text.DecimalFormat;
import shared.Copyable;
/**
* A class representing a matrix, with linear algebra operations
* @author Andrew Guillory gtg008g@mail.gatech.edu
* @version 1.0
*/
public abstract class Matrix implements Serializable, Copyable {
/**
* Get the number of rows
* @return the number of rows
*/
public abstract int m();
/**
* Get the number of columns
* @return the number of colulmns
*/
public abstract int n();
/**
* Get a value
* @param i the row
* @param j the column
* @return the value
*/
public abstract double get(int i, int j);
/**
* Get a sub matrix from this matrix
* @param ia the starting row index (inclusive)
* @param ib the ending row index (exclusive)
* @param ja the starting column index (inclusive)
* @param jb the ending column index(exclusive)
* @return the sub matrix
*/
public Matrix get(int ia, int ib, int ja, int jb) {
double[][] result = new double[ib - ia][jb - ja];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++) {
result[i][j] = get(ia + i, ja + j);
}
}
return new RectangularMatrix(result);
}
/**
* Set a value
* @param i the row
* @param j the column
* @param d the new value
*/
public abstract void set(int i, int j, double d);
/**
* Set a block in this matrix equal to the given matrix
* @param i the top row of the block
* @param j the left most column of the block
* @param matrix the values to set the block with
*/
public void set(int i, int j, Matrix matrix) {
for (int row = i; row < matrix.m() + i; row++) {
for (int column = j; column < matrix.n() + j; column++) {
set(row, column, matrix.get(row - i,column - j));
}
}
}
/**
* Create the transpose of this matrix\
* @return the transpose
*/
public Matrix transpose() {
double[][] result = new double[n()][m()];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++) {
result[i][j] = get(j, i);
}
}
return new RectangularMatrix(result);
}
/**
* Get a column vector from this matrix
* @param index the index of the column to get
* @return the column vector
*/
public Vector getColumn(int index) {
double[] result = new double[m()];
for (int i = 0; i < result.length; i++) {
result[i] = get(i, index);
}
return new DenseVector(result);
}
/**
* Set a column of this matrix
* @param index the index
* @param v the vector
*/
public void setColumn(int index, Vector v) {
for (int i = 0; i < v.size(); i++) {
set(i, index, v.get(i));
}
}
/**
* Get a row vector from the matrix
* @param index the index of the row to get
* @return the row vector
*/
public Vector getRow(int index) {
double[] result = new double[n()];
for (int i = 0; i < result.length; i++) {
result[i] = get(index, i);
}
return new DenseVector(result);
}
/**
* Set a row of this matrix
* @param index the index
* @param v the vector
*/
public void setRow(int index, Vector v) {
for (int i = 0; i < v.size(); i++) {
set(index, i, v.get(i));
}
}
/**
* Multiply this matrix with another matrix
* @param matrix the other matrix
* @return the resulting matrix
*/
public Matrix times(Matrix matrix) {
double[][] result = new double[m()][matrix.n()];
for (int row = 0; row < result.length; row++) {
for (int column = 0; column < result[0].length; column++) {
for (int i = 0; i < n(); i++) {
result[row][column] +=
get(row,i) * matrix.get(i, column);
}
}
}
return new RectangularMatrix(result);
}
/**
* Multiply with a vector
* @param vector the vector to multiply by
* @return the result
*/
public Vector times(Vector vector) {
double[] result = new double[m()];
for (int row = 0; row < result.length; row++) {
for (int i = 0; i < n(); i++) {
result[row] += get(row, i) * vector.get(i);
}
}
return new DenseVector(result);
}
/**
* Multiply the matrix by a scale
* @param scale the scale
* @return the scaled matrix
*/
public Matrix times(double scale) {
Matrix result = (Matrix) copy();
result.timesEquals(scale);
return result;
}
/**
* Multiply this matrix in place by the given scale
* @param scale the scale to multiply by
*/
public void timesEquals(double scale) {
for (int i = 0; i < m(); i++) {
for (int j = 0; j < n(); j++) {
set(i, j, get(i,j) * scale);
}
}
}
/**
* Add this matrix with another matrix
* @param matrix the other matrix
* @return the resulting matrix
*/
public Matrix plus(Matrix matrix) {
double[][] result = new double[m()][n()];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++) {
result[i][j] = get(i,j) + matrix.get(i,j);
}
}
return new RectangularMatrix(result);
}
/**
* Add this matrix with another matrix in place
* @param matrix the other matrix to add
*/
public void plusEquals(Matrix matrix) {
for (int i = 0; i < m(); i++) {
for (int j = 0; j < n(); j++) {
set(i,j, get(i,j) + matrix.get(i,j));
}
}
}
/**
* Subtract this matrix with another matrix
* @param matrix the other matrix
* @return the resulting matrix
*/
public Matrix minus(Matrix matrix) {
double[][] result = new double[m()][n()];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[i].length; j++) {
result[i][j] = get(i,j) - matrix.get(i,j);
}
}
return new RectangularMatrix(result); }
/**
* Subtract from this matrix in place
* @param matrix the matrix to subtract
*/
public void minusEquals(Matrix matrix) {
for (int i = 0; i < m(); i++) {
for (int j = 0; j < n(); j++) {
set(i,j, get(i,j) - matrix.get(i,j));
}
}
}
/**
* Create and return a copy of this matrix
* @return the copy
*/
public Copyable copy() {
double[][] result = new double[m()][n()];
for (int i = 0; i < result.length; i++) {
for (int j = 0; j < result[0].length; j++) {
result[i][j] = get(i,j);
}
}
return new RectangularMatrix(result);
}
/**
* @see java.lang.Object#toString()
*/
public String toString() {
DecimalFormat df = new DecimalFormat("0.000000");
String result = "";
for (int i = 0; i < m(); i++) {
for (int j = 0; j < n(); j++) {
result += df.format(get(i,j)) + "\t";
}
result += "\n";
}
return result;
}
}