Understanding rounding operations in XL Fortran can help you get predictable, consistent results. It can also help you to makeinformed 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.
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:
Figure 21. 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
Notes:
Related Information: | For more information about the bits in the FPSCR register that correspond to the fpstat array elements, see the POWERstation and POWERserver Hardware Technical Reference - General Information. |
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:
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.
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.
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