Chapter 14
Essentials of Essentials of Fortran-90/95/2003
Extended Precision and Complex Data Types

Math 60 -- D. C. Smolarski, S.J.
Santa Clara University, Department of Mathematics and Computer Science

[Return to Math 60 Homepage | Return to Brief Contents Page]
[Return to Full Contents Page]

Contents


14.1 Double Precision Variables and Constants

Double precision is the name given in FORTRAN-77 (and earlier versions of FORTRAN) to the data type used to increase the number of digits of accuracy of real variables. Using double precision variables normally at least doubles the number of digits of accuracy. Although in use for several decades and still permitted, this data type is now considered outmoded with the introduction in Fortran-90/95/2003 of extended precision (see section 14.4 below). To declare variables as double precision, one uses an explicit type variable declaration statement with the key words DOUBLE PRECISION, i.e.,
	DOUBLE PRECISION A,B,C
(There is no default typing corresponding to double precision.) In input and output, one can use a D field descriptor in the FORMAT statements--the rules are the same as for the E descriptor. For fixed point output, one uses the F descriptor.

For constants, one always uses scientific (exponential) form substituting a D for the E. Since 10 to the power of 0 is 1, one can always express a double precision number as a simple fixed point number followed by D00. In other words, zero as a double precision number is 0.0D00. Double precision 300 can be written as 3.0D02 and double precision pi as 3.1415926D00.

Some FORTRAN-77 compilers permitted the notation REAL*8 as an alternative to (or even in place of) the standard terminology of double precision and REAL*16 for double double (or "quadruple") precision (non-standard Fortran).

Many authors suggest avoiding the use of double precision, except for constants, using, instead, extended precision declarations as described below in section 14.4.

14.2 Complex Variables and Constants

To declare variables as complex, one must use an explicit declaration statement with the keyword COMPLEX, e.g.,
	COMPLEX C
or
        COMPLEX :: C

Complex numbers are stored as two adjacent real numbers (one being the value of the real part and the other the value of the imaginery part), so all input and output is done via two E or F descriptors.

To indicate a complex constant, one uses parentheses around the two component numbers separated by a comma. For example, to indicate a = 3 + 4i in Fortran, one writes

	A = (3.0,4.0)
Fortran-90/95/2003 permits extended precision complex variables following the same procedures as for extended precision real variables (described below in section 14.4)..

14.3 Conversion Functions

Numerical conversion functions exist for various situations (cf. Chapter 7). For example, to convert from real to complex, one uses the intrinsic function CMPLX, e.g.,
	C = CMPLX(A,B)
where A and B are real variables or constants, with A containing the real value and B containing the imaginery value to be placed in the complex variable C. (For higher precision complex numbers, a third argument may be added, specifying the KIND of the complex number desired.)

To extract the real or imaginary part of a complex number, one uses the library functions REAL or AIMAG, e.g.

	A = REAL(C)
or
	B = AIMAG(C)

To calculate the conjugate of a complex number c = a+bi (i.e., to find a-bi), one uses the library function CONJG, e.g.,

	CBAR = CONJG(C)

14.4 Extended Numeric Precision and KIND

Many languages provide for several specific data types for the same general numeric type. The same is true for Fortran-90/95/2003, particularly for real variables and constants. As noted above, older versions of FORTRAN included the standard type of REAL but also included the type DOUBLE PRECISION which usually consisted of double the memory space used for standard precision REAL.

The architecture of contemporary machines is such that extended precision is commonly achieved by increasing the number of bytes used to store a single variable, since "bytes" rather than "words" has become the more standard measurement of memory size. Hence, character data is commonly stored in a single byte, and integers and reals in 4 bytes. Double precision reals are commonly stored in 8 bytes.

On computers that use 4 bytes for standard real precision, the accuracy usually stops around the sixth significant figure. Thus, even though a program may specify that more than 6 digits be printed, only the first 6 significant digits are accurate.

For this reason, when using unknown platforms, programmers should determine the actual (decimal) precision of numeric data types when using these types, since merely requesting many decimal places when printing out values does not mean that all the decimal places are accurate.

Note that there is no industry wide standard or consistency among machines and compilers for the number of decimal digit accuracy that the standard types reflect. In other words, it is possible that single precision on a massively-parallel computer may easily correspond to double precision on a desktop PC.

14.4.1 Extended Precision in Fortran-90/95/2003

To address possible inconsistencies in output resulting from running the same code on different machines and to permit a user to specify greater precision, Fortran-90/95/2003 has introduced a data KIND attribute. The KIND function accepts an argument of one element of a specific data type, and returns an integer value (which often is the number of bytes used to store that data element, but technically can be any number unique to the data type). Hence,
    KIND('a')
may return the value of 1 (indicating that all single characters have the "kind" value of 1)
    KIND(1)
may return the value of 4 (the "kind" value for integers).

What is of greater usefulness is the ability, in Fortran-90/95/2003, to prescribe a new "kind" of numeric data having specific precision, and then to be able to declare variables of that new, extended precision, data type. This involves making use of the following two Fortran-90/95/2003 functions (both of which return integer values),

    SELECTED_REAL_KIND(i,j)
    SELECTED_INT_KIND(i)
In either function, the input argument i indicates the number of digits accuracy desired, and (in the case of reals) the input argument j indicates the maximum exponent desired. These would be used in defining parameters which, in turn, could be used to declare higher precision numeric variables. For example, to declare a new real "kind" with (at least) 20 decimal digits accuracy, and the exponent range between -350 and +350, and then declare variables of this precision, one includes the following statements at the beginning of the segment code:
  INTEGER, PARAMETER  :: MYPREC20=SELECTED_REAL_KIND(20,350)
  REAL(KIND=MYPREC20) :: X, Y, Z
The first statement determines which "kind" value for real numbers would guarantee a precision of at least 20 digits and an exponent of 350 and stores that integer value in MYPREC20. The second statement declares variables to be of type REAL with precision ("kind") MYPREC20, i.e., having at least 20 digits accuracy. Note that this presupposes that the platform and compiler can actually handle this precision (see possible error values noted below)!

To declare an integer "kind" with 10 decimal digits accuracy, and then declare variables of this precision, one includes the following statements at the beginning of the segment code:

  INTEGER, PARAMETER      :: MYPREC10=SELECTED_INT_KIND(10)
  INTEGER (KIND=MYPREC10) :: I, J, K
(Note that earlier versions of Fortran did not have any way of declaring extended precision integer variables as was possible in C/C++ with datatype long.)

One can also declare complex variables of extended "kind" by determining the appropriate real precision of each of the two components, and using that as the "kind" parameter. Thus, using the declaration of MYPREC20 given in the REAL example above, we could declare complex variables as follows:

   COMPLEX (KIND=MYPREC20) :: C, D
In this case, the real and imaginery components of each variable would be of kind MYPREC20.

NOTE: The actual numeric values of MYPREC20 or MYPREC10 are irrelevant, since they are merely determined for immediate use to declare variables of that "flavor" of REAL or INTEGER. Nowhere else in the program code are the actual values of MYPREC20 or MYPREC10 ever used (or are they of any actual usefulness!). In fact, using specific numbers determined on one machine in a program may make the code less portable than it might be otherwise.

One should also note that not every possible precision is implemented by every compiler! For integer numbers, if the desired kind is not available, SELECTED_INT_KIND will return an "error" value of -1. For real numbers, if the desired kind is not available, SELECTED_REAL_KIND will return an "error" value of -1 if sufficient precision is unavailable, -2 if sufficient exponent range is unavailable, and -3 if both are unavailable. Thus, before writing a program on an unknown machine and compiler using extended precision, it can be useful to run a test program to determine what are the maximum precisions for real and integer numbers.

14.4.2 Using Extended Precision

Extended Precision can be used in place of the older FORTRAN data type of DOUBLE PRECISION. For example, one may determine a machine's "kind" value for double precision real numbers by invoking the KIND function in this manner:
         INTEGER, PARAMETER :: DP = KIND(0.0D0)
and then use DP (which contains the machine's number that corresponds to double precision real variables) when declaring variables. This is done as follows:
         REAL (KIND=DP)     :: X, Y, Z
One may also indicate real constants of this precision by using the "kind" designator as a type of suffix, preceded by the underscore symbol. For example, using DP to indicate the correct "kind" of double precision constants and variables, in place of writing
         123.45D00
one can write
         123.45_DP
Many Fortran-90/95/2003 books suggest avoiding completely the use of the data type "double precision" when declaring variable and recommend, instead, the use of REAL of higher precision (as given in this example).

We also note that Fortran-90/95/2003, via the "kind" parameters, is able to support non-European characters within the code. Suppose a specific compiler could support the Japanese Kanji character set, and that the "kind" value for this set were determined and stored in KANJI. To indicate that a constant is of this new character kind, one puts the "kind" parameter before the character constant it is associated with, if the character constant appears in quotes. Thus one may write:

         KANJI_'...'
where "..." indicates characters using Kanji script.


This page is maintained by Dennis C. Smolarski, S.J. dsmolarski@math.scu.edu
© Copyright 1999-2005 Dennis C. Smolarski, SJ, All rights reserved.
Last changed: 27 June 2005.