Finding out default kind values

Hi guys,
I am working through the “Guide to Fortran 2008” book, and I am on page 11.
The 4th exercise is where I am stuck.

4th:
Determine the kind number of one real kind that has precision greater than that of
the default real kind on your computer system.

How do I find the default real kind ? I am using the Intel Fortran compiler: ifort

Thanks

Write a short program to do that. Declare a real variable. Apply the various intrinsic functions KIND(), PRECISION, RANGE(), etc., to that variable and print the returned values.

Having done that, you can proceed to tackling the next part of the question, i.e., creating a variable of greater precision.

Note that the standard requires a compiler to provide more than a single REAL kind.

1 Like

@mecej4 answered your question. Here is a program that lists the properties of real number systems for gfortran. The comments mention modifications needed to run it for other compilers.

program main ! compiles with gfortran
use iso_fortran_env, only: real_kinds
implicit none
character (len=20) :: fmt = "(7i10,3(1x,es0.4))"
real(kind=4)  :: x4
real(kind=8)  :: x8
real(kind=10) :: x10 ! ifort, flang, and nvfortran reject this
real(kind=16) :: x16 ! flang and nvfortran reject this
print "(a,*(1x,i0))","real_kinds =",real_kinds
print "(7a10,3a10)","kind","storage","digits","precision","range", &
      "minexp","maxexp","epsilon","tiny","huge"
print fmt,4,storage_size(x4),digits(x4),precision(x4),range(x4),minexponent(x4), &
      maxexponent(x4),epsilon(x4),tiny(x4),huge(x4)
print fmt,8,storage_size(x8),digits(x8),precision(x8),range(x8),minexponent(x8), &
      maxexponent(x8),epsilon(x8),tiny(x8),huge(x8)
print fmt,10,storage_size(x10),digits(x10),precision(x10),range(x10),minexponent(x10), &
      maxexponent(x10),epsilon(x10),tiny(x10),huge(x10)
print fmt,16,storage_size(x16),digits(x16),precision(x16),range(x16),minexponent(x16), &
      maxexponent(x16),epsilon(x16),tiny(x16),huge(x16)
end program main

output:

real_kinds = 4 8 10 16
      kind   storage    digits precision     range    minexp    maxexp   epsilon      tiny      huge
         4        32        24         6        37      -125       128 1.1921E-7 1.1755E-38 3.4028E+38
         8        64        53        15       307     -1021      1024 2.2204E-16 2.2251E-308 1.7977E+308
        10       128        64        18      4931    -16381     16384 1.0842E-19 3.3621E-4932 1.1897E+4932
        16       128       113        33      4931    -16381     16384 1.9259E-34 3.3621E-4932 1.1897E+4932
2 Likes

Thank you both for your help. :+1:

One could guess that it should be possible to loop over real_kinds parameter array from iso_fortran_env module. It is, however, impossible as all the numeric inquiry functions require a declared variable as the argument and the variable can be declared using constant kind value only.

Below, a slightly modified version of @Beliavsky’s code which is a bit less processor-dependent, using values from real_kinds array (statically, of course). It assumes the size of real_kinds array of 4 (true for gfortran, four different real kinds supported). If a compiler fails because it supports less real kinds, comment out the last declaration (x4) and the last print statement.

BTW, ifort (ver. 2021.4.0) fails to properly render tiny(x3) and huge(x3) (the largest kind=16) values with es0.4 format (producing hundreds of * characters), so I changed it to g0.4

code and output
program check_kinds
  use iso_fortran_env, only: real_kinds
  implicit none
  character(len=*), parameter :: fmt = "(7i10,3(1x,g0.4))"
  real(kind=real_kinds(1)) :: x1
  real(kind=real_kinds(2)) :: x2
  real(kind=real_kinds(3)) :: x3
  real(kind=real_kinds(4)) :: x4

  print "(a,*(1x,i0))","real_kinds =",real_kinds
  print "(a,1x,i0)","default real kind =",kind(1.0)
  print "(7a10,3a10)","kind","storage","digits","precision","range", &
      "minexp","maxexp","epsilon","tiny","huge"
  print fmt,kind(x1),storage_size(x1),digits(x1),precision(x1),&
      range(x1),minexponent(x1),maxexponent(x1),epsilon(x1),tiny(x1),huge(x1)
  print fmt,kind(x2),storage_size(x2),digits(x2),precision(x2),&
      range(x2),minexponent(x2),maxexponent(x2),epsilon(x2),tiny(x2),huge(x2)
  print fmt,kind(x3),storage_size(x3),digits(x3),precision(x3),&
      range(x3),minexponent(x3),maxexponent(x3),epsilon(x3),tiny(x3),huge(x3)
  print fmt,kind(x4),storage_size(x4),digits(x4),precision(x4),&
      range(x4),minexponent(x4),maxexponent(x4),epsilon(x4),tiny(x4),huge(x4)
end program check_kinds

output (gfortran 11.2):

real_kinds = 4 8 10 16
default real kind = 4
      kind   storage    digits precision     range    minexp    maxexp   epsilon      tiny      huge
         4        32        24         6        37      -125       128 0.1192E-6 0.1175E-37 0.3403E+39
         8        64        53        15       307     -1021      1024 0.2220E-15 0.2225E-307 0.1798E+309
        10       128        64        18      4931    -16381     16384 0.1084E-18 0.3362E-4931 0.1190E+4933
        16       128       113        33      4931    -16381     16384 0.1926E-33 0.3362E-4931 0.1190E+4933

output (ifort 2021.4.0, ‘x4’ commented out):

real_kinds = 4 8 16
default real kind = 4
      kind   storage    digits precision     range    minexp    maxexp   epsilon      tiny      huge
         4        32        24         6        37      -125       128 .1192E-06 .1175E-37 .3403E+39
         8        64        53        15       307     -1021      1024 .2220E-15 .2225E-307 .1798E+309
        16       128       113        33      4931    -16381     16384 .1926E-33 .3362E-4931 .1190E+4933
1 Like

For the limited purpose of answering the textbook question in the original post, Fortran 95 is sufficient, and one need not assume the kind number of default reals to be known to the programmer in advance.

program mykinds
implicit none
real x
!
print *,'Kind of higher precision real = ',selected_real_kind(precision(x)+1)
end program mykinds
1 Like