https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_distCov@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 78 85 91.8 %
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 the implementation of procedures in [pm_distCov](@ref pm_distCov).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \AmirShahmoradi, Monday March 6, 2017, 3:22 pm, Institute for Computational Engineering and Sciences (ICES), The University of Texas at Austin.<br>
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      28             : #if     getCovRand_ENABLED && GRAM_ENABLED
      29             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      30             : 
      31             :         type(rngf_type) :: rng
      32             : #if     S0_ENABLED
      33        1434 :         if (present(scale)) then
      34          10 :             call setCovRand(rng, rand, scale)
      35             :         else
      36        1424 :             call setCovRand(rng, rand)
      37             :         end if
      38             : #elif   S1_ENABLED
      39          31 :         call setCovRand(rng, rand, scale)
      40             : #else
      41             : #error  "Unrecognized interface."
      42             : #endif
      43             : 
      44             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      45             : #elif   getCovRand_ENABLED && (DVINE_ENABLED || ONION_ENABLED)
      46             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      47             : 
      48             :         type(rngf_type) :: rng
      49             :         ! The onion method appears unstable, use the slower but more stable method for now.
      50             :         !type(onion_type) :: onion
      51             : #if     S0_ENABLED
      52             :         if (present(scale)) then
      53             :             call setCovRand(rng, rand, method, eta, scale)
      54             :         else
      55             :             call setCovRand(rng, rand, method, eta)
      56             :         end if
      57             : #elif   S1_ENABLED
      58             :         call setCovRand(rng, rand, method, eta, scale)
      59             : #else
      60             : #error  "Unrecognized interface."
      61             : #endif
      62             : #if     ONION_ENABLED
      63             :         if (onion%info /= 0_IK) error stop "@getCovRand(): The Cholesky factorization of the onion method failed."
      64             : #endif
      65             :         !call setMatCopy(rand(2:, 1:), rdpack, rand(1:, 2:), rdpack, uppDia)
      66             : 
      67             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      68             : #elif   getCovRand_ENABLED && GRAM_ENABLED
      69             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      70             : 
      71             : #error  "Unrecognized interface."
      72             : !        type(rngf_type) :: rng
      73             : !#if     S0_ENABLED
      74             : !        if (present(scale)) then
      75             : !            call setCovRand(rng, rand, scale)
      76             : !        else
      77             : !            call setCovRand(rng, rand)
      78             : !        end if
      79             : !#elif   S1_ENABLED
      80             : !        call setCovRand(rng, rand, scale)
      81             : !#else
      82             : !#error  "Unrecognized interface."
      83             : !#endif
      84             : 
      85             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      86             : #elif   setCovRand_ENABLED && GRAM_ENABLED
      87             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      88             : 
      89             :         real(TKC) :: normfac
      90             :         real(TKC), parameter :: EPS = 2 * sqrt(epsilon(0._TKC))
      91             :         ! Define the output kind.
      92             : #if     CK_ENABLED
      93             : #define TYPE_OF_RAND complex(TKC)
      94             : #define GET_CONJG(X)conjg(X)
      95             : #define GET_RE(X)X%re
      96             :         complex(TKC), parameter :: LB = -cmplx(1._TKC, 1._TKC, TKC), UB = cmplx(1._TKC, 1._TKC, TKC), ZERO = (0._TKC, 0._TKC), ONE = (1._TKC, 0._TKC)
      97             : #elif   RK_ENABLED
      98             : #define GET_RE(X)X
      99             : #define GET_CONJG(X)X
     100             : #define TYPE_OF_RAND real(TKC)
     101             :         real(TKC), parameter :: LB = -1._TKC, UB = 1._TKC, ZERO = 0._TKC, ONE = 1._TKC
     102             : #else
     103             : #error  "Unrecognized interface."
     104             : #endif
     105        1536 :         TYPE_OF_RAND :: upper(size(rand, 1, IK), size(rand, 2, IK))
     106             :         integer(IK) :: idim, jdim, ndim
     107             : #if     SD_ENABLED
     108             : #define GET_SCALED(X)X
     109             : #elif   S0_ENABLED
     110             : #define GET_SCALED(X)X * scaledSq
     111             :         real(TKC) :: scaledSq
     112          20 :         scaledSq = scale**2
     113          20 :         CHECK_ASSERTION(__LINE__, 0._TKC < scale, SK_"@setCovRand(): The condition `0. < scale` must hold. scale = "//getStr(scale))
     114             : #elif   S1_ENABLED
     115             : #define GET_SCALED(X)X * scale(idim) * scale(jdim)
     116         208 :         CHECK_ASSERTION(__LINE__, all([0._TKC < scale]), SK_"@setCovRand(): The condition `all([0. < scale])` must hold. scale = "//getStr(scale))
     117         246 :         CHECK_ASSERTION(__LINE__, size(scale, 1, IK) == size(rand, 1, IK), SK_"@setCovRand(): The condition `size(scale) == size(rand, 1, IK)` must hold. size(scale), shape(rand) = "//getStr([size(scale, 1, IK), shape(rand, IK)]))
     118             : #else
     119             : #error  "Unrecognized interface."
     120             : #endif
     121        1495 :         CHECK_ASSERTION(__LINE__, size(rand, 1, IK) == size(rand, 2, IK), SK_"@setCovRand(): The condition `size(rand, 1) == size(rand, 2)` must hold. shape(rand) = "//getStr(shape(rand, IK)))
     122             :         ndim = size(rand, 1, IK)
     123        1495 :         if (ndim < 1_IK) return
     124        7324 :         do idim = 1, ndim
     125             :             do
     126       34502 :                 call setUnifRand(rng, upper(1 : ndim, idim), LB, UB)
     127       34502 :                 normfac = real(sqrt(dot_product(upper(1 : ndim, idim), upper(1 : ndim, idim))), TKC) ! \todo: The performance of this expression can be improved by replacing `dot_product` with `absq()`.
     128        5833 :                 if (ZERO == normfac) cycle
     129           0 :                 exit
     130             :             end do
     131        4141 :             normfac = 1._TKC / normfac
     132       35993 :             upper(1 : ndim, idim) = upper(1 : ndim, idim) * normfac
     133             :         end do
     134      229352 :         rand = matmul(transpose(GET_CONJG(upper)), upper)
     135             :         ! Ensure the diagonals are all pure 1, free from numerical round-off errors.
     136        7324 :         do jdim = 1, ndim
     137        7324 :             rand(jdim, jdim) = ONE
     138             :         end do
     139             :         !block
     140             :         !   use pm_io
     141             :         !   call disp%show("rand")
     142             :         !   call disp%show( rand )
     143             :         !end block
     144             :         !call setCor(rand, uppDia, rand, uppDia)
     145             :         ! Rescale.
     146             : #if     S0_ENABLED || S1_ENABLED
     147         310 :         do jdim = 1, ndim
     148        1117 :             do idim = 1, jdim
     149        1060 :                 rand(idim, jdim) = GET_SCALED(rand(idim, jdim))
     150             :             end do
     151             :         end do
     152             : #endif
     153             :         !block
     154             :         !use pm_io, only: disp
     155             :         !call disp%show("rand")
     156             :         !call disp%show( rand )
     157             :         !end block
     158             :         ! copy to the lower triangle.
     159        1491 :         call setMatCopy(rand, rdpack, rand, rdpack, upp, transHerm)
     160             : #undef  TYPE_OF_RAND
     161             : #undef  GET_SCALED
     162             : #undef  GET_CONJG
     163             : #undef  GET_RE
     164             : 
     165             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     166             : #elif   setCovRand_ENABLED && (DVINE_ENABLED || ONION_ENABLED)
     167             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     168             : 
     169             : #define GET_INDEX(i,j) i, j
     170             : !#if     UXD_ENABLED
     171             : !#define GET_INDEX(i,j) j, i
     172             : !#elif   XLD_ENABLED
     173             : !#define GET_INDEX(i,j) i, j
     174             : !#else
     175             : !#error  "Unrecognized interface."
     176             : !#endif
     177             :         real(TKC) :: beta
     178             :         integer(IK) :: ndim, idim, jdim, kdim
     179             :         ! Set the scale
     180             : #if     SD_ENABLED
     181             :         real(TKC), parameter :: scaleSq = 1._TKC
     182             : #define GET_SCALED(x, i, j)
     183             : #else
     184             : #if     S0_ENABLED
     185             :         real(TKC) :: scaleSq
     186          20 :         scaleSq = scale * scale
     187             : #define GET_SCALED(x, i, j) x = x * scaleSq
     188             : #elif   S1_ENABLED
     189          12 :         CHECK_ASSERTION(__LINE__, size(scale, 1, IK) == size(rand, 1, IK), SK_"@setCovRand(): The condition `size(scale) == size(rand, 1, IK)` must hold. size(scale), shape(rand) = "//getStr([size(scale, 1, IK), shape(rand, IK)]))
     190             : #define GET_SCALED(x, i, j) x = x * scale(i) * scale(j)
     191             : #else
     192             : #error  "Unrecognized interface."
     193             : #endif
     194          38 :         CHECK_ASSERTION(__LINE__, all([0._TKC < scale]), SK_"@setCovRand(): The condition `all([0. < scale])` must hold. scale = "//getStr(scale))
     195             : #endif
     196          42 :         CHECK_ASSERTION(__LINE__, 0._TKC <= eta, SK_"@setCovRand(): The condition `0. <= eta` must hold. eta = "//getStr(eta))
     197             :        !CHECK_ASSERTION(__LINE__, 0_IK < size(rand, 1, IK), SK_"@setCovRand(): The condition `0 < size(rand, 1)` must hold. shape(rand) = "//getStr(shape(rand)))
     198          42 :         CHECK_ASSERTION(__LINE__, size(rand, 1, IK) == size(rand, 2, IK), SK_"@setCovRand(): The condition `size(rand, 1) <= size(rand, 2)` must hold. shape(rand) = "//getStr(shape(rand)))
     199             :         ndim = size(rand, 1, IK)
     200          42 :         if (1_IK < ndim) then
     201             : #if         ONION_ENABLED
     202          21 :             beta = eta + 0.5_TKC * ndim
     203             :             block
     204             :                 integer(IK) :: kdimp1
     205          42 :                 real(TKC) :: brand, ssnrandInv, chol(ndim - 1, ndim - 1), wrand(ndim - 1) ! sphere rv.
     206           0 :                 do
     207          21 :                     call setBetaRand(rng, brand, beta, beta)
     208          21 :                     if (0._TKC < brand .and. brand < 1._TKC) exit
     209             :                 end do
     210          21 :                 rand(1, 1) = 1._TKC
     211          21 :                 rand(2, 2) = 1._TKC
     212          21 :                 rand(1, 2) = 2._TKC * brand - 1._TKC
     213          57 :                 do kdim = 2_IK, ndim - 1_IK
     214          41 :                     call setNormRand(rng, wrand(1 : kdim))
     215         150 :                     ssnrandInv = 1._TKC / norm2(wrand(1 : kdim)) ! `wrand(1 : kdim) * ssnrandInv` would be a uniform random point on the surface of the kdim-sphere.
     216          41 :                     beta = beta - 0.5_TKC
     217             :                     do
     218          41 :                         call setBetaRand(rng, brand, 0.5_TKC * kdim, beta)
     219          41 :                         if (0._TKC < brand .and. brand < 1._TKC) exit
     220             :                     end do
     221          41 :                     ssnrandInv = ssnrandInv * sqrt(brand)
     222          41 :                     call setMatChol(rand, uppDia, method%info, chol, nothing, kdim, 0_IK, 0_IK, 0_IK, 0_IK)
     223          41 :                     if (method%info /= 0_IK) return
     224             :                     ! Compute z = cholow * wrand.
     225          36 :                     kdimp1 = kdim + 1
     226         128 :                     rand(1 : kdim, kdimp1) = 0._TKC
     227         128 :                     do jdim = 1, kdim
     228          92 :                         rand(jdim, kdimp1) = rand(jdim, kdimp1) + chol(jdim, jdim) * wrand(jdim) * ssnrandInv
     229         207 :                         do idim = jdim + 1, kdim
     230         171 :                             rand(idim, kdimp1) = rand(idim, kdimp1) + rand(idim, jdim) * rand(jdim, kdimp1)
     231             :                         end do
     232             :                     end do
     233          52 :                     rand(kdimp1, kdimp1) = 1._TKC
     234             :                     !block
     235             :                         !use pm_io, only: display_type
     236             :                         !type(display_type) :: disp
     237             :                         !call disp%skip
     238             :                         !call disp%show(rand(1 : kdimp1, 1 : kdimp1))
     239             :                         !call disp%skip
     240             :                     !end block
     241             :                 end do
     242          77 :                 do kdim = ndim, 1, -1
     243             : #if                 SD_ENABLED || S0_ENABLED
     244          61 :                     rand(kdim, kdim) = scaleSq
     245             : #elif               S1_ENABLED
     246           0 :                     rand(kdim, kdim) = rand(kdim, kdim) * scale(kdim) * scale(kdim)
     247             : #endif
     248         169 :                     do idim = kdim + 1, ndim
     249             : #if                     SD_ENABLED || S0_ENABLED
     250          92 :                         rand(kdim, idim) = rand(kdim, idim) * scaleSq
     251             : #elif                   S1_ENABLED
     252           0 :                         rand(kdim, idim) = rand(kdim, idim) * scale(idim) * scale(kdim)
     253             : #endif
     254         153 :                         rand(idim, kdim) = rand(kdim, idim)
     255             :                     end do
     256             :                 end do
     257             :                 !call setMatCopy(rand(2 : ndim, 1 : ndim), rdpack, rand(1 : ndim, 2 : ndim), rdpack, uppDia)
     258             :             end block
     259             :             !block
     260             :                 !use pm_io, only: display_type
     261             :                 !type(display_type) :: disp
     262             :                 !call disp%skip
     263             :                 !call disp%show(rand)
     264             :                 !call disp%skip
     265             :             !end block
     266             : #elif       DVINE_ENABLED
     267          21 :             beta = eta + 0.5_TKC * (ndim + 1_IK)
     268             :             block
     269          21 :                 real(TKC) :: parCorMat(size(rand, 1, IK), size(rand, 1, IK))
     270         509 :                 parCorMat = 0._TKC
     271          88 :                 do kdim = 1_IK, ndim - 1_IK
     272          67 :                     beta = beta - 0.5_TKC
     273             : #if                 SD_ENABLED || S0_ENABLED
     274          60 :                     rand(kdim, kdim) = scaleSq
     275             : #elif               S1_ENABLED
     276           7 :                     rand(kdim, kdim) = scale(kdim) * scale(kdim)
     277             : #endif
     278         244 :                     do idim = kdim + 1_IK, ndim
     279          67 :                         loopSensibleBeta: do
     280         156 :                             call setBetaRand(rng, parCorMat(kdim, idim), beta, beta)
     281         156 :                             if (0._TKC < parCorMat(kdim, idim) .and. parCorMat(kdim, idim) < 1._TKC) then
     282         156 :                                 parCorMat(kdim, idim) = 2 * parCorMat(kdim, idim) - 1._TKC ! Linearly shift to the range (-1, 1).
     283             :                                 ! Convert the partial correlations to full correlation.
     284         156 :                                 rand(GET_INDEX(kdim, idim)) = parCorMat(kdim, idim)
     285         314 :                                 do jdim = kdim - 1_IK, 1_IK, -1_IK
     286             :                                     rand(GET_INDEX(kdim, idim)) = parCorMat(jdim, idim) * parCorMat(jdim, kdim) + & ! LCOV_EXCL_LINE
     287         314 :                                     rand(GET_INDEX(kdim, idim)) * sqrt((1._TKC - parCorMat(jdim, idim)**2) * (1._TKC - parCorMat(jdim, kdim)**2))
     288             :                                 end do
     289          92 :                                 GET_SCALED(rand(GET_INDEX(kdim, idim)), idim, kdim)
     290         156 :                                 rand(GET_INDEX(idim, kdim)) = rand(GET_INDEX(kdim, idim))
     291             :                                 exit loopSensibleBeta
     292             :                             end if
     293             :                         end do loopSensibleBeta
     294             :                     end do
     295             :                 end do
     296             : #if             SD_ENABLED || S0_ENABLED
     297          20 :                 rand(kdim, kdim) = scaleSq
     298             : #elif           S1_ENABLED
     299           1 :                 rand(kdim, kdim) = scale(kdim) * scale(kdim)
     300             : #endif
     301             :             end block
     302             : #else
     303             : #error  "Unrecognized interface."
     304             : #endif
     305           0 :         elseif (1_IK == ndim) then
     306             : #if         SD_ENABLED || S0_ENABLED
     307           0 :             rand(1,1) = scaleSq
     308             : #elif       S1_ENABLED
     309           0 :             rand(1,1) = scale(1) * scale(1)
     310             : #endif
     311             :         end if
     312             : #if     ONION_ENABLED
     313          16 :         method%info = 0_IK
     314             : #endif
     315             : 
     316             : #else
     317             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     318             : #error  "Unrecognized interface."
     319             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     320             : #endif
     321             : #undef  GET_SCALED
     322             : #undef  GET_INDEX

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