wrote in message
news:edd4003d-7459-46c3...@googlegroups.com...
There is a problem in that not all compilers have quad precision and
so if qp is used as a kind number, on such a compiler it will be
negative and cause an error. This can be worked around by creating
a candidate kind number and using MERGE to select between the
candidate and its backup if necessary. As an additional complication,
MERGE wasn't allowed in initialization expressions in f95, so it
proved necessary to use a more complicated expression with SIGN
to replace it.
D:\gfortran\clf\kinds>type kinds4.f90
module numeric_kinds
! named constants for 8, 4, 2, and 1 byte integers:
integer, parameter :: &
i8b = selected_int_kind(18), &
i4b = selected_int_kind(9), &
i2b = selected_int_kind(4), &
i1b = selected_int_kind(2)
! and for single, double and quadruple precision reals:
integer, parameter :: &
sp = kind([REAL::]), &
dp = kind([DOUBLE PRECISION::])
integer, parameter, private :: &
ep_we_hope = selected_real_kind(18,4931)
integer, parameter :: &
ep = (1+sign(1,ep_we_hope))/2*ep_we_hope+ &
(1-sign(1,ep_we_hope))/2*dp
integer, parameter, private :: &
qp_we_hope = selected_real_kind(2*precision(1.0_dp))
integer, parameter :: &
qp = merge(qp_we_hope,ep,qp_we_hope >= 0)
integer, parameter, private :: &
i16b_we_hope = selected_int_kind(38)
integer, parameter :: &
i16b = merge(i16b_we_hope,i8b,i16b_we_hope >= 0)
end module numeric_kinds
program test
use numeric_kinds
implicit none
integer(i16b) ii16b
integer(i8b) ii8b
integer(i4b) ii4b
integer(i2b) ii2b
integer(i1b) ii1b
real(sp) rsp
real(dp) rdp
real(ep) rep
real(qp) rqp
write(*,'(*(g0))') 'range(ii1b) = ',range(ii1b)
write(*,'(*(g0))') 'range(ii2b) = ',range(ii2b)
write(*,'(*(g0))') 'range(ii4b) = ',range(ii4b)
write(*,'(*(g0))') 'range(ii8b) = ',range(ii8b)
write(*,'(*(g0))') 'range(ii16b) = ',range(ii16b)
write(*,'(*(g0))') 'precision(rsp) = ',precision(rsp)
write(*,'(*(g0))') 'range(rsp) = ',range(rsp)
write(*,'(*(g0))') 'precision(rdp) = ',precision(rdp)
write(*,'(*(g0))') 'range(rdp) = ',range(rdp)
write(*,'(*(g0))') 'precision(rep) = ',precision(rep)
write(*,'(*(g0))') 'range(rep) = ',range(rep)
write(*,'(*(g0))') 'precision(rqp) = ',precision(rqp)
write(*,'(*(g0))') 'range(rqp) = ',range(rqp)
end program test
D:\gfortran\clf\kinds>gfortran kinds4.f90 -okinds4
D:\gfortran\clf\kinds>kinds4
range(ii1b) = 2
range(ii2b) = 4
range(ii4b) = 9
range(ii8b) = 18
range(ii16b) = 38
precision(rsp) = 6
range(rsp) = 37
precision(rdp) = 15
range(rdp) = 307
precision(rep) = 18
range(rep) = 4931
precision(rqp) = 33
range(rqp) = 4931
But with ifort not all of these kinds are available, but using the
kind numbers from the preceding module is still OK:
D:\gfortran\clf\kinds>ifort /nologo kinds4.f90
D:\gfortran\clf\kinds>kinds4
range(ii1b) = 2
range(ii2b) = 4
range(ii4b) = 9
range(ii8b) = 18
range(ii16b) = 18
precision(rsp) = 6
range(rsp) = 37
precision(rdp) = 15
range(rdp) = 307
precision(rep) = 33
range(rep) = 4931
precision(rqp) = 33
range(rqp) = 4931
Some duplication, but no compile-time errors.