File fordef.for and Its Usage

The parameter file fordef.for contains symbols and INTEGER*4 values corresponding to the classes of floating-point representations. Some of these classes are exceptional ones such as bit patterns that represent positive denormalized numbers.

With this file of symbols and with the FP_CLASS intrinsic function, you have the flexibility of identifying exceptional numbers so that, for example, you can replace positive and negative denormalized numbers with true zero.

The following is a simple example of identifying floating-point bit representations:

include 'fordef.for'

real*4 a

integer*4 class_of_bits

a = 57.0   

class_of_bits = fp_class(a)

if ( class_of_bits .eq. for_k_fp_pos_norm  .or.   &

     class_of_bits .eq. for_k_fp_neg_norm       ) then

   print *, a, ' is a non-zero and non-exceptional value'

else

   print *, a, ' is zero or an exceptional value'

end if

end

In this example, the symbol for_k_fp_pos_norm in the file fordef.for plus the REAL*4 value 57.0 to the FP_CLASS intrinsic function results in the execution of the first print statement.

The table below explains the symbols in the file fordef.for and their corresponding floating-point representations.

Symbols in fordef.for

Symbol Name

Class of Floating-Point Bit Representation

FOR_K_FP_SNAN

Signaling NaN

FOR_K_FP_QNAN

Quiet NaN

FOR_K_FP_POS_INF

Positive infinity

FOR_K_FP_NEG_INF

Negative infinity

FOR_K_FP_POS_NORM

Positive normalized finite number

FOR_K_FP_NEG_NORM

Negative normalized finite number

FOR_K_FP_POS_DENORM

Positive denormalized number

FOR_K_FP_NEG_DENORM

Negative denormalized number

FOR_K_FP_POS_ZERO

Positive zero

FOR_K_FP_NEG_ZERO

Negative zero

Another example of using file fordef.for and intrinsic function FP_CLASS follows. The goals of this program are to quickly read any 32-bit pattern into a REAL*4 number from an unformatted file with no exception reporting and to replace denormalized numbers with true zero:

include 'fordef.for'

real*4 a(100)

integer*4 class_of_bits

! open an unformatted file as unit 1

!     ...

read (1) a

do i = 1, 100

  class_of_bits = fp_class(a(i))

  if ( class_of_bits .eq. for_k_fp_pos_denorm  .or.   &

       class_of_bits .eq. for_k_fp_neg_denorm       ) then

    a(i) = 0.0

  end if

end do

close (1)

end

You can compile this program with any value of -fpen (Linux* and Mac OS* X) or /fpe:n (Windows*). Intrinsic function FP_CLASS helps to find and replace denormalized numbers with zeroes before the program can attempt to perform calculations on the denormalized numbers.

On the other hand, if this program did not replace denormalized numbers read from unit 1 with zeroes and the program was compiled with -fpe0 or /fpe:0, then the first attempted calculation on a denormalized number would result in a floating-point exception. If you compile with /fpe:0 flush-to-zero is enabled. If the resulting calculation creates a divide-by-zero, overflow, or invalid operation, then the application should abort with a floating-point exception. Otherwise, a program using the data will run to completion, perhaps faster and with different answers.

File fordef.for and intrinsic function FP_CLASS can work together to identify NaNs. A variation of the previous example would contain the symbols for_k_fp_snan and for_k_fp_qnan in the IF statement. A faster way to do this is based on the intrinsic ISNAN function. One modification of the previous example, using ISNAN, follows:

! The ISNAN function does not need file fordef.for

real*4 a(100)

! open an unformatted file as unit 1

!     ...

read (1) a

do i = 1, 100

  if ( isnan (a(i)) ) then

    print *, 'Element ', i, ' contains a NaN'

  end if

end do

close (1)

end

You can compile this program with any value of -fpen or /fpe:n.