/*
 * Copyright (c) 2009-2014, Peter Abeles. All Rights Reserved.
 *
 * This file is part of Efficient Java Matrix Library (EJML).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ejml.alg.dense.decompose.lu;

import org.ejml.UtilEjml;
import org.ejml.alg.dense.decompose.CTriangularSolver;
import org.ejml.data.CDenseMatrix64F;
import org.ejml.data.Complex64F;
import org.ejml.interfaces.decomposition.LUDecomposition;
import org.ejml.ops.CCommonOps;
import org.ejml.ops.CSpecializedOps;


/**
 * 

* Contains common data structures and operations for LU decomposition algorithms. *

* @author Peter Abeles */ public abstract class LUDecompositionBase_CD64 implements LUDecomposition { // the decomposed matrix protected CDenseMatrix64F LU; // it can decompose a matrix up to this size protected int maxWidth=-1; // the shape of the matrix protected int m,n,stride; // data in the matrix protected double dataLU[]; // used in set, solve, invert protected double vv[]; // used in set protected int indx[]; protected int pivot[]; // used by determinant protected double pivsign; protected Complex64F det = new Complex64F(); public void setExpectedMaxSize( int numRows , int numCols ) { LU = new CDenseMatrix64F(numRows,numCols); this.dataLU = LU.data; maxWidth = Math.max(numRows,numCols); vv = new double[ maxWidth*2 ]; indx = new int[ maxWidth ]; pivot = new int[ maxWidth ]; } public CDenseMatrix64F getLU() { return LU; } public int[] getIndx() { return indx; } public int[] getPivot() { return pivot; } @Override public boolean inputModified() { return false; } /** * Writes the lower triangular matrix into the specified matrix. * * @param lower Where the lower triangular matrix is written to. */ @Override public CDenseMatrix64F getLower( CDenseMatrix64F lower ) { int numRows = LU.numRows; int numCols = LU.numRows < LU.numCols ? LU.numRows : LU.numCols; if( lower == null ) { lower = new CDenseMatrix64F(numRows,numCols); } else { if( lower.numCols != numCols || lower.numRows != numRows ) throw new IllegalArgumentException("Unexpected matrix dimension"); CCommonOps.fill(lower,0, 0); } for( int i = 0; i < numCols; i++ ) { lower.set(i,i,1.0,0.0); for( int j = 0; j < i; j++ ) { int indexLU = LU.getIndex(i,j); int indexL = lower.getIndex(i,j); double real = LU.data[indexLU]; double imaginary = LU.data[indexLU+1]; lower.data[indexL] = real; lower.data[indexL+1] = imaginary; } } if( numRows > numCols ) { for( int i = numCols; i < numRows; i++ ) { for( int j = 0; j < numCols; j++ ) { int indexLU = LU.getIndex(i,j); int indexL = lower.getIndex(i,j); double real = LU.data[indexLU]; double imaginary = LU.data[indexLU+1]; lower.data[indexL] = real; lower.data[indexL+1] = imaginary; } } } return lower; } /** * Writes the upper triangular matrix into the specified matrix. * * @param upper Where the upper triangular matrix is writen to. */ @Override public CDenseMatrix64F getUpper( CDenseMatrix64F upper ) { int numRows = LU.numRows < LU.numCols ? LU.numRows : LU.numCols; int numCols = LU.numCols; if( upper == null ) { upper = new CDenseMatrix64F(numRows, numCols); } else { if( upper.numCols != numCols || upper.numRows != numRows ) throw new IllegalArgumentException("Unexpected matrix dimension"); CCommonOps.fill(upper, 0,0); } for( int i = 0; i < numRows; i++ ) { for( int j = i; j < numCols; j++ ) { int indexLU = LU.getIndex(i,j); int indexU = upper.getIndex(i,j); double real = LU.data[indexLU]; double imaginary = LU.data[indexLU+1]; upper.data[indexU] = real; upper.data[indexU+1] = imaginary; } } return upper; } public CDenseMatrix64F getPivot( CDenseMatrix64F pivot ) { return CSpecializedOps.pivotMatrix(pivot, this.pivot, LU.numRows, false); } protected void decomposeCommonInit(CDenseMatrix64F a) { if( a.numRows > maxWidth || a.numCols > maxWidth ) { setExpectedMaxSize(a.numRows,a.numCols); } m = a.numRows; n = a.numCols; stride = n*2; LU.set(a); for (int i = 0; i < m; i++) { pivot[i] = i; } pivsign = 1; } /** * Determines if the decomposed matrix is singular. This function can return * false and the matrix be almost singular, which is still bad. * * @return true if singular false otherwise. */ @Override public boolean isSingular() { for( int i = 0; i < m; i++ ) { double real = dataLU[i*stride+i*2]; double imaginary = dataLU[i*stride+i*2+1]; double mag2 = real*real + imaginary*imaginary; if( mag2 < UtilEjml.EPS*UtilEjml.EPS ) return true; } return false; } /** * Computes the determinant from the LU decomposition. * * @return The matrix's determinant. */ @Override public Complex64F computeDeterminant() { if( m != n ) throw new IllegalArgumentException("Must be a square matrix."); double realRet = pivsign; double realImg = 0; int total = m*stride; for( int i = 0; i < total; i += stride + 2 ) { double real = dataLU[i]; double imaginary = dataLU[i+1]; double r = realRet*real - realImg*imaginary; double t = realRet*imaginary + realImg*real; realRet = r; realImg = t; } det.set(realRet,realImg); return det; } public double quality() { return CSpecializedOps.qualityTriangular(LU); } /** * a specialized version of solve that avoid additional checks that are not needed. */ public void _solveVectorInternal( double []vv ) { // Solve L*Y = B solveL(vv); // Solve U*X = Y; CTriangularSolver.solveU(dataLU, vv, n); } /** * Solve the using the lower triangular matrix in LU. Diagonal elements are assumed * to be 1 */ protected void solveL(double[] vv) { int ii = 0; for( int i = 0; i < n; i++ ) { int ip = indx[i]; double sumReal = vv[ip*2]; double sumImg = vv[ip*2+1]; vv[ip*2] = vv[i*2]; vv[ip*2+1] = vv[i*2+1]; if( ii != 0 ) { // for( int j = ii-1; j < i; j++ ) // sum -= dataLU[i* n +j]*vv[j]; int index = i*stride + (ii-1)*2; for( int j = ii-1; j < i; j++ ){ double luReal = dataLU[index++]; double luImg = dataLU[index++]; double vvReal = vv[j*2]; double vvImg = vv[j*2+1]; sumReal -= luReal*vvReal - luImg*vvImg; sumImg -= luReal*vvImg + luImg*vvReal; } } else if( sumReal*sumReal + sumImg*sumImg != 0.0 ) { ii=i+1; } vv[i*2] = sumReal; vv[i*2+1] = sumImg; } } public double[] _getVV() { return vv; } }

Ads help maintain this website.