LCOV - code coverage report
Current view: top level - source - CholeskyFactorization.cpp (source / functions) Hit Total Coverage
Test: LibForBES Unit Tests Lines: 48 59 81.4 %
Date: 2016-04-18 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* 
       2             :  * File:   CholeskyFactorization.cpp
       3             :  * Author: Pantelis Sopasakis
       4             :  * 
       5             :  * Created on August 4, 2015, 8:14 PM
       6             :  * 
       7             :  * ForBES is free software: you can redistribute it and/or modify
       8             :  * it under the terms of the GNU Lesser General Public License as published by
       9             :  * the Free Software Foundation, either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *  
      12             :  * ForBES is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      15             :  * GNU Lesser General Public License for more details.
      16             :  * 
      17             :  * You should have received a copy of the GNU Lesser General Public License
      18             :  * along with ForBES. If not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include "CholeskyFactorization.h"
      22             : 
      23           8 : CholeskyFactorization::CholeskyFactorization(Matrix& matrix) :
      24           8 : FactoredSolver(matrix) {
      25           8 :     m_L = NULL;
      26           8 :     m_factor = NULL;
      27           8 :     if (matrix.getNrows() != matrix.getNcols()){
      28           0 :         throw std::invalid_argument("CholeskyFactorization factorization can only be applied to square matrices");
      29             :     }
      30           8 :     if (matrix.getType() != Matrix::MATRIX_SPARSE) {
      31           6 :         this->m_L = new double[matrix.length()]();
      32             :     }
      33           8 : }
      34             : 
      35          21 : CholeskyFactorization::~CholeskyFactorization() {
      36           7 :     if (m_L != NULL) {
      37           5 :         delete[] m_L;
      38           5 :         m_L = NULL;
      39             :     }
      40           7 :     if (m_factor != NULL) {
      41           2 :         cholmod_free_factor(&m_factor, Matrix::cholmod_handle());
      42           2 :         m_factor = NULL;
      43             :     }
      44          14 : }
      45             : 
      46           8 : int CholeskyFactorization::factorize() {
      47           8 :     if (m_matrix_type == Matrix::MATRIX_SPARSE) {
      48             :         /* Cholesky decomposition of a SPARSE matrix: */
      49           2 :         if (m_matrix->m_sparse == NULL) {
      50           2 :             m_matrix->_createSparse();
      51             :         }
      52             :         /* analyze */
      53           2 :         m_factor = cholmod_analyze(m_matrix->m_sparse, Matrix::cholmod_handle());
      54             :         /* factorize */
      55           2 :         cholmod_factorize(m_matrix->m_sparse, m_factor, Matrix::cholmod_handle());
      56             :         /* Success: status = 0, else 1*/
      57           2 :         return (m_factor->minor == m_matrix->m_nrows) ? ForBESUtils::STATUS_OK : ForBESUtils::STATUS_NUMERICAL_PROBLEMS;
      58             :     } else { /* If this is any non-sparse matrix: */
      59           6 :         memcpy(m_L, m_matrix->getData(), m_matrix->length() * sizeof (double)); /* m_L := m_matrix.m_data */
      60           6 :         int info = ForBESUtils::STATUS_OK;
      61           6 :         if (m_matrix_type == Matrix::MATRIX_DENSE) { /* This is a dense matrix */
      62           4 :             info = LAPACKE_dpotrf(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, m_L, m_matrix_nrows);
      63             : #ifdef SET_L_OFFDIAG_TO_ZERO
      64             :             for (size_t i = 0; i < m_matrix_nrows; i++) {
      65             :                 for (size_t j = i + 1; j < m_matrix_nrows; j++) {
      66             :                     L.set(i, j, 0.0);
      67             :                 }
      68             :             }
      69             : #endif
      70           2 :         } else if (m_matrix_type == Matrix::MATRIX_SYMMETRIC) { /* This is a symmetric matrix */
      71           2 :             info = LAPACKE_dpptrf(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, m_L);
      72             :         }
      73           6 :         return info;
      74             :     }
      75             : }
      76             : 
      77          98 : int CholeskyFactorization::solve(Matrix& rhs, Matrix& solution) {
      78          98 :     if (m_matrix_type == Matrix::MATRIX_SPARSE) {
      79             :         cholmod_dense *x;
      80             : 
      81             :         /* cast the RHS as a cholmod_dense b = rhs */
      82           2 :         if (rhs.m_type == Matrix::MATRIX_DENSE) {
      83             : 
      84             :             cholmod_dense *b;
      85           2 :             b = cholmod_allocate_dense(rhs.m_nrows, rhs.m_ncols, rhs.m_nrows, CHOLMOD_REAL, Matrix::cholmod_handle());
      86           2 :             b->x = rhs.m_data;
      87             : 
      88             :             /* Solve - rhs is dense*/
      89           2 :             x = cholmod_solve(CHOLMOD_A, m_factor, b, Matrix::cholmod_handle());
      90           2 :             solution = Matrix(rhs.m_nrows, rhs.m_ncols);
      91           2 :             solution.m_delete_data = false;
      92           2 :             memcpy(solution.m_data, static_cast<double*> (x->x), rhs.m_nrows * rhs.m_ncols * sizeof (double));
      93           2 :             cholmod_free_dense(&x, Matrix::cholmod_handle());
      94             : 
      95           0 :         } else if (rhs.m_type == Matrix::MATRIX_SPARSE) {
      96             :             // still untested!
      97             :             cholmod_sparse * rhs_sparse;
      98           0 :             if (rhs.m_sparse == NULL) {
      99           0 :                 const_cast<Matrix&> (rhs)._createSparse();
     100             :             }
     101           0 :             rhs_sparse = rhs.m_sparse;
     102           0 :             cholmod_sparse * result = cholmod_spsolve(CHOLMOD_LDLt, m_factor, rhs_sparse, Matrix::cholmod_handle());
     103           0 :             solution = Matrix(rhs.m_nrows, rhs.m_ncols, Matrix::MATRIX_SPARSE);
     104           0 :             solution.m_sparse = result;
     105           0 :             solution._createTriplet();
     106             :         } else {
     107           0 :             throw std::logic_error("Not supported");
     108             :         }
     109           2 :         return ForBESUtils::STATUS_OK;
     110             :     } else { /* the matrix to be factorized is not sparse */
     111          96 :         int info = ForBESUtils::STATUS_UNDEFINED_FUNCTION;
     112          96 :         solution = Matrix(rhs);
     113          96 :         if (m_matrix_type == Matrix::MATRIX_DENSE) {
     114          85 :             info = LAPACKE_dpotrs(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, rhs.m_ncols, m_L, m_matrix_nrows, solution.m_data, m_matrix_nrows);
     115          11 :         } else if (m_matrix_type == Matrix::MATRIX_SYMMETRIC) {
     116          11 :             info = LAPACKE_dpptrs(LAPACK_COL_MAJOR, 'L', m_matrix_nrows, rhs.m_ncols, m_L, solution.m_data, m_matrix_nrows);
     117             :         } else {
     118           0 :             throw std::invalid_argument("This matrix type is not supported - only DENSE, SPARSE and SYMMETRIC are supported");
     119             :         }
     120          96 :         return info;
     121             :     }
     122             : }
     123             : 
     124             : 

Generated by: LCOV version 1.10