package util.linalg;
import shared.Copyable;
/**
* A class representing a lower triangular matrix
* @author Andrew Guillory gtg008g@mail.gatech.edu
* @version 1.0
*/
public class LowerTriangularMatrix extends Matrix {
/**
* The number of rows in the matrix
*/
private int m;
/**
* The number of columns in the matrix
*/
private int n;
/**
* The data of the matrix
*/
private double[][] data;
/**
* Create a new square zero matrix that is
* restricted to be lower triangular
* @param m the row size of the matrix
*/
public LowerTriangularMatrix(int m) {
this(m,m);
}
/**
* Create a new zero matrix that is
* restricted to be lower triangular
* @param m the row size of the matrix
* @param n the column size of the matrix
*/
public LowerTriangularMatrix(int m, int n) {
this.m = m;
this.n = n;
data = new double[m][];
for (int i = 0; i < data.length; i++) {
data[i] = new double[Math.min(i + 1, n)];
}
}
/**
* Create a lower triangular matrix
* containing the lower triangular entries
* of the given matrix
* @param m the matrix to extract from
*/
public LowerTriangularMatrix(Matrix m) {
this(m.m(), m.n());
for (int i = 0; i < m(); i++) {
for (int j = 0; j <= i; j++) {
set(i,j, m.get(i,j));
}
}
}
/**
* @see linalg.Matrix#m()
*/
public int m() {
return m;
}
/**
* @see linalg.Matrix#n()
*/
public int n() {
return n;
}
/**
* @see linalg.Matrix#get(int, int)
*/
public double get(int i, int j) {
if (i < m() && j < n() && j > i) {
return 0;
} else {
return data[i][j];
}
}
/**
* @see linalg.Matrix#set(int, int, double)
*/
public void set(int i, int j, double d) {
if (!(i < m() && j < n() && j > i && d == 0)) {
data[i][j] = d;
}
}
/**
* Calculate the determinant
* @return the determinant
*/
public double determinant() {
int mnmin = Math.min(m(), n());
double d = 1;
for (int i = 0; i < mnmin; i++) {
d *= get(i,i);
}
return d;
}
/**
* @see linalg.Matrix#transpose()
*/
public Matrix transpose() {
UpperTriangularMatrix result = new UpperTriangularMatrix(n(), m());
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
result.set(j, i, data[i][j]);
}
}
return result;
}
/**
* Solve this upper triangular system for the
* given vector. Solves A*x = b for the given
* b.
* @param b the vector to solve for
* @return the solution vector
*/
public Vector solve(Vector b) {
b = (Vector) b.copy();
// solve by forward substiution
// overwriting the copy of b with the solution x
b.set(0, b.get(0) / get(0,0));
for (int i = 1; i < b.size(); i++) {
double sum = 0;
for (int j = 0; j < i; j++) {
sum += get(i, j) * b.get(j);
}
b.set(i, (b.get(i) - sum) / get(i,i));
}
return b;
}
/**
* Find the inverse of this matrix
* @return the inverse
*/
public LowerTriangularMatrix inverse() {
Vector[] columns = new Vector[n];
for (int i = 0; i < columns.length; i++) {
columns[i] = solve(DenseVector.e(i, m));
}
return new LowerTriangularMatrix(
RectangularMatrix.columns(columns));
}
/**
* @see linalg.Matrix#copy()
*/
public Copyable copy() {
LowerTriangularMatrix result = new LowerTriangularMatrix(m(), n());
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
result.data[i][j] = data[i][j];
}
}
return result;
}
}