AnalysisSystemForRadionucli.../include/armadillo_bits/op_inv_meat.hpp
2024-06-04 15:25:02 +08:00

158 lines
3.1 KiB
C++

// Copyright (C) 2008-2015 National ICT Australia (NICTA)
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// -------------------------------------------------------------------
//
// Written by Conrad Sanderson - http://conradsanderson.id.au
//! \addtogroup op_inv
//! @{
//! immediate inverse of a matrix, storing the result in a dense matrix
template<typename eT>
inline
void
op_inv::apply(Mat<eT>& out, const Mat<eT>& A)
{
arma_extra_debug_sigprint();
// no need to check for aliasing, due to:
// - auxlib::inv() copies A to out before inversion
// - for 2x2 and 3x3 matrices the code is alias safe
bool status = auxlib::inv(out, A);
if(status == false)
{
out.reset();
arma_bad("inv(): matrix appears to be singular");
}
}
//! immediate inverse of T1, storing the result in a dense matrix
template<typename T1>
inline
void
op_inv::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_inv>& X)
{
arma_extra_debug_sigprint();
const strip_diagmat<T1> strip(X.m);
bool status;
if(strip.do_diagmat == true)
{
status = op_inv::apply_diagmat(out, strip.M);
}
else
{
status = auxlib::inv(out, X.m);
}
if(status == false)
{
out.reset();
arma_bad("inv(): matrix appears to be singular");
}
}
template<typename T1>
inline
bool
op_inv::apply_diagmat(Mat<typename T1::elem_type>& out, const T1& X)
{
arma_extra_debug_sigprint();
typedef typename T1::elem_type eT;
const diagmat_proxy<T1> A(X);
arma_debug_check( (A.n_rows != A.n_cols), "inv(): given matrix must be square sized" );
const uword N = (std::min)(A.n_rows, A.n_cols);
bool status = true;
if(A.is_alias(out) == false)
{
out.zeros(N,N);
for(uword i=0; i<N; ++i)
{
const eT val = A[i];
out.at(i,i) = eT(1) / val;
if(val == eT(0)) { status = false; }
}
}
else
{
Mat<eT> tmp(N, N, fill::zeros);
for(uword i=0; i<N; ++i)
{
const eT val = A[i];
tmp.at(i,i) = eT(1) / val;
if(val == eT(0)) { status = false; }
}
out.steal_mem(tmp);
}
return status;
}
//! inverse of T1 (triangular matrices)
template<typename T1>
inline
void
op_inv_tr::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_inv_tr>& X)
{
arma_extra_debug_sigprint();
const bool status = auxlib::inv_tr(out, X.m, X.aux_uword_a);
if(status == false)
{
out.reset();
arma_bad("inv(): matrix appears to be singular");
}
}
//! inverse of T1 (symmetric positive definite matrices)
template<typename T1>
inline
void
op_inv_sympd::apply(Mat<typename T1::elem_type>& out, const Op<T1,op_inv_sympd>& X)
{
arma_extra_debug_sigprint();
const bool status = auxlib::inv_sympd(out, X.m, X.aux_uword_a);
if(status == false)
{
out.reset();
arma_bad("inv_sympd(): matrix appears to be singular");
}
}
//! @}