https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_matrixDet@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 54 67 80.6 %
Date: 2024-04-08 03:18:57 Functions: 0 0 -
Legend: Lines: hit not hit

          Line data    Source code
       1             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       2             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       3             : !!!!                                                                                                                            !!!!
       4             : !!!!    ParaMonte: Parallel Monte Carlo and Machine Learning Library.                                                           !!!!
       5             : !!!!                                                                                                                            !!!!
       6             : !!!!    Copyright (C) 2012-present, The Computational Data Science Lab                                                          !!!!
       7             : !!!!                                                                                                                            !!!!
       8             : !!!!    This file is part of the ParaMonte library.                                                                             !!!!
       9             : !!!!                                                                                                                            !!!!
      10             : !!!!    LICENSE                                                                                                                 !!!!
      11             : !!!!                                                                                                                            !!!!
      12             : !!!!       https://github.com/cdslaborg/paramonte/blob/main/LICENSE.md                                                          !!!!
      13             : !!!!                                                                                                                            !!!!
      14             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      15             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      16             : 
      17             : !>  \brief
      18             : !>  This include file contains procedure implementation of the generic interface [pm_matrixDet](@ref pm_matrixDet).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \AmirShahmoradi, Apr 21, 2017, 1:54 AM, Institute for Computational Engineering and Sciences (ICES), The University of Texas at Austin
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             : #if     CK_ENABLED
      28             : #define TYPE_KIND complex(TKC)
      29             : #define GET_CONJG(X) conjg(X)
      30             : #elif   RK_ENABLED
      31             : #define GET_CONJG(X) X
      32             : #define TYPE_KIND real(TKC)
      33             : #else
      34             : #error  "Unrecognized interface."
      35             : #endif
      36             :         ! Define the output variable.
      37             : #if     getMatDetSqrt_ENABLED || setMatDetSqrt_ENABLED
      38             : #define GETLOG(X) X
      39             : #define OUTPUT detSqrt
      40             : #define INCREMENT(X,Y) X = X * Y
      41             : #elif   getMatDetSqrtLog_ENABLED || setMatDetSqrtLog_ENABLED
      42             : #define GETLOG(X) log(X)
      43             : #define OUTPUT detSqrtLog
      44             : #define INCREMENT(X,Y) X = X + log(Y)
      45             : #elif   !(getMatDet_ENABLED || setMatDet_ENABLED)
      46             : #error  "Unrecognized interface."
      47             : #endif
      48             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      49             : #if     getMatDet_ENABLED || setMatDet_ENABLED
      50             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      51             : 
      52             : #if     getMatDet_ENABLED
      53             :         integer(IK) :: info
      54         260 :         TYPE_KIND :: matLUP(size(mat, 1, IK), size(mat, 2, IK))
      55             : #elif   setMatDet_ENABLED
      56             : #define matLUP mat
      57             : #else
      58             : #error  "Unrecognized interface."
      59             : #endif
      60             :         integer(IK) :: idim, ndim
      61          20 :         integer(IK) :: rperm(size(mat,1))
      62             :         ndim = size(mat, 1, IK)
      63         150 :         CHECK_ASSERTION(__LINE__, size(mat, 2, IK) == ndim, SK_"The input `mat` must be square. shape(mat) = "//getStr(shape(mat)))
      64             : #if     getMatDet_ENABLED
      65        4046 :         matLUP = mat
      66             : #endif
      67         150 :         call setMatLUP(matLUP, rperm, info) ! This returns det as +-1.
      68         150 :         if (info /= 0_IK) then
      69             : #if         getMatDet_ENABLED
      70             :             error stop "LU factorization failed." ! LCOV_EXCL_LINE
      71             : #elif       setMatDet_ENABLED
      72             :             return
      73             : #endif
      74             :         end if
      75          95 :         det = 1 ! parity
      76         834 :         do idim = 1_IK, ndim
      77         684 :             det = det * matLUP(idim, idim)
      78         834 :             if (rperm(idim) /= idim) det = -det
      79             :         end do
      80             : 
      81             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      82             : #elif   getMatDetSqrt_ENABLED || getMatDetSqrtLog_ENABLED
      83             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      84             : 
      85             : #if     getMatDetSqrt_ENABLED
      86             : #define SETDET(SUBSET) \
      87             : call setMatDetSqrt(mat, SUBSET, detSqrt, info, chol, nothing)
      88             : #elif   getMatDetSqrtLog_ENABLED
      89             : #define SETDET(SUBSET) \
      90             : call setMatDetSqrtLog(mat, SUBSET, detSqrtLog, info, chol, nothing)
      91             : #else
      92             : #error  "Unrecognized interface."
      93             : #endif
      94             :         integer(IK) :: info
      95      500204 :         TYPE_KIND :: chol(size(mat, 1, IK), size(mat, 2, IK))
      96      250102 :         if (size(mat, 1, IK) < 64_IK) then
      97             :             ! Use the unblocked algorithm from this module.
      98      250102 :             if (present(subset)) then
      99             :                 select type (subset)
     100             :                 type is (uppDia_type)
     101      250027 :                     SETDET(uppDia)
     102             :                 type is (lowDia_type)
     103          24 :                     SETDET(lowDia)
     104             :                 class default
     105             :                     error stop "Unrecognized `subset`. Only objects of `uppDia_type()` and `lowDia_type()` are recognized." ! LCOV_EXCL_LINE
     106             :                 end select
     107             :             else
     108          51 :                 SETDET(uppDia)
     109             :             end if
     110      250102 :             if (info /= 0_IK) error stop "The Cholesky factorization of small matrix failed."
     111             :         else
     112             :             ! Use the blocked algorithm potentially dispatched to LAPACK if available.
     113           0 :             if (present(subset)) then
     114             :                 select type (subset)
     115             :                 type is (uppDia_type)
     116           0 :                     call setMatCopy(chol, rdpack, mat, rdpack, uppDia)
     117           0 :                     call setMatChol(chol, uppDia, info, iteration)
     118             :                 type is (lowDia_type)
     119           0 :                     call setMatCopy(chol, rdpack, mat, rdpack, lowDia)
     120           0 :                     call setMatChol(chol, lowDia, info, iteration)
     121             :                 class default
     122             :                     error stop "Unrecognized `subset`. Only objects of `uppDia_type()` and `lowDia_type()` are recognized." ! LCOV_EXCL_LINE
     123             :                 end select
     124             :             else
     125           0 :                 call setMatCopy(chol, rdpack, mat, rdpack, uppDia)
     126           0 :                 call setMatChol(chol, uppDia, info, iteration)
     127             :             end if
     128           0 :             if (info /= 0_IK) error stop "The Cholesky factorization of large matrix failed."
     129           0 :             OUTPUT = GETLOG(real(chol(1, 1), TKC))
     130           0 :             do info = 2, size(chol, 1, IK)
     131           0 :                 INCREMENT(OUTPUT,real(chol(info, info), TKC))
     132             :             end do
     133             :             info = 0_IK
     134             :         end if
     135             : #undef  SETDET
     136             : 
     137             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     138             : #elif   setMatDetSqrt_ENABLED || setMatDetSqrtLog_ENABLED
     139             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     140             : 
     141             :         real(TKC) :: summ
     142             :         integer(IK) :: irow
     143             : !#if     IMP_ENABLED
     144             :         integer(IK) :: ndim
     145      250153 :         ndim = size(mat, 1, IK)
     146      750459 :         CHECK_ASSERTION(__LINE__, size(mat, 1, IK) == size(mat, 2, IK), SK_"@setMatChol(): The condition `size(mat, 1) == size(mat, 2)` must hold. ndim = "//getStr([size(mat, 1, IK), size(mat, 2, IK)]))
     147     2751683 :         CHECK_ASSERTION(__LINE__, all(shape(mat, IK) == shape(chol, IK)), SK_"@setMatChol(): The condition `all(shape(mat) == shape(chol))` must hold. shape(mat), shape(chol) = "//getStr([shape(mat, IK), shape(chol, IK)]))
     148             : !#elif   EXP_ENABLED
     149             : !        ! Ensure offsets and subset bounds are logical.
     150             : !        check_assertion(__LINE__, 0_IK <= ndim, SK_"@setMatChol(): The condition `0 <= ndim` must hold. ndim = "//getStr(ndim))
     151             : !        check_assertion(__LINE__, all(0_IK <= 1_IK - lbound(mat, kind = IK)), SK_"@setMatChol(): The condition `all(0 <= [roff, coff])` must hold. roff, coff = "//getStr(1_IK - lbound(mat)))
     152             : !        check_assertion(__LINE__, all(ndim <= ubound(mat, kind = IK)), SK_"@setMatChol(): The condition `ndim + [roff, coff] <= shape(mat)` must hold. ndim, roff, coff, shape(mat) = "//getStr([ndim, 1 - lbound(mat, kind = IK), shape(mat, kind = IK)]))
     153             : !        check_assertion(__LINE__, all(ndim <= ubound(chol, kind = IK)), SK_"@setMatChol(): The condition `ndim + [roffc, coffc] <= shape(chol)` must hold. ndim, roffc, coffc, shape(chol) = "//getStr([ndim, 1 - lbound(chol, kind = IK), shape(chol, kind = IK)]))
     154             : !#else
     155             : !#error  "Unrecognized interface."
     156             : !#endif
     157     3001836 :         CHECK_ASSERTION(__LINE__, all(ndim <= ubound(chol, kind = IK)), SK_"@setMatChol(): The condition `all(shape(mat) == shape(chol))` must hold. shape(mat), ubound(chol) = "//getStr([shape(mat, IK), ubound(chol, kind = IK)]))
     158             :         ! Define operations based on the specified triangular side.
     159             : #if     UXD_ENABLED
     160             : #define GET_MATMUL(I,J) matmul(J,I)
     161             : #define GETMAT(MAT,I,J) MAT(J,I)
     162             : #elif   XLD_ENABLED
     163             : #define GET_MATMUL(I,J) matmul(I,J)
     164             : #define GETMAT(MAT,I,J) MAT(I,J)
     165             : #else
     166             : #error  "Unrecognized interface."
     167             : #endif
     168      250153 :         if (1_IK < ndim) then
     169      250118 :             info = 1_IK
     170      250118 :             summ = real(mat(info, info), TKC)
     171      250118 :             if (0._TKC < summ) then
     172      250118 :                 summ = sqrt(summ)
     173      250118 :                 chol(info, info) = summ
     174      250118 :                 OUTPUT = GETLOG(summ)
     175      250118 :                 summ = 1._TKC / summ
     176             : #if             ONO_ENABLED
     177      500284 :                 do irow = info + 1, ndim
     178      500284 :                     GETMAT(chol, irow, info) = (GETMAT(mat, irow, info) - dot_product(GETMAT(chol, info, 1 : info - 1), GETMAT(chol, irow, 1 : info - 1))) * summ
     179             :                 end do
     180             : #elif           OTH_ENABLED
     181         122 :                 do irow = info + 1, ndim
     182         122 :                     GETMAT(chol, info, irow) = GET_CONJG(GETMAT(mat, irow, info) - dot_product(GETMAT(chol, 1 : info - 1, irow), GETMAT(chol, 1 : info - 1, info))) * summ
     183             :                 end do
     184             : #endif
     185      500406 :                 do info = 2_IK, ndim
     186             : #if                 ONO_ENABLED
     187      500628 :                     summ = real(mat(info, info), TKC) - real(dot_product(GETMAT(chol, info, 1 : info - 1), GETMAT(chol, info, 1 : info - 1)), TKC)
     188             : #elif               OTH_ENABLED
     189         222 :                     summ = real(mat(info, info), TKC) - real(dot_product(GETMAT(chol, 1 : info - 1, info), GETMAT(chol, 1 : info - 1, info)), TKC)
     190             : #else
     191             : #error              "Unrecognized interface."
     192             : #endif
     193      250288 :                     if (0._TKC < summ) then
     194      250288 :                         summ = sqrt(summ)
     195      250288 :                         chol(info, info) = summ
     196      250288 :                         INCREMENT(OUTPUT,summ)
     197      250288 :                         summ = 1._TKC / summ
     198             : #if                     ONO_ENABLED
     199             :                         !GETMAT(chol, info + 1 : ndim, info) = (GETMAT(mat, info + 1 : ndim, info) - GET_MATMUL(GET_CONJG(GETMAT(chol, info + 1 : ndim, 1 : info - 1)),GETMAT(chol, info, 1 : info - 1))) * summ
     200      250422 :                         do irow = info + 1, ndim
     201      250750 :                             GETMAT(chol, irow, info) = (GETMAT(mat, irow, info) - dot_product(GETMAT(chol, info, 1 : info - 1), GETMAT(chol, irow, 1 : info - 1))) * summ
     202             :                         end do
     203             : #elif                   OTH_ENABLED
     204         140 :                         do irow = info + 1, ndim
     205         218 :                             GETMAT(chol, info, irow) = (GET_CONJG(GETMAT(mat, irow, info) - dot_product(GETMAT(chol, 1 : info - 1, irow), GETMAT(chol, 1 : info - 1, info)))) * summ
     206             :                         end do
     207             : #endif
     208             :                         cycle
     209             :                     end if
     210      250118 :                     return
     211             :                 end do
     212      250118 :                 info = 0_IK
     213             :             end if
     214          35 :         elseif (1_IK == ndim) then
     215          35 :             summ = real(mat(1, 1), TKC)
     216          35 :             if (0._TKC < real(summ, TKC)) then
     217          35 :                 summ = sqrt(summ)
     218          35 :                 OUTPUT = GETLOG(summ)
     219          35 :                 chol(1,1) = summ
     220          35 :                 info = 0_IK
     221             :             else
     222           0 :                 info = 1_IK
     223             :             end if
     224             :         else
     225           0 :             info = 0_IK
     226             :         end if
     227             : #undef  GET_MATMUL
     228             : #undef  GETMAT
     229             : 
     230             : #else
     231             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     232             : #error  "Unrecognized interface."
     233             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     234             : #endif
     235             : #undef  INCREMENT
     236             : #undef  TYPE_KIND
     237             : #undef  GET_CONJG
     238             : #undef  OUTPUT
     239             : #undef  GETLOG
     240             : #undef  matLUP

ParaMonte: Parallel Monte Carlo and Machine Learning Library 
The Computational Data Science Lab
© Copyright 2012 - 2024