Programming Conventions
91. Where possible and appropriate, use the intrinsic function kind in conjuction with the instrinsic conversion functions int , real , and cmplx
when converting types.
Several situations exist where it may be useful to use thekindintrinsic function in conjunction with intrinsic functions such asint,real, andcmplx. This can help clarify potential portability, scalability, or accuracy problems inherent in the default type conversion rules.
In arithmetic expressions involving mixed data types, the basic rule is that less precise types, meaning those with less precision or those requiring fewer storage units, are converted to the more precise type; they are “promoted.” The following code assumes that both the default integer kind and default real kind occupy four bytes of memory. The code defines two named constants using the intrinsic functions selected int kind and selected real kind. The integer kind corresponds to a single-byte integer; the real kind to double precision, requiring eight bytes of storage. The declaration of four variables, two integers, and two reals follow.
! e s t a b l i s h named c o n s t a n t s f o r two non−d e f a u l t i n t e g e r s
! and one non−d e f a u l t r e a l .
i n t e g e r , parameter : : BYTE 1 INT = s e l e c t e d i n t k i n d ( 2 ) i n t e g e r , parameter : : D PREC = &
s e l e c t e d r e a l k i n d ( 1 5 , 3 0 7 ) r e a l : : x d e f r e a l
r e a l ( D PREC ) : : y d o u b i n t e g e r : : i d e f i n t
i n t e g e r ( BYTE 1 INT ) : : j b y t e i n t
The next section of code presents four mixed arithmetic expressions, with comments describing the promotions.
! Promote i d e f i n t t o d e f a u l t r e a l x d e f r e a l + i d e f i n t
! Promote j b y t e i n t t o d e f a u l t i n t e g e r j b y t e i n t * i d e f i n t
! Two e x p r e s s i o n s , e a c h i n p a r e n t h e s e s ,
! Promote r e s u l t o f t h e s e c o n d t o d e f a u l t r e a l . ( x d e f r e a l + i d e f i n t ) * ( i d e f i n t − j b y t e i n t )
! Promote r e s u l t f r o m d e f a u l t r e a l t o D PREC . y d o u b = x d e f r e a l + i d e f i n t
When kind type parameters were introduced in Fortran 90, an optional kind argument was introduced to the intrinsic functions that convert data types.
It is possible to think of the conversions the program is performing in the previous expressions as implicit use of these conversion functions. Using them, the last expression would be:
y d o u b = r e a l ( x d e f r e a l + &
r e a l ( i d e f i n t , k i n d=k i n d ( x d e f r e a l ) ) , &
k i n d=k i n d ( y d o u b ) )
You can override the default conversion behavior by using these conversion functions; when you do, use thekindfunction. Here, for example, the require-ment is to add the truncated value of a real number to whole numberm int.
! No c h a n g e r e q u i r e d i f k i n d o f m i n t i s c h a n g e d . i d e f i n t = m i n t + i n t ( x d e f r e a l , k i n d ( m i n t ) ) There exists one type of conversion where you do not use thekindfunction: You may need to convert the type or the kind of an actual subprogram argument.
In the following two lines, the real kindsWORK PRECandSING PRECare not the same:
r e a l (WORK PREC) : : t e m p e r a t u r e . . .
c a l l S u b 1 ( r e a l ( t e m p e r a t u r e , k i n d=SING PREC ) )
Another opportunity for using thekindfunction occurs in thecaseconstruct.
Here is an example where the execution branches based on the type of line being processed.
s u b r o u t i n e P r o c e s s l i n e ( t h i s ) . . .
t y p e ( l i n e t ) , i n t e n t ( i n ) : : t h i s . . .
s e l e c t c a s e ( t h i s%l i n e t y p e ) c a s e ( SOLID )
. . .
c a s e (DASHED) . . .
c a s e d e f a u l t end s e l e c t
. . .
end s u b r o u t i n e P r o c e s s l i n e
Here, line type is an integer component of type line t, and SOLID and DASHED are named constants. The standard requires that all the case-selector entities, such as SOLID, be of the same type and kind as the case-expression , this %line type. To ensure this, the case construct may be written:
s e l e c t c a s e ( t h i s%l i n e t y p e , k i n d=k i n d ( SOLID ) ) c a s e ( i n t ( SOLID ) )
. . .
c a s e ( i n t (DASHED) ) . . .
c a s e d e f a u l t end s e l e c t
which allows for subsequent changes in the kind of the component line type without requiring modification to the statements of the construct.
There are several situations where explicitly using the conversion functions, even though they are not required, are worthwhile because they mark potential problem spots.
The first occurs when the program converts from a higher precision number to a lower precision one, that is, the data is “narrowed.” With floating-point numbers, the danger is, at best, a loss of precision; at worst, the generation of a floating-point overflow exception. Using the variables x def real andy doub that were declared in the previous code, the following code will generate such an exception (see Section 13.3):
r e a l ( D PREC ) , parameter : : HUGE DP = huge &
( 1 . 0 D PREC )
y d o u b = HUGE DP
x d e f r e a l = y d o u b
It is best to signal to the reader that the program is executing a mixed-precision operation requiring converting a floating-point number, with the danger of raising an exception or losing precision, and to explicitly use the conversion function with thekindargument.
x d e f r e a l = r e a l ( y d o u b , k i n d ( x d e f r e a l ) )
A more egregious problem can occur when converting integer values. Using the variable j byte int that uses one byte of storage, the following code will not work, meaning the expected assignment will not be correct because the number on the right-hand side is too large to be expressed by a single-byte integer.
i d e f i n t = 20000 . . .
j b y t e i n t = i d e f i n t
Making the problem worse, Fortran is silent with integers; no warning will be issued or exception raised, but the number will not be correct. To point out the potential problem, write this using the conversion function using thekind argument.
j b y t e i n t = i n t ( i d e f i n t , k i n d ( j b y t e i n t ) )
The second situation where the use of the conversion function with the optionalkind argument clarifies the code is with all the intrinsic functions that return information about the size of an array or an index to an array element as a default integer. These functions include size,ubound,maxloc, and so on. If the size of the array exceeds the value that can be stored in a default integer, use of these functions can result in an incorrect value being returned. This is especially the case with large multi-dimensional arrays. So, if the size of the following array my array exceeds the largest number that can be stored in a default integer, the first line of the following code pro-duces an incorrect result; the second line at least points out the potential problem.
i d e f i n t = s i z e ( m y a r r a y ) . . .
i d e f i n t = i n t ( s i z e ( m y a r r a y ) , k i n d ( i d e f i n t ) ) The final situation involves the numeric instrinsic functions real, which con-verts numbers to a real type, and cmplx, which converts one or two real numbers to a complex one. The problem here is that these functions always return a number of default kind, regardless of the kinds of the input arguments.
This can result in a silent loss of precision or a floating-point exception. To override this behavior, you must specify the kind of the result as shown in the second assignment in the following code:
! WORK PREC i s n o t d e f a u l t r e a l . i n t e g e r , parameter : : WORK PREC = &
s e l e c t e d r e a l k i n d ( 1 4 , 3 0 0 ) complex ( k i n d=WORK PREC) : : c c o m p l e x r e a l ( k i n d=WORK PREC) : : x , y . . .
c c o m p l e x = cmplx ( x , y ) . . .
c c o m p l e x = cmplx ( x , y , k i n d=WORK PREC)
92. Use the Fortran intrinsic functionslboundand uboundto determine