J3/12-164
To: J3
From: Dan Nagle
Subject: Update Kinds Discussion in Annex
Date: 2012 June 23
The kinds discussion in the explanatory annex doesn't mention
iso_fortran_env and does mention using literal kind values. Thus,
there is room for improvement. Also no mention is made in the existing
text of kinds for derived types. This paper offers text that might be
an improvement on the existing text.
Edits:
{Editor, improve the kind discussion in the explanatory annex}
[467:5-27] Delete the existing C.1.1
[467:28-] Add
C.1.1 Selection of Representations of Intrinsic Types (4.4.2.3)
All the intrinsic types (logical, integer, character, real and complex)
allow several representations to be used by a processor. Real and
complex are required to have at least two, while integer must have one
with a decimal range greater than 18, and therefore many processors will
support more than one representation.
Kind type values are processor-dependent. Therefore, for maximum
portability a program should never use literal kind values. There are
several ways to obtain kind values for any type, and do so in a completely
portable way. Indeed, there is no need to know what value a kind type
parameter is.
Type logical has only two values so different representations have the same
set of values and may be used interchangeably. Processors may choose
to support different representations of type logical to provide entities
of different storage sizes.
Processors may support several representations of type character
to support several character sets. These representations will likely have
different storage sizes. For most processors, these character sets
are taken from the ISO 10646 family of character sets, although there is
no reason not to support other character sets.
The most important factors involving integers is the range of values
an integer may support and the storage size required to do so.
The representation of type integer required to have a range greater than 18
may be implemented as a 64-bit integer. A processor may well support
an integer representation smaller than 64 bits, such as a 32-bit integer.
There are three ways to obtain a kind type value for type integer (without
using a literal value). These are the selected_int_kind intrinsic,
the integer_kinds array defined in the iso_fortran_env intrinsic module,
and the named constants int32 and int64 defined
in the iso_fortran_env intrinsic module. An example follows.
program diagnose_integers
use, intrinsic :: iso_fortran_env, only: int32, int64
write( *, '( / a)') 'for int32'
write( *, '( a13, i0)') 'bit size ', bit_size( 0_int32)
write( *, '( a13, i0)') 'digits ', digits( 0_int32)
write( *, '( a13, i0)') 'huge ', huge( 0_int32)
write( *, '( a13, i0)') 'radix ', radix( 0_int32)
write( *, '( a13, i0)') 'storage size ', storage_size( 0_int32)
write( *, '( / a)') 'for int64'
write( *, '( a13, i0)') 'bit size ', bit_size( 0_int64)
write( *, '( a13, i0)') 'digits ', digits( 0_int64)
write( *, '( a13, i0)') 'huge ', huge( 0_int64)
write( *, '( a13, i0)') 'radix ', radix( 0_int64)
write( *, '( a13, i0)') 'storage size ', storage_size( 0_int64)
end program diagnose_integers
The most important factors involving reals is the range of values
a real may support, the precision it supports, and the storage size
required to do so.
A processor is required to support two representations of type real
one of which will require twice the storage of the other. Of course,
a processor is allowed to support further representations of type real
as well. One representation may be implemented as a 64-bit integer.
A processor may well support a real representation smaller than 64 bits,
such as a 32-bit real.
There are three ways to obtain a kind type value for type real (without
using a literal value). These are the selected_real_kind intrinsic,
the real_kinds array defined in the iso_fortran_env intrinsic module,
and the named constants real32 and real64 defined
in the iso_fortran_env intrinsic module. An example follows.
program diagnose_reals
use, intrinsic :: iso_fortran_env, only: real32, real64
write( *, '( / a)') 'for real32'
write( *, '( a13, i0)') 'digits ', digits( 0.0_real32)
write( *, '( a13, es24.16)') 'epsilon ', epsilon( 0.0_real32)
write( *, '( a13, es24.16)') 'huge ', huge( 0.0_real32)
write( *, '( a13, i0)') 'max exponent ', maxexponent( 0.0_real32)
write( *, '( a13, i0)') 'min exponent ', minexponent( 0.0_real32)
write( *, '( a13, i0)') 'precision ', precision( 0.0_real32)
write( *, '( a13, i0)') 'radix ', radix( 0.0_real32)
write( *, '( a13, i0)') 'storage size ', storage_size( 0.0_real32)
write( *, '( / a)') 'for real64'
write( *, '( a13, i0)') 'digits ', digits( 0.0_real64)
write( *, '( a13, es24.16)') 'epsilon ', epsilon( 0.0_real64)
write( *, '( a13, es24.16') 'huge ', huge( 0.0_real64)
write( *, '( a13, i0)') 'max exponent ', maxexponent( 0.0_real64)
write( *, '( a13, i0)') 'min exponent ', minexponent( 0.0_real64)
write( *, '( a13, i0)') 'precision ', precision( 0.0_real32)
write( *, '( a13, i0)') 'radix ', radix( 0.0_real64)
write( *, '( a13, i0)') 'storage size ', storage_size( 0.0_real64)
end program diagnose_reals
Note that there is no need to know that value of the type kind value
in order to fully diagnose the representation of the kinds supported.
If it is imagined that a kind value might be changed after a program has
been substantially developed, use of a rename clause on the use statement
of the iso_fortran_env intrinsic module isolates the changes
to a single line.
use, intrinsic :: iso_fortran_env, only: wrk => real64
If a change is desired, the 'real64' is all that must be changed
if wrk is used throughout the scope to supply the kind value.