All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ejml.dense.block.decomposition.chol.CholeskyOuterForm_DDRB Maven / Gradle / Ivy

/*
 * Copyright (c) 2009-2017, 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.dense.block.decomposition.chol;

import org.ejml.data.Complex_F64;
import org.ejml.data.DMatrixRBlock;
import org.ejml.data.DSubmatrixD1;
import org.ejml.dense.block.InnerRankUpdate_DDRB;
import org.ejml.dense.block.MatrixOps_DDRB;
import org.ejml.dense.block.TriangularSolver_DDRB;
import org.ejml.interfaces.decomposition.CholeskyDecomposition_F64;


/**
 * 

* Block Cholesky using outer product form. The original matrix is stored and modified. *

* *

* Based on the description provided in "Fundamentals of Matrix Computations" 2nd Ed. by David S. Watkins. *

* * @author Peter Abeles */ public class CholeskyOuterForm_DDRB implements CholeskyDecomposition_F64 { // if it should compute an upper or lower triangular matrix private boolean lower = false; // The decomposed matrix. private DMatrixRBlock T; // predeclare local work space private DSubmatrixD1 subA = new DSubmatrixD1(); private DSubmatrixD1 subB = new DSubmatrixD1(); private DSubmatrixD1 subC = new DSubmatrixD1(); // storage for the determinant private Complex_F64 det = new Complex_F64(); /** * Creates a new BlockCholeskyOuterForm * * @param lower Should it decompose it into a lower triangular matrix or not. */ public CholeskyOuterForm_DDRB(boolean lower) { this.lower = lower; } /** * Decomposes the provided matrix and stores the result in the same matrix. * * @param A Matrix that is to be decomposed. Modified. * @return If it succeeded or not. */ @Override public boolean decompose(DMatrixRBlock A) { if( A.numCols != A.numRows ) throw new IllegalArgumentException("A must be square"); this.T = A; if( lower ) return decomposeLower(); else return decomposeUpper(); } private boolean decomposeLower() { int blockLength = T.blockLength; subA.set(T); subB.set(T); subC.set(T); for( int i = 0; i < T.numCols; i += blockLength ) { int widthA = Math.min(blockLength, T.numCols-i); subA.col0 = i; subA.col1 = i+widthA; subA.row0 = subA.col0; subA.row1 = subA.col1; subB.col0 = i; subB.col1 = i+widthA; subB.row0 = i+widthA; subB.row1 = T.numRows; subC.col0 = i+widthA; subC.col1 = T.numRows; subC.row0 = i+widthA; subC.row1 = T.numRows; // cholesky on inner block A if( !InnerCholesky_DDRB.lower(subA)) return false; // on the last block these operations are not needed. if( widthA == blockLength ) { // B = L^-1 B TriangularSolver_DDRB.solveBlock(blockLength,false,subA,subB,false,true); // C = C - B * B^T InnerRankUpdate_DDRB.symmRankNMinus_L(blockLength,subC,subB); } } MatrixOps_DDRB.zeroTriangle(true,T); return true; } private boolean decomposeUpper() { int blockLength = T.blockLength; subA.set(T); subB.set(T); subC.set(T); for( int i = 0; i < T.numCols; i += blockLength ) { int widthA = Math.min(blockLength, T.numCols-i); subA.col0 = i; subA.col1 = i+widthA; subA.row0 = subA.col0; subA.row1 = subA.col1; subB.col0 = i+widthA; subB.col1 = T.numCols; subB.row0 = i; subB.row1 = i+widthA; subC.col0 = i+widthA; subC.col1 = T.numCols; subC.row0 = i+widthA; subC.row1 = T.numCols; // cholesky on inner block A if( !InnerCholesky_DDRB.upper(subA)) return false; // on the last block these operations are not needed. if( widthA == blockLength ) { // B = U^-1 B TriangularSolver_DDRB.solveBlock(blockLength,true,subA,subB,true,false); // C = C - B^T * B InnerRankUpdate_DDRB.symmRankNMinus_U(blockLength,subC,subB); } } MatrixOps_DDRB.zeroTriangle(false,T); return true; } @Override public boolean isLower() { return lower; } @Override public DMatrixRBlock getT(DMatrixRBlock T) { if( T == null ) return this.T; T.set(this.T); return T; } @Override public Complex_F64 computeDeterminant() { double prod = 1.0; int blockLength = T.blockLength; for( int i = 0; i < T.numCols; i += blockLength ) { // width of the submatrix int widthA = Math.min(blockLength, T.numCols-i); // index of the first element in the block int indexT = i*T.numCols + i*widthA; // product along the diagonal for (int j = 0; j < widthA; j++) { prod *= T.data[indexT]; indexT += widthA+1; } } det.real = prod*prod; det.imaginary = 0; return det; } @Override public boolean inputModified() { return true; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy