https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_distanceEuclid@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 62 63 98.4 %
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 file contains implementations of procedures [pm_distanceEuclid](@ref pm_distanceEuclid).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \AmirShahmoradi, September 1, 2017, 12:00 AM, Institute for Computational Engineering and Sciences (ICES), The University of Texas at Austin
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      28             : #if     getDisEuclid_ENABLED && XYZ_ENABLED
      29             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      30             : 
      31             :         real(TKC) :: absx, absy, absz, maximum
      32           2 :         absx = abs(x)
      33           2 :         absy = abs(y)
      34           2 :         absz = abs(z)
      35           2 :         maximum = max(absx, absy, absz)
      36           2 :         if(maximum == 0._TKC .or. maximum > huge(maximum)) then
      37             :             ! maximum can be zero for max(0,nan,0) adding all three entries together will make sure nan will not disappear.
      38           0 :             distance = absx + absy + absz
      39             :         else
      40           2 :             distance = maximum * sqrt((absx / maximum)**2 + (absy / maximum)**2 + (absz / maximum)**2)
      41             :         end if
      42             : 
      43             :         !%%%%%%%%%%%%%%%%%%%
      44             : #elif   getDisEuclid_ENABLED
      45             :         !%%%%%%%%%%%%%%%%%%%
      46             : 
      47             : #if     D1_D1_ENABLED || D1_D2_ENABLED || D2_D1_ENABLED || D2_D2_ENABLED
      48             : #define REF ref,
      49             : #elif   D1_XX_ENABLED || D2_XX_ENABLED
      50             : #define REF
      51             : #else
      52             : #error  "Unrecognized interface."
      53             : #endif
      54       28593 :         if (present(method)) then
      55             :             select type (method)
      56             :             type is (euclid_type)
      57        9529 :                 call setDisEuclid(distance, point, REF method)
      58             :             type is (euclidu_type)
      59        9529 :                 call setDisEuclid(distance, point, REF method)
      60             :             type is (euclidsq_type)
      61        9529 :                 call setDisEuclid(distance, point, REF method)
      62             :             class default
      63             :                 error stop MODULE_NAME//SK_"@getDisEuclid(): Unsupported input value for `method`." ! LCOV_EXCL_LINE
      64             :             end select
      65        6000 :             return
      66             :         end if
      67           6 :         call setDisEuclid(distance, point, REF euclid)
      68             : #undef  REF
      69             : 
      70             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      71             : #elif   setDisEuclid_ENABLED && (D1_XX_ENABLED || D1_D1_ENABLED)
      72             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      73             : 
      74             :         integer(IK) :: idim
      75             : #if     D1_XX_ENABLED
      76             : #define GET_DIFF(PNT,REF)PNT
      77             : #elif   D1_D1_ENABLED
      78             : #define GET_DIFF(PNT,REF)(PNT - REF)
      79    13579266 :         CHECK_ASSERTION(__LINE__, size(point, 1, IK) == size(ref, 1, IK), SK_"@setDisEuclid(): The condition `size(point) == size(ref)` must hold. size(point), size(ref) = "//getStr([size(point, 1, IK), size(ref, 1, IK)]))
      80             : #else
      81             : #error  "Unrecognized interface."
      82             : #endif
      83             : #if     MED_ENABLED
      84             :         block
      85             :             real(TKC) :: invmax, maximum
      86             :             ! First find the maximum.
      87      757585 :             maximum = -huge(maximum)
      88     9976976 :             do idim = 1_IK, size(point, 1, IK)
      89     8444552 :                 invmax = abs(GET_DIFF(point(idim),ref(idim))) ! placeholder.
      90     9976976 :                 if (maximum < invmax) maximum = invmax
      91             :             end do
      92     1532424 :             if(maximum == 0._TKC .or. huge(maximum) < maximum) then
      93      248366 :                 distance = sum(GET_DIFF(point,ref)) ! Ensure propagation of potential nan in the vector.
      94             :             else
      95     1494278 :                 distance = 0._TKC
      96     1494278 :                 invmax = 1._TKC / maximum
      97     9728610 :                 do idim = 1_IK, size(point, 1, IK)
      98     9728610 :                     distance = distance + (GET_DIFF(point(idim),ref(idim)) * invmax)**2
      99             :                 end do
     100     1494278 :                 distance = maximum * sqrt(distance)
     101             :             end if
     102             :         end block
     103             : #elif   MEU_ENABLED || MEQ_ENABLED
     104     3017333 :         distance = 0._TKC
     105    19950818 :         do idim = 1_IK, size(point, 1, IK)
     106    19950818 :             distance = distance + GET_DIFF(point(idim),ref(idim))**2
     107             :         end do
     108             : #if     MEU_ENABLED
     109     1531923 :         distance = sqrt(distance)
     110             : #endif
     111             : #else
     112             : #error  "Unrecognized interface."
     113             : #endif
     114             : #undef  GET_DIFF
     115             : 
     116             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     117             : #elif   setDisEuclid_ENABLED && D1_D2_ENABLED
     118             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     119             : 
     120             :         integer(IK) :: iref, ndim
     121      285225 :         ndim = size(point, 1, IK)
     122     1711350 :         CHECK_ASSERTION(__LINE__, size(ref, 2, IK) == size(distance, 1, IK), SK_"@getDisEuclid(): The condition `size(ref, 2) == size(distance)` must hold. shape(ref), size(distance) = "//getStr([shape(ref, IK), size(distance, 1, IK)]))
     123     3291138 :         do iref = 1_IK, size(ref, 2, IK)
     124     3291138 :             call setDisEuclid(distance(iref), point, ref(1:ndim, iref), method)
     125             :         end do
     126             : 
     127             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     128             : #elif   setDisEuclid_ENABLED && (D2_XX_ENABLED || D2_D1_ENABLED)
     129             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     130             : 
     131             :         integer(IK) :: ipnt, ndim
     132       12002 :         ndim = size(point, 1, IK)
     133       72012 :         CHECK_ASSERTION(__LINE__, size(point, 2, IK) == size(distance, 1, IK), SK_"@getDisEuclid(): The condition `size(point, 2) == size(distance)` must hold. shape(point), size(distance) = "//getStr([shape(point, IK), size(distance, 1, IK)]))
     134      137246 :         do ipnt = 1_IK, size(point, 2, IK)
     135             : #if         D2_XX_ENABLED
     136       69997 :             call setDisEuclid(distance(ipnt), point(1:ndim, ipnt), method)
     137             : #elif       D2_D1_ENABLED
     138       67249 :             call setDisEuclid(distance(ipnt), point(1:ndim, ipnt), ref, method)
     139             : #else
     140             : #error      "Unrecognized interface."
     141             : #endif
     142             :         end do
     143             : 
     144             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     145             : #elif   setDisEuclid_ENABLED && D2_D2_ENABLED
     146             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     147             : 
     148             :         integer(IK) :: ipnt, ndim, nref
     149       16682 :         nref = size(ref, 2, IK)
     150       16682 :         ndim = size(point, 1, IK)
     151      250230 :         CHECK_ASSERTION(__LINE__, all(shape(distance, IK) == [nref, size(point, 2, IK)]), SK_"@getDisEuclid(): The condition `all(shape(distance) == [size(ref, 2), size(point, 2)])` must hold. shape(distance), shape(ref), shape(point) = "//getStr([shape(distance, IK), shape(ref, IK), shape(point, IK)]))
     152      192451 :         do ipnt = 1_IK, size(point, 2, IK)
     153      192451 :             call setDisEuclid(distance(1 : nref, ipnt), point(1 : ndim, ipnt), ref, method)
     154             :         end do
     155             : 
     156             :         !%%%%%%%%%%%%%%%%%%%%%%
     157             : #elif   getDisMatEuclid_ENABLED
     158             :         !%%%%%%%%%%%%%%%%%%%%%%
     159             : 
     160             : #if     FUL_ENABLED
     161             :         type(rdpack_type), parameter :: pack = rdpack_type()
     162             :         type(uppLowDia_type), parameter :: subset = uppLowDia_type()
     163             : #endif
     164        9660 :         if (present(method)) then
     165             :             select type (method)
     166             :             type is (euclidsq_type)
     167        3215 :                 call setDisMatEuclid(distance, pack, subset, point, method)
     168             :             type is (euclidu_type)
     169        3205 :                 call setDisMatEuclid(distance, pack, subset, point, method)
     170             :             type is (euclid_type)
     171        3210 :                 call setDisMatEuclid(distance, pack, subset, point, method)
     172             :             class default
     173             :                 error stop MODULE_NAME//SK_"@getDisMatEuclid(): Unsupported input value for `method`." ! LCOV_EXCL_LINE
     174             :             end select
     175             :             return
     176             :         end if
     177          30 :         call setDisMatEuclid(distance, pack, subset, point, euclid)
     178             : 
     179             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     180             : #elif   setDisMatEuclid_ENABLED && RDP_ENABLED && ULD_ENABLED
     181             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     182             : 
     183             :         ! Construct the full distance matrix.
     184             :         integer(IK) :: ndim, npnt
     185             :         integer(IK) :: ipnt, jpnt
     186       10845 :         ndim = size(point, 1, IK)
     187       10845 :         npnt = size(point, 2, IK)
     188      119295 :         CHECK_ASSERTION(__LINE__, all(shape(distance, IK) == [npnt, npnt]), \
     189             :         SK_"@setDisMatEuclid(): The condition `all(shape(distance) == shape(point))` must hold. shape(distance), shape(point) = "//getStr([shape(distance, IK), shape(point, IK)]))
     190      125407 :         do jpnt = 1_IK, npnt
     191      114562 :             distance(jpnt, jpnt) = 0._TKC
     192      852036 :             do ipnt = jpnt + 1, npnt
     193             :                 ! construct the lower triangle element and transpose to upper triangle.
     194      726629 :                 call setDisEuclid(distance(ipnt, jpnt), point(1 : ndim, ipnt), point(1 : ndim, jpnt), method)
     195      841191 :                 distance(jpnt, ipnt) = distance(ipnt, jpnt)
     196             :             end do
     197             :         end do
     198             : 
     199             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     200             : #elif   setDisMatEuclid_ENABLED && RDP_ENABLED && ULX_ENABLED
     201             :         !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     202             : 
     203             :         ! Construct the full distance matrix excluding diagonal.
     204             :         integer(IK), parameter :: doff = 1_IK ! diagonal offset.
     205             :         integer(IK) :: ndim, npnt
     206             :         integer(IK) :: ipnt, jpnt
     207       10845 :         ndim = size(point, 1, IK)
     208       10845 :         npnt = size(point, 2, IK)
     209      119295 :         CHECK_ASSERTION(__LINE__, all(shape(distance, IK) == [npnt - 1_IK, npnt]), \
     210             :         SK_"@setDisMatEuclid(): The condition `all(shape(distance) == [size(point, 2) - 1_IK, size(point, 2)])` must hold. shape(distance), shape(point) = "//\
     211             :         getStr([shape(distance, IK), shape(point, IK)]))
     212      125407 :         do jpnt = 1_IK, npnt
     213      852036 :             do ipnt = jpnt + 1, npnt
     214             :                 ! construct the lower triangle element and transpose to upper triangle.
     215      726629 :                 call setDisEuclid(distance(ipnt - doff, jpnt), point(1 : ndim, ipnt), point(1 : ndim, jpnt), method)
     216      841191 :                 distance(jpnt, ipnt) = distance(ipnt - doff, jpnt)
     217             :             end do
     218             :         end do
     219             : #else
     220             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     221             : #error  "Unrecognized interface."
     222             :         !%%%%%%%%%%%%%%%%%%%%%%%%
     223             : #endif
     224             : !        !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     225             : !#elif   getDisEuclid_ENABLED && (PNT_ENABLED || REF_ENABLED)
     226             : !        !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     227             : !
     228             : !        integer(IK) :: i
     229             : !        real(TKC)   :: invmax
     230             : !        real(TKC)   :: maximum
     231             : !#if     REF_ENABLED
     232             : !        real(TKC)   :: diff(size(point, 1, IK))
     233             : !        CHECK_ASSERTION(__LINE__, size(point, 1, IK) == size(ref, 1, IK), SK_"@getDisEuclid(): The condition `size(point) == size(ref)` must hold. size(point), size(ref) = "//getStr([size(point, 1, IK) == size(ref, 1, IK)]))
     234             : !#else
     235             : !#define DIFF point
     236             : !#endif
     237             : !        maximum = -huge(maximum)
     238             : !        do i = 1_IK, size(point, 1, IK)
     239             : !#if         PNT_ENABLED
     240             : !            invmax = abs(point(i))
     241             : !            if (maximum < invmax) maximum = invmax
     242             : !#elif       REF_ENABLED
     243             : !            diff(i) = abs(point(i) - ref(i))
     244             : !            if (maximum < diff(i)) maximum = diff(i)
     245             : !#else
     246             : !#error      "Unrecognized interface."
     247             : !#endif
     248             : !        end do
     249             : !        if(maximum == 0._TKC .or. maximum > huge(maximum)) then
     250             : !            distance = sum(point) ! Ensure propagation of potential nan in the vector.
     251             : !        else
     252             : !            distance = 0._TKC
     253             : !            invmax = 1._TKC / maximum
     254             : !            do i = 1_IK, size(point, 1, IK)
     255             : !                distance = distance + (DIFF(i) * invmax)**2
     256             : !            end do
     257             : !            distance = maximum * sqrt(distance)
     258             : !        end if
     259             : !
     260             : !        !%%%%%%%%%%%%%%%%%%%%%%%
     261             : !#elif   getDisMatEuclid_ENABLED
     262             : !        !%%%%%%%%%%%%%%%%%%%%%%%
     263             : !
     264             : !!#if     LFP_ENABLED
     265             : !!#define OPTIONAL_ARG
     266             : !!#elif   Sym_ENABLED
     267             : !!#define OPTIONAL_ARG diag,
     268             : !!#elif   REF_ENABLED
     269             : !!#define OPTIONAL_ARG ref,
     270             : !!#else
     271             : !!#error  "Unrecognized interface."
     272             : !!#endif
     273             : !        if (present(method)) then
     274             : !            select type (method)
     275             : !            type is (euclidsq_type)
     276             : !                call setDisMatEuclid(distance, point, OPTIONAL_ARG euclidsq)
     277             : !                return
     278             : !            type is (euclidu_type)
     279             : !                call setDisMatEuclid(distance, point, OPTIONAL_ARG euclidu)
     280             : !                return
     281             : !                call setDisMatEuclid(distance, point, OPTIONAL_ARG euclid)
     282             : !            end select
     283             : !        end if
     284             : !        ! type is (euclid_type)
     285             : !        call setDisMatEuclid(distance, point, OPTIONAL_ARG euclidu)
     286             : !#endif
     287             : !
     288             : !        !%%%%%%%%%%%%%%%%%%%%%%%
     289             : !#elif   setDisMatEuclid_ENABLED
     290             : !        !%%%%%%%%%%%%%%%%%%%%%%%
     291             : !
     292             : !        integer(IK) :: idim
     293             : !
     294             : !        !%%%%%%%%%%%%%%%%%%%%%%%
     295             : !#elif   setDisMatEuclid_ENABLED
     296             : !        !%%%%%%%%%%%%%%%%%%%%%%%
     297             : !
     298             : !        integer(IK) :: ndim, npnt
     299             : !        integer(IK) :: ipnt, jref
     300             : !#if     MUF_ENABLED || MEQ_ENABLED
     301             : !        integer(IK) :: idim
     302             : !#endif
     303             : !#if     LFP_ENABLED
     304             : !        integer(IK) :: indx
     305             : !        indx = 0_IK
     306             : !#endif
     307             : !        ndim = size(point, 1, IK)
     308             : !        npnt = size(point, 2, IK)
     309             : !#if     DEF_ENABLED || ULD_ENABLED
     310             : !#define REFERENCE point
     311             : !#define LBND jref + 1_IK
     312             : !#define NREF npnt
     313             : !#elif   REF_ENABLED
     314             : !#define NREF size(ref, 2, IK)
     315             : !#define REFERENCE ref
     316             : !#define LBND 1_IK
     317             : !        CHECK_ASSERTION(__LINE__, ndim == size(ref, 1, IK), SK_"@setDisMatEuclid(): The condition `size(point, 1) == size(ref, 1)` must hold. size(point, 1), size(ref, 1) = "//getStr([ndim, size(ref, 1, IK)]))
     318             : !#else
     319             : !#error  "Unrecognized interface."
     320             : !#endif
     321             : !        ! \warning
     322             : !        ! This loops is well-reasoned. Do not change it blindly.
     323             : !        do jref = 1_IK, NREF
     324             : !#if         Sym_ENABLED
     325             : !            distance(jref, jref) = diag
     326             : !#endif
     327             : !            do ipnt = LBND, npnt
     328             : !#if             LFP_ENABLED
     329             : !                indx = indx + 1_IK
     330             : !#define         INDEX indx
     331             : !#else
     332             : !#define         INDEX ipnt, jref
     333             : !#endif
     334             : !#if             MUF_ENABLED || MEQ_ENABLED
     335             : !                distance(INDEX) = 0._TKC
     336             : !                do idim = 1_IK, ndim
     337             : !                    distance(INDEX) = distance(INDEX) + (point(idim, ipnt) - REFERENCE(idim, jref))**2
     338             : !                end do
     339             : !#if             MUF_ENABLED
     340             : !                distance(INDEX) = sqrt(distance(INDEX))
     341             : !#endif
     342             : !#elif           S_ENABLED
     343             : !                distance(INDEX) = getDisEuclid(point(1:ndim, ipnt), REFERENCE(1:ndim, jref))
     344             : !#else
     345             : !#error          "Unrecognized interface."
     346             : !#endif
     347             : !#if             Sym_ENABLED
     348             : !                distance(jref, ipnt) = distance(ipnt, jref)
     349             : !#endif
     350             : !            end do
     351             : !        end do
     352             : !
     353             : !#else
     354             : !        !%%%%%%%%%%%%%%%%%%%%%%%%
     355             : !#error  "Unrecognized interface."
     356             : !        !%%%%%%%%%%%%%%%%%%%%%%%%
     357             : !#endif
     358             : !#undef  OPTIONAL_ARG
     359             : !#undef  REFERENCE
     360             : !#undef  INDEX
     361             : !#undef  NREF
     362             : !#undef  LBND

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