blob: 762a5ee25505b3d09469967deed700815c4202e0 [file] [log] [blame]
package jnt.scimark2;
/**
LU matrix factorization. (Based on TNT implementation.)
Decomposes a matrix A into a triangular lower triangular
factor (L) and an upper triangular factor (U) such that
A = L*U. By convnetion, the main diagonal of L consists
of 1's so that L and U can be stored compactly in
a NxN matrix.
*/
public class LU
{
/**
Returns a <em>copy</em> of the compact LU factorization.
(useful mainly for debugging.)
@return the compact LU factorization. The U factor
is stored in the upper triangular portion, and the L
factor is stored in the lower triangular portion.
The main diagonal of L consists (by convention) of
ones, and is not explicitly stored.
*/
public static final double num_flops(int N) {
// rougly 2/3*N^3
double Nd = (double) N;
return (2.0 * Nd *Nd *Nd/ 3.0);
}
protected static double[] new_copy(double x[]) {
int N = x.length;
double T[] = new double[N];
for (int i=0; i<N; i++)
T[i] = x[i];
return T;
}
protected static double[][] new_copy(double A[][]) {
int M = A.length;
int N = A[0].length;
double T[][] = new double[M][N];
for (int i=0; i<M; i++) {
double Ti[] = T[i];
double Ai[] = A[i];
for (int j=0; j<N; j++)
Ti[j] = Ai[j];
}
return T;
}
public static int[] new_copy(int x[]) {
int N = x.length;
int T[] = new int[N];
for (int i=0; i<N; i++)
T[i] = x[i];
return T;
}
protected static final void insert_copy(double B[][], double A[][]) {
int M = A.length;
int N = A[0].length;
int remainder = N & 3; // N mod 4;
for (int i=0; i<M; i++) {
double Bi[] = B[i];
double Ai[] = A[i];
for (int j=0; j<remainder; j++)
Bi[j] = Ai[j];
for (int j=remainder; j<N; j+=4) {
Bi[j] = Ai[j];
Bi[j+1] = Ai[j+1];
Bi[j+2] = Ai[j+2];
Bi[j+3] = Ai[j+3];
}
}
}
public double[][] getLU() {
return new_copy(LU_);
}
/**
Returns a <em>copy</em> of the pivot vector.
@return the pivot vector used in obtaining the
LU factorzation. Subsequent solutions must
permute the right-hand side by this vector.
*/
public int[] getPivot() {
return new_copy(pivot_);
}
/**
Initalize LU factorization from matrix.
@param A (in) the matrix to associate with this
factorization.
*/
public LU( double A[][] ) {
int M = A.length;
int N = A[0].length;
//if ( LU_ == null || LU_.length != M || LU_[0].length != N)
LU_ = new double[M][N];
insert_copy(LU_, A);
//if (pivot_.length != M)
pivot_ = new int[M];
factor(LU_, pivot_);
}
/**
Solve a linear system, with pre-computed factorization.
@param b (in) the right-hand side.
@return solution vector.
*/
public double[] solve(double b[]) {
double x[] = new_copy(b);
solve(LU_, pivot_, x);
return x;
}
/**
LU factorization (in place).
@param A (in/out) On input, the matrix to be factored.
On output, the compact LU factorization.
@param pivit (out) The pivot vector records the
reordering of the rows of A during factorization.
@return 0, if OK, nozero value, othewise.
*/
public static int factor(double A[][], int pivot[]) {
int N = A.length;
int M = A[0].length;
int minMN = Math.min(M,N);
for (int j=0; j<minMN; j++) {
// find pivot in column j and test for singularity.
int jp=j;
double t = Math.abs(A[j][j]);
for (int i=j+1; i<M; i++) {
double ab = Math.abs(A[i][j]);
if ( ab > t) {
jp = i;
t = ab;
}
}
pivot[j] = jp;
// jp now has the index of maximum element
// of column j, below the diagonal
if ( A[jp][j] == 0 )
return 1; // factorization failed because of zero pivot
if (jp != j) {
// swap rows j and jp
double tA[] = A[j];
A[j] = A[jp];
A[jp] = tA;
}
if (j<M-1) // compute elements j+1:M of jth column
{
// note A(j,j), was A(jp,p) previously which was
// guarranteed not to be zero (Label #1)
//
double recp = 1.0 / A[j][j];
for (int k=j+1; k<M; k++)
A[k][j] *= recp;
}
if (j < minMN-1) {
// rank-1 update to trailing submatrix: E = E - x*y;
//
// E is the region A(j+1:M, j+1:N)
// x is the column vector A(j+1:M,j)
// y is row vector A(j,j+1:N)
for (int ii=j+1; ii<M; ii++) {
double Aii[] = A[ii];
double Aj[] = A[j];
double AiiJ = Aii[j];
for (int jj=j+1; jj<N; jj++)
Aii[jj] -= AiiJ * Aj[jj];
}
}
}
return 0;
}
/**
Solve a linear system, using a prefactored matrix
in LU form.
@param LU (in) the factored matrix in LU form.
@param pivot (in) the pivot vector which lists
the reordering used during the factorization
stage.
@param b (in/out) On input, the right-hand side.
On output, the solution vector.
*/
public static void solve(double LU[][], int pvt[], double b[]) {
int M = LU.length;
int N = LU[0].length;
int ii=0;
for (int i=0; i<M; i++) {
int ip = pvt[i];
double sum = b[ip];
b[ip] = b[i];
if (ii==0)
for (int j=ii; j<i; j++)
sum -= LU[i][j] * b[j];
else
if (sum == 0.0)
ii = i;
b[i] = sum;
}
for (int i=N-1; i>=0; i--) {
double sum = b[i];
for (int j=i+1; j<N; j++)
sum -= LU[i][j] * b[j];
b[i] = sum / LU[i][i];
}
}
private double LU_[][];
private int pivot_[];
}