package util.linalg;
import shared.Copyable;
/**
* A class respresenting a upper triangular matrix
* @author Andrew Guillory gtg008g@mail.gatech.edu
* @version 1.0
*/
public class UpperTriangularMatrix extends Matrix {
/**
* The row size
*/
private int m;
/**
* The column size
*/
private int n;
/**
* The internal data storage
*/
private double[][] data;
/**
* Create a new square zero matrix that is
* restricted to be upper triangular
* @param m the row size of the matrix
*/
public UpperTriangularMatrix(int m) {
this(m,m);
}
/**
* Create a new zeroed square matrix of size m
* capable of only representing upper triangular matrices
* @param m the row size
* @param n the column size
*/
public UpperTriangularMatrix(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[n - i];
}
}
/**
* Create a upper triangular matrix
* containing the upper triangular entries
* of the given matrix
* @param m the matrix to extract from
*/
public UpperTriangularMatrix(Matrix m) {
this(m.m(), m.n());
for (int i = 0; i < m(); i++) {
for (int j = i; j < n(); 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() && i > j) {
return 0;
} else {
return data[i][j - i];
}
}
/**
* @see linalg.Matrix#set(int, int, double)
*/
public void set(int i, int j, double d) {
if (!(i < m() && j < n() && i > j && d == 0)) {
data[i][j - i] = d;
}
}
/**
* @see linalg.Matrix#transpose()
*/
public Matrix transpose() {
LowerTriangularMatrix result = new LowerTriangularMatrix(n(), m());
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
result.set(j + i, i, data[i][j]);
}
}
return result;
}
/**
* 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;
}
/**
* 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 with backward substitution
// overwriting the copy of b with the solution x
b.set(b.size() - 1, b.get(b.size() - 1) /
get(b.size() - 1, b.size() - 1));
for (int i = b.size() - 2; i >= 0; i--) {
double sum = 0;
for (int j = i+1; j < b.size(); 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 UpperTriangularMatrix inverse() {
Vector[] columns = new Vector[n];
for (int i = 0; i < columns.length; i++) {
columns[i] = solve(DenseVector.e(i, m));
}
return new UpperTriangularMatrix(
RectangularMatrix.columns(columns));
}
/**
* @see linalg.Matrix#copy()
*/
public Copyable copy() {
UpperTriangularMatrix result = new UpperTriangularMatrix(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;
}
}