fn_log_det.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright 2008-2016 Conrad Sanderson (http://conradsanderson.id.au)
  2. // Copyright 2008-2016 National ICT Australia (NICTA)
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // ------------------------------------------------------------------------
  15. //! \addtogroup fn_log_det
  16. //! @{
  17. //! log determinant of mat
  18. template<typename T1>
  19. inline
  20. void
  21. log_det
  22. (
  23. typename T1::elem_type& out_val,
  24. typename T1::pod_type& out_sign,
  25. const Base<typename T1::elem_type,T1>& X,
  26. const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
  27. )
  28. {
  29. arma_extra_debug_sigprint();
  30. arma_ignore(junk);
  31. typedef typename T1::elem_type eT;
  32. typedef typename T1::pod_type T;
  33. const bool status = auxlib::log_det(out_val, out_sign, X);
  34. if(status == false)
  35. {
  36. out_val = eT(Datum<T>::nan);
  37. out_sign = T(0);
  38. arma_debug_warn("log_det(): failed to find determinant");
  39. }
  40. }
  41. template<typename T1>
  42. inline
  43. void
  44. log_det
  45. (
  46. typename T1::elem_type& out_val,
  47. typename T1::pod_type& out_sign,
  48. const Op<T1,op_diagmat>& X,
  49. const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
  50. )
  51. {
  52. arma_extra_debug_sigprint();
  53. arma_ignore(junk);
  54. typedef typename T1::elem_type eT;
  55. typedef typename T1::pod_type T;
  56. const diagmat_proxy<T1> A(X.m);
  57. arma_debug_check( (A.n_rows != A.n_cols), "log_det(): given matrix must be square sized" );
  58. const uword N = (std::min)(A.n_rows, A.n_cols);
  59. if(N == 0)
  60. {
  61. out_val = eT(0);
  62. out_sign = T(1);
  63. return;
  64. }
  65. eT x = A[0];
  66. T sign = (is_cx<eT>::no) ? ( (access::tmp_real(x) < T(0)) ? -1 : +1 ) : +1;
  67. eT val = (is_cx<eT>::no) ? std::log( (access::tmp_real(x) < T(0)) ? x*T(-1) : x ) : std::log(x);
  68. for(uword i=1; i<N; ++i)
  69. {
  70. x = A[i];
  71. sign *= (is_cx<eT>::no) ? ( (access::tmp_real(x) < T(0)) ? -1 : +1 ) : +1;
  72. val += (is_cx<eT>::no) ? std::log( (access::tmp_real(x) < T(0)) ? x*T(-1) : x ) : std::log(x);
  73. }
  74. out_val = val;
  75. out_sign = sign;
  76. }
  77. template<typename T1>
  78. inline
  79. arma_warn_unused
  80. std::complex<typename T1::pod_type>
  81. log_det
  82. (
  83. const Base<typename T1::elem_type,T1>& X,
  84. const typename arma_blas_type_only<typename T1::elem_type>::result* junk = 0
  85. )
  86. {
  87. arma_extra_debug_sigprint();
  88. arma_ignore(junk);
  89. typedef typename T1::elem_type eT;
  90. typedef typename T1::pod_type T;
  91. eT out_val = eT(0);
  92. T out_sign = T(0);
  93. log_det(out_val, out_sign, X.get_ref());
  94. return (out_sign >= T(1)) ? std::complex<T>(out_val) : (out_val + std::complex<T>(T(0),Datum<T>::pi));
  95. }
  96. //! @}