LCOV - code coverage report
Current view: top level - utils/private - utils_nan_dp.f90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 42.1 % 57 24
Test Date: 2025-05-08 18:23:42 Functions: 27.3 % 11 3

            Line data    Source code
       1              : ! ***********************************************************************
       2              : !
       3              : !   Copyright (C) 2010-2019  The MESA Team
       4              : !
       5              : !   This program is free software: you can redistribute it and/or modify
       6              : !   it under the terms of the GNU Lesser General Public License
       7              : !   as published by the Free Software Foundation,
       8              : !   either version 3 of the License, or (at your option) any later version.
       9              : !
      10              : !   This program is distributed in the hope that it will be useful,
      11              : !   but WITHOUT ANY WARRANTY; without even the implied warranty of
      12              : !   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
      13              : !   See the GNU Lesser General Public License for more details.
      14              : !
      15              : !   You should have received a copy of the GNU Lesser General Public License
      16              : !   along with this program. If not, see <https://www.gnu.org/licenses/>.
      17              : !
      18              : ! ***********************************************************************
      19              : 
      20              : module utils_nan_dp
      21              : 
      22              :   use const_def, only : dp
      23              : 
      24              :   use ISO_FORTRAN_ENV
      25              :   use ISO_C_BINDING
      26              : 
      27              :   implicit none
      28              : 
      29              :   integer, parameter :: FRAC_BITS_64 = 52
      30              :   integer, parameter :: EXPN_BITS_64 = 11
      31              : 
      32              :   integer(INT64), parameter :: QNAN_64 = INT(z'7ff8000000000001', INT64)
      33              :   integer(INT64), parameter :: SNAN_64 = INT(z'7ff0000000000001', INT64)
      34              : 
      35              :   interface is_nan
      36              :      module procedure is_nan_dp
      37              :   end interface is_nan
      38              : 
      39              :   interface is_inf
      40              :      module procedure is_inf_dp
      41              :   end interface is_inf
      42              : 
      43              :   interface is_bad
      44              :      module procedure is_bad_dp
      45              :   end interface is_bad
      46              : 
      47              :   interface set_nan
      48              :      module procedure set_nan_dp_0d
      49              :      module procedure set_nan_dp_1d
      50              :      module procedure set_nan_dp_2d
      51              :      module procedure set_nan_dp_3d
      52              :      module procedure set_nan_dp_4d
      53              :   end interface set_nan
      54              : 
      55              :   private
      56              : 
      57              :   public :: is_nan
      58              :   public :: is_inf
      59              :   public :: is_bad
      60              :   public :: set_nan
      61              : 
      62              : contains
      63              : 
      64   2044783171 :   elemental function is_nan_dp (x, signal) result (is_nan)
      65              : 
      66              :     real(dp), target, intent(in)  :: x
      67              :     logical, optional, intent(in) :: signal
      68              :     logical                       :: is_nan
      69              : 
      70              :     integer(INT64) :: ix
      71              :     integer(INT64) :: frac
      72              :     integer(INT64) :: expn
      73              :     integer(INT64) :: sign
      74              : 
      75              :     ! Convert x to integer
      76              : 
      77   2044783171 :     ix = TRANSFER(x, ix)
      78              : 
      79              :     ! Split out IEEE fields
      80              : 
      81   2044783171 :     frac = IBITS(ix, 0, FRAC_BITS_64)
      82   2044783171 :     expn = IBITS(ix, FRAC_BITS_64, EXPN_BITS_64)
      83   2044783171 :     sign = IBITS(ix, FRAC_BITS_64+EXPN_BITS_64, 1)
      84              : 
      85              :     ! Check for NaN
      86              : 
      87   2044783171 :     is_nan = expn == MASKR(EXPN_BITS_64, INT64) .AND. frac /= 0_INT64
      88              : 
      89            0 :     if (PRESENT(signal)) then
      90            0 :        is_nan = is_nan .AND. (BTEST(frac, FRAC_BITS_64-1) .EQV. .NOT. signal)
      91              :     end if
      92              : 
      93              :     return
      94              : 
      95              :   end function is_nan_dp
      96              : 
      97              : 
      98   2044783171 :   elemental function is_inf_dp (x) result (is_inf)
      99              : 
     100              :     real(dp), target, intent(in)  :: x
     101              :     logical                       :: is_inf
     102              : 
     103              :     integer(INT64) :: ix
     104              :     integer(INT64) :: frac
     105              :     integer(INT64) :: expn
     106              :     integer(INT64) :: sign
     107              : 
     108              :     ! Convert x to integer
     109              : 
     110   2044783171 :     ix = TRANSFER(x, ix)
     111              : 
     112              :     ! Split out IEEE fields
     113              : 
     114   2044783171 :     frac = IBITS(ix, 0, FRAC_BITS_64)
     115   2044783171 :     expn = IBITS(ix, FRAC_BITS_64, EXPN_BITS_64)
     116   2044783171 :     sign = IBITS(ix, FRAC_BITS_64+EXPN_BITS_64, 1)
     117              : 
     118              :     ! Check for infinity
     119              : 
     120   2044783171 :     is_inf = expn == MASKR(EXPN_BITS_64, INT64) .AND. frac == 0_INT64
     121              : 
     122              :     return
     123              : 
     124              :   end function is_inf_dp
     125              : 
     126              : 
     127   2044783171 :   elemental function is_bad_dp (x) result (is_bad)
     128              : 
     129              :     real(dp), intent(in) :: x
     130              :     logical              :: is_bad
     131              : 
     132              :     ! Check for NaN or infinity
     133              : 
     134   2044783171 :     is_bad = is_nan(x) .OR. is_inf(x)
     135              : 
     136              :     return
     137              : 
     138              :   end function is_bad_dp
     139              : 
     140              : 
     141            0 :   subroutine set_nan_dp_0d (x, signal)
     142              : 
     143              :     real(dp), target, intent(out) :: x
     144              :     logical, optional, intent(in) :: signal
     145              : 
     146              :     integer(INT64), pointer :: ix
     147              : 
     148              :     ! Convert x to a signaling or quiet NaN
     149              : 
     150            0 :     call C_F_POINTER(C_LOC(x), ix)
     151              : 
     152            0 :     if (PRESENT(signal)) then
     153            0 :        if (signal) then
     154            0 :           ix = SNAN_64
     155              :        else
     156            0 :           ix = QNAN_64
     157              :        end if
     158              :     else
     159            0 :        ix = SNAN_64
     160              :     end if
     161              : 
     162            0 :     return
     163              : 
     164              :   end subroutine set_nan_dp_0d
     165              : 
     166              : 
     167            0 :   subroutine set_nan_dp_1d (x, signal)
     168              : 
     169              :     real(dp), target, intent(out) :: x(:)
     170              :     logical, optional, intent(in) :: signal
     171              : 
     172              :     integer(INT64), pointer :: ix(:)
     173              : 
     174              :     ! Convert x to a signaling or quiet NaN
     175              : 
     176            0 :     call C_F_POINTER(C_LOC(x), ix, SHAPE(x))
     177              : 
     178            0 :     if (PRESENT(signal)) then
     179            0 :        if (signal) then
     180            0 :           ix = SNAN_64
     181              :        else
     182            0 :           ix = QNAN_64
     183              :        end if
     184              :     else
     185            0 :        ix = SNAN_64
     186              :     end if
     187              : 
     188            0 :     return
     189              : 
     190              :   end subroutine set_nan_dp_1d
     191              : 
     192              : 
     193           19 :   subroutine set_nan_dp_2d (x, signal)
     194              : 
     195              :     real(dp), target, intent(out) :: x(:,:)
     196              :     logical, optional, intent(in) :: signal
     197              : 
     198              :     integer(INT64), pointer :: ix(:,:)
     199              : 
     200              :     ! Convert x to a signaling or quiet NaN
     201              : 
     202           57 :     call C_F_POINTER(C_LOC(x), ix, SHAPE(x))
     203              : 
     204           19 :     if (PRESENT(signal)) then
     205            0 :        if (signal) then
     206            0 :           ix = SNAN_64
     207              :        else
     208            0 :           ix = QNAN_64
     209              :        end if
     210              :     else
     211     10641159 :        ix = SNAN_64
     212              :     end if
     213              : 
     214           19 :     return
     215              : 
     216              :   end subroutine set_nan_dp_2d
     217              : 
     218              : 
     219            0 :   subroutine set_nan_dp_3d (x, signal)
     220              : 
     221              :     real(dp), target, intent(out) :: x(:,:,:)
     222              :     logical, optional, intent(in) :: signal
     223              : 
     224              :     integer(INT64), pointer :: ix(:,:,:)
     225              : 
     226              :     ! Convert x to a signaling or quiet NaN
     227              : 
     228            0 :     call C_F_POINTER(C_LOC(x), ix, SHAPE(x))
     229              : 
     230            0 :     if (PRESENT(signal)) then
     231            0 :        if (signal) then
     232            0 :           ix = SNAN_64
     233              :        else
     234            0 :           ix = QNAN_64
     235              :        end if
     236              :     else
     237            0 :        ix = SNAN_64
     238              :     end if
     239              : 
     240            0 :     return
     241              : 
     242              :   end subroutine set_nan_dp_3d
     243              : 
     244              : 
     245          138 :   subroutine set_nan_dp_4d (x, signal)
     246              : 
     247              :     real(dp), target, intent(out) :: x(:,:,:,:)
     248              :     logical, optional, intent(in) :: signal
     249              : 
     250              :     integer(INT64), pointer :: ix(:,:,:,:)
     251              : 
     252              :     ! Convert x to a signaling or quiet NaN
     253              : 
     254          690 :     call C_F_POINTER(C_LOC(x), ix, SHAPE(x))
     255              : 
     256          138 :     if (PRESENT(signal)) then
     257            0 :        if (signal) then
     258            0 :           ix = SNAN_64
     259              :        else
     260            0 :           ix = QNAN_64
     261              :        end if
     262              :     else
     263     19887042 :        ix = SNAN_64
     264              :     end if
     265              : 
     266          138 :     return
     267              : 
     268              :   end subroutine set_nan_dp_4d
     269              : 
     270            0 : end module utils_nan_dp
        

Generated by: LCOV version 2.0-1