XL Fortran for AIX 8.1

User's Guide


How XL Fortran Rounds Floating-Point Calculations

Understanding rounding operations in XL Fortran can help you get predictable, consistent results. It can also help you to make informed decisions when you have to make tradeoffs between speed and accuracy.

In general, floating-point results from XL Fortran programs are more accurate than those from other implementations because of MAF operations and the higher precision used for intermediate results. If identical results are more important to you than the extra precision and performance of the XL Fortran defaults, read Duplicating the Floating-Point Results of Other Systems.

Selecting the Rounding Mode

To change the rounding mode in a program, you can call the fpsets and fpgets routines, which use an array of logicals named fpstat, defined in the include files /usr/include/fpdt.h and /usr/include/fpdc.h. The fpstat array elements correspond to the bits in the floating-point status and control register.

For floating-point rounding control, the array elements fpstat(fprn1) and fpstat(fprn2) are set as specified in the following table:

Table 19. Rounding-Mode Bits to Use with fpsets and fpgets

fpstat(fprn1) fpstat(fprn2) Rounding Mode Enabled
.true. .true. Round towards -infinity.
.true. .false. Round towards +infinity.
.false. .true. Round towards zero.
.false. .false. Round to nearest.

For example:

	program fptest
        include 'fpdc.h'
 
        print *, 'Before test: 2.0 / 3.0 = ', 2.0 / 3.0
        print *, '            -2.0 / 3.0 = ', -2.0 / 3.0
 
        call fpgets( fpstat )   ! Get current register values.
        fpstat(fprn1) = .TRUE.  ! These 2 lines mean round towards
        fpstat(fprn2) = .FALSE. !   +INFINITY.
        call fpsets( fpstat )
        r = 2.0 / 3.0
        print *, 'Round towards +INFINITY:  2.0 / 3.0= ', r
 
        call fpgets( fpstat )   ! Get current register values.
        fpstat(fprn1) = .TRUE.  ! These 2 lines mean round towards
        fpstat(fprn2) = .TRUE.  !   -INFINITY.
        call fpsets( fpstat )
        r = -2.0 / 3.0
        print *, 'Round towards -INFINITY: -2.0 / 3.0= ', r
        end
! This block data program unit initializes the fpstat array, and so on.
        block data
        include 'fpdc.h'
        include 'fpdt.h'
        end

XL Fortran also provides several procedures that allow you to control the floating-point status and control register of the processor directly. These procedures are more efficient than the fpsets and fpgets subroutines because they are mapped into inlined machine instructions that manipulate the floating-point status and control register (fpscr) directly.

XL Fortran supplies the procedure, get_round_mode(), which is available in the xlf_fp_util module. This procedure returns the current floating-point rounding mode.

For example:

 USE XLF_FP_UTIL
 INTEGER(FPSCR_KIND) MODE
 
 MODE=get_round_mode()
 IF (MODE .EQ. FP_RND_RZ) THEN
 ! ...
 END IF

Notes:

  1. Extended-precision floating-point values must only be used in round-to-nearest mode.
  2. For thread-safety and reentrancy, the include file /usr/include/fpdc.h contains a THREADLOCAL directive that is protected by the trigger constant IBMT. The invocation commands xlf_r, xlf_r7, xlf90_r, xlf90_r7, xlf95_r, and xlf95_r7 turn on the -qthreaded compiler option by default, which in turn implies the trigger constant IBMT. If you are including the file /usr/include/fpdc.h in code that is not intended to be thread-safe, do not specify IBMT as a trigger constant.
Related Information:
For more information about the bits in the FPSCR register that correspond to the fpstat array elements, see the POWERstation and POWERserver(R) Hardware Technical Reference - General Information.

Minimizing Rounding Errors

There are several strategies for handling rounding errors and other unexpected, slight differences in calculational results. You may want to consider one or more of the following strategies:

Minimizing Overall Rounding

Rounding operations, especially in loops, reduce code performance and may have a negative effect on the precision of computations. Consider using double-precision variables instead of single-precision variables when you store the temporary results of double-precision calculations, and delay rounding operations until the final result is computed. You can also specify the hssngl suboption of -qfloat instead of converting a stored single-precision result back to double-precision. This suboption preserves computed double-precision results so that they can be used again later.

Delaying Rounding until Run Time

The compiler evaluates floating-point expressions during compilation when it can, so that the resulting program does not run more slowly due to unnecessary run-time calculations. However, the results of the compiler's evaluation might not match exactly the results of the run-time calculation. To delay these calculations until run time, specify the nofold suboption of the -qfloat option.

The results may still not be identical; for example, calculations in DATA and PARAMETER statements are still performed at compile time.

The differences in results due to fold or nofold are greatest for programs that perform extended-precision calculations or are compiled with the -O option or both.

Ensuring that the Rounding Mode is Consistent

You can change the rounding mode from its default setting of round-to-nearest by calling the fpsets subroutine inside a program. If you do so, you must be careful that all rounding operations for the program use the same mode:

For example, you might compile a program like the one in Selecting the Rounding Mode with this command if the program consistently uses round-to-plus-infinity mode:

xlf95 -qieee=plus -qfloat=rrm changes_rounding_mode.f


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]