https://www.cdslab.org/paramonte/fortran/2
Current view: top level - main - pm_mathNumSys@routines.inc.F90 (source / functions) Hit Total Coverage
Test: ParaMonte 2.0.0 :: Serial Fortran - Code Coverage Report Lines: 27 29 93.1 %
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 [pm_mathNumSys](@ref pm_mathNumSys).
      19             : !>
      20             : !>  \finmain
      21             : !>
      22             : !>  \author
      23             : !>  \AmirShahmoradi, Sunday 3:33 AM, September 19, 2021, Dallas, TX
      24             : 
      25             : !%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      26             : 
      27             : #if     getDecimal_ENABLED || getNumeral_ENABLED
      28             :         character(*,SKC), parameter :: NUM_ALPHA = SKC_"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      29             : #endif
      30             : 
      31             :         !%%%%%%%%%%%%%%%%%
      32             : #if     getDecimal_ENABLED
      33             :         !%%%%%%%%%%%%%%%%%
      34             : 
      35             :         integer(IKC) :: i, numlen
      36          42 :         numlen = len(numeral, IKC)
      37          42 :         CHECK_ASSERTION(__LINE__, base > 0_IKC, SK_"@getDecimal(): The input `base` must be positive integer. base = "//getStr(base))
      38          42 :         CHECK_ASSERTION(__LINE__, numlen > 0_IKC, SK_"@getDecimal(): The input `numeral` must be non-empty. len(numeral) = "//getStr(numlen))
      39             :         !   \todo
      40             :         !   \pvhigh
      41             :         !   \warning
      42             :         !   The presence of `getStr()` in the followng statement `getStr(numeral), getStr(NUM_ALPHA(1:base))` is because of GNU gfortran bug as of version 11,
      43             :         !   which mistakenly converts the kind of a slices string to the default kind. It MUST be removed as soon as the gfortran bug is resolved.
      44          42 :         CHECK_ASSERTION(__LINE__, verify(getStr(numeral), getStr(NUM_ALPHA(1:base)), kind = IKC) == 0_IKC, \
      45             :         SK_"@getDecimal(): The input `numeral` must be only ASCII digits and the first `base` upper-case English alphabets. base, numeral, NUM_ALPHA(1:base) = " \
      46             :         //getStr(base)//SK_", "//getStr(numeral)//SK_", "//getStr(NUM_ALPHA(1:base)))
      47           0 :         decimal = 0_IKC
      48         222 :         do i = 1_IKC, numlen
      49             :             !   \todo
      50             :             !   \pvhigh
      51             :             !   \warning
      52             :             !   The following fence bypasses gfortran bug as of Version 11. It MUST be removed as soon as GFortran bug is resolved.
      53             : #if         __GFORTRAN__
      54          42 :             block
      55             :                 character(1,SKC) :: numeral_char
      56         180 :                 numeral_char = numeral(i:i)
      57         180 :             decimal = decimal + (index(NUM_ALPHA, numeral_char, kind = IKC) - 1_IKC) * base**(numlen - i)
      58             :             end block
      59             : #else
      60             :             decimal = decimal + (index(NUM_ALPHA, numeral(i:i), kind = IKC) - 1_IKC) * base**(numlen - i)
      61             : #endif
      62             :         end do
      63             : 
      64             :         !%%%%%%%%%%%%%%%%%
      65             : #elif   getNumeral_ENABLED
      66             :         !%%%%%%%%%%%%%%%%%
      67             : 
      68             :         !   \todo
      69             :         !   \warning
      70             :         !   `RK64` is good for handling integers as big as `huge(1_int1024)` that has 306 digits:
      71             :         !   7022238808055921514567598401519627865695222573993385049743362545223932648652381372371
      72             :         !   4248954065443758250044484324763030335464753443131493161268527593544579835065583369088
      73             :         !   0801860555545317367555154113605281582053784524026102900245630757473088050106395169337
      74             :         !   932361665227499793929447186391815763110662594625536
      75             :         !   As of 2022, the largest integer kind is made available by GNU Fortran compiler as `int128` whose huge has only 39 digits: 170141183460469231731687303715884105728
      76             :         integer, parameter :: RK64 = selected_real_kind(15)
      77             :         integer(IKC) :: remainderPlusOne, lamiced
      78             :         integer(IK) :: i, numlen
      79           8 :         CHECK_ASSERTION(__LINE__, range(0_IKC) < precision(0._RK64), \
      80             :         SK_"@getNumeral(): Hello, the distant future user. The condition `range(0_IKC) < precision(0._RK64)` must hold. This is an internal library limitation. Please report this to the developers if they are still alive.")
      81           8 :         CHECK_ASSERTION(__LINE__, base > 0_IKC, SK_"@getNumeral(): The input `base` must be a positive number. base = "//getStr(base))
      82           8 :         CHECK_ASSERTION(__LINE__, decimal > 0_IKC, SK_"@getNumeral(): The input `decimal` must be a positive number. decimal = "//getStr(decimal))
      83           8 :         numlen = int(log10(real(huge(1_IKC),RK64)) / log10(real(base,RK64)), IK) + 1_IK
      84           8 :         allocate(character(numlen,SKC) :: numeral)
      85           0 :         lamiced = decimal
      86          56 :         do i = numlen, 1_IK, -1_IK
      87          56 :             if(lamiced < base) then
      88           8 :                 numeral(i:i) = NUM_ALPHA(lamiced + 1_IK : lamiced + 1_IK)
      89           8 :                 exit
      90             :             end if
      91          48 :             remainderPlusOne = mod(lamiced, base) + 1_IKC
      92          48 :             numeral(i:i) = NUM_ALPHA(remainderPlusOne : remainderPlusOne)
      93          48 :             lamiced = lamiced / base
      94             :         end do
      95           8 :         CHECK_ASSERTION(__LINE__, i > 0_IK, SK_"@getNumeral(): Internal library error occured: i < 1. i = "//getStr(i))
      96           8 :         numeral = numeral(i:numlen)
      97             : 
      98             :         !%%%%%%%%%%%%%%%%%%%%
      99             : #elif   getCountDigit_ENABLED
     100             :         !%%%%%%%%%%%%%%%%%%%%
     101             : 
     102             : #if     1
     103             :         integer(IKC) :: lav
     104         181 :         lav = val / 10_IKC
     105             :         count = 1_IK
     106         574 :         do
     107         755 :             if (lav == 0_IKC) exit
     108         574 :             count = count + 1_IK
     109         574 :             lav = lav / 10_IKC
     110             :         end do
     111             : #else
     112             :         !   \todo
     113             :         !   \warning
     114             :         !   `RK64` is good for handling integers as big as `huge(1_int1024)` that has 306 digits:
     115             :         !   7022238808055921514567598401519627865695222573993385049743362545223932648652381372371
     116             :         !   4248954065443758250044484324763030335464753443131493161268527593544579835065583369088
     117             :         !   0801860555545317367555154113605281582053784524026102900245630757473088050106395169337
     118             :         !   932361665227499793929447186391815763110662594625536
     119             :         !   As of 2022, the largest integer kind is made available by GNU Fortran compiler as `int128` whose huge has only 39 digits: 170141183460469231731687303715884105728
     120             :         !   \todo
     121             :         !   The performance of this algorithm can be improved by converting the integer values to appropriate reals with lower precision than RK64.
     122             :         integer, parameter :: RK64 = selected_real_kind(15)
     123             :         count = int(log10(real(abs(lav), RK64))) + 1_IK
     124             : #endif
     125             : 
     126             :         !%%%%%%%%%%%%%%%%%
     127             : #else
     128             : #error  "Unrecognized interface."
     129             : #endif
     130             :         !%%%%%%%%%%%%%%%%%

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