

For this example I also use the `C' preprocessor for conditional compilation. The source file is tkind.F90, which #includes tkind.h. This method is common on UNIX systems, and on other platforms as well. The `C' preprocessor is more flexible and provides much more capability than the Fortran 90 standard `INCLUDE' (which is deprecated).
In this case, the conditional compilation is necessary for the GENERIC INTERFACE code. Generic interfaces allow the overloading of user functions, similar to overloading ABS to equate to ABS, IABS, DABS, CABS, or etc. It selects the correct function depending on the type of argument given. Generic interfaces require the functions to be distinguishable by Type, Kind, or Rank (TKR). One implementation couldn't handle the KIND=16 and demoted it to KIND=8 instead of failing. This created an ambiguity between show_real8 and show_real16, which yielded a compiler error.
The selected kinds, precision and ranges, are typical for IEEE implementation of floating point representations. Also, notice that parameter values are kept in a MODULE for easy inclusion in all the subroutines.
Code examples
module numeric_kind implicit none ! define several KIND parameters for use everywhere integer, parameter :: INT1 = selected_int_kind(R=2) integer, parameter :: INT2 = selected_int_kind(R=4) integer, parameter :: INT4 = selected_int_kind(R=9) integer, parameter :: INT8 = selected_int_kind(R=18) integer, parameter :: REAL4 = selected_real_kind(P= 6,R=37) integer, parameter :: REAL8 = selected_real_kind(P=13,R=300) integer, parameter :: REAL16 = selected_real_kind(P=27,R=2400) end module numeric_kind subroutine show_int1(x) use numeric_kind implicit none ! KIND must be known at compile time integer(kind=INT1), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***INT1 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_int_kind(R=2) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"RANGE = ", i6)') range(x) write(6,'(1x,"HUGE = ")',advance='NO') ! Have no idea how many digits to plan for ! Use non-advancing output and let compiler ! handle it with list directed output write(6, *) huge(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_int1 subroutine show_int2(x) use numeric_kind implicit none integer(kind=INT2), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***INT2 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_int_kind(R=4) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"RANGE = ", i6)') range(x) write(6,'(1x,"HUGE = ")',advance='NO') write(6, *) huge(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_int2 subroutine show_int4(x) use numeric_kind implicit none integer(kind=INT4), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***INT4 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_int_kind(R=9) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"RANGE = ", i6)') range(x) write(6,'(1x,"HUGE = ")',advance='NO') write(6, *) huge(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_int4 subroutine show_int8(x) use numeric_kind implicit none integer(kind=INT8), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***INT8 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_int_kind(R=18) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"RANGE = ", i6)') range(x) write(6,'(1x,"HUGE = ")',advance='NO') write(6, *) huge(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_int8 subroutine show_real4(x) use numeric_kind implicit none real(kind=REAL4), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***REAL4 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_real_kind(P= 6,R=37) write(6,'(1x,"PRECISION = ", i6)') precision(x) write(6,'(1x,"MAXEXPONENT = ", i6)') maxexponent(x) write(6,'(1x,"MINEXPONENT = ", i6)') minexponent(x) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"EPSILON = ")',advance='NO') write(6, *) epsilon(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_real4 subroutine show_real8(x) use numeric_kind implicit none real(kind=REAL8), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***REAL8 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_real_kind(P=13,R=300) write(6,'(1x,"PRECISION = ", i6)') precision(x) write(6,'(1x,"MAXEXPONENT = ", i6)') maxexponent(x) write(6,'(1x,"MINEXPONENT = ", i6)') minexponent(x) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"EPSILON = ")',advance='NO') write(6, *) epsilon(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_real8 subroutine show_real16(x) use numeric_kind implicit none real(kind=REAL16), intent(in) :: x ! kind must not be variable write(6,'(/1x,"***REAL16 KIND = ", i6, 10x,"requested = ", i6)') & kind(x), selected_real_kind(P=27,R=2400) write(6,'(1x,"PRECISION = ", i6)') precision(x) write(6,'(1x,"MAXEXPONENT = ", i6)') maxexponent(x) write(6,'(1x,"MINEXPONENT = ", i6)') minexponent(x) write(6,'(1x,"RADIX = ", i6)') radix(x) write(6,'(1x,"DIGITS = ", i6)') digits(x) write(6,'(1x,"EPSILON = ")',advance='NO') write(6, *) epsilon(x) write(6,'(1x,"value = ")',advance='NO') write(6, *) x end subroutine show_real16 program tkind use numeric_kind ! Use parameter names,because KIND values may ! vary for each compiler integer(kind=INT1) :: iq = 1_INT1 integer(kind=INT2) :: ih = 1_INT2 integer(kind=INT4) :: i = 1_INT4 integer(kind=INT8) :: ii = 1_INT8 real(kind=REAL4) :: x = 1.0_REAL4/3.0_REAL4 real(kind=REAL8) :: xx = 1.0_REAL8/3.0_REAL8 real(kind=REAL16) :: xxxx = 1.0_REAL16/3.0_REAL16 ! use the CPP include instead of F90 include, because need conditional ! compilation #include "tkind.h" call show_real4(x) call show_real8(xx) call show_real16(xxxx) call show_int1(iq) call show_int2(ih) call show_int4(i) call show_int8(ii) write(6,'(/1x,"try generic interface")') call show_kind(i) call show_kind(xx) end program tkind
! ! create an overloaded 'generic' interface which depends on the subroutine ! 'signature' based on data type, kind number, and rank (TKR) interface show_kind subroutine show_int1(x) use numeric_kind integer(kind=INT1), intent(in) :: x end subroutine show_int1 subroutine show_int2(x) use numeric_kind integer(kind=INT2), intent(in) :: x end subroutine show_int2 subroutine show_int4(x) use numeric_kind integer(kind=INT4), intent(in) :: x end subroutine show_int4 subroutine show_int8(x) use numeric_kind integer(kind=INT8), intent(in) :: x end subroutine show_int8 subroutine show_real4(x) use numeric_kind real(kind=REAL4), intent(in) :: x end subroutine show_real4 subroutine show_real8(x) use numeric_kind real(kind=REAL8), intent(in) :: x end subroutine show_real8 #ifndef NO_16 subroutine show_real16(x) use numeric_kind real(kind=REAL16), intent(in) :: x end subroutine show_real16 #endif end interface
x86 Linux - g77/vastf90 ***REAL4 KIND = 4 requested = 4 PRECISION = 6 MAXEXPONENT = 128 MINEXPONENT = -125 RADIX = 2 DIGITS = 24 EPSILON = 1.1920929E-07 value = 0.333333343 ***REAL8 KIND = 8 requested = 8 PRECISION = 15 MAXEXPONENT = 1024 MINEXPONENT = -1021 RADIX = 2 DIGITS = 53 EPSILON = 2.22044605E-16 value = 0.333333333 ***REAL16 KIND = 8 requested = 16 PRECISION = 15 MAXEXPONENT = 1024 MINEXPONENT = -1021 RADIX = 2 DIGITS = 53 EPSILON = 2.22044605E-16 value = 0.333333333 ***INT1 KIND = 1 requested = 1 RADIX = 2 DIGITS = 7 RANGE = 2 HUGE = 127 value = 1 ***INT2 KIND = 2 requested = 2 RADIX = 2 DIGITS = 15 RANGE = 4 HUGE = 32767 value = 1 ***INT4 KIND = 4 requested = 4 RADIX = 2 DIGITS = 31 RANGE = 9 HUGE = 2147483647 value = 1 ***INT8 KIND = 8 requested = 8 RADIX = 2 DIGITS = 63 RANGE = 18 HUGE = -1 value = 1 try generic interface ***INT4 KIND = 4 requested = 4 RADIX = 2 DIGITS = 31 RANGE = 9 HUGE = 2147483647 value = 1 ***REAL8 KIND = 8 requested = 8 PRECISION = 15 MAXEXPONENT = 1024 MINEXPONENT = -1021 RADIX = 2 DIGITS = 53 EPSILON = 2.22044605E-16 value = 0.333333333

