选择取整方式

要更改程序中的舍入方式,您可以调用 fpsetsfpgets 例程,这些例程使用在包含文件 /usr/include/fpdt.h/usr/include/fpdc.h中定义的名为 fpstat的逻辑数组。 fpstat 数组元素对应于浮点状态和控制寄存器中的位。 它们对应于 FPSCR 位的下半部。

对于浮点舍入控制,数组元素 fpstat(fprn1)fpstat(fprn2) 按下表中的指定进行设置:

表 1. 用于 fpsets 和 fpgets 的舍入模式位
fpstat(fprn1) fpstat(fprn2) 已启用取整方式
.true. .true. 向负无穷大舍入。
.true. .false. 向正无穷大舍入。
.false. .true. 向零舍入。
.false. .false. 舍入到最近。
例如:
      program fptest
        include 'fpdc.h'

        call fpgets( fpstat ) ! Get current register values.
        if ( (fpstat(fprn1) .eqv. .false.) .and. +
               (fpstat(fprn2) .eqv. .false.)) then
        print *, 'Before test: Rounding mode is towards nearest'
        print *, '             2.0 / 3.0 = ', 2.0 / 3.0
        print *, '            -2.0 / 3.0 = ', -2.0 / 3.0
        end if

        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

Open XL Fortran 还提供了若干过程,允许您直接控制处理器的浮点状态和控制寄存器。 这些过程比 fpsetsfpgets 子例程更高效,因为它们映射到直接处理浮点状态和控制寄存器 (fpscr) 的内联机器指令中。

Open XL Fortran 提供 xlf_fp_util 模块中的 get_round_mode()set_round_mode() 过程。 这些过程分别返回并设置当前二进制浮点取整方式。

例如:
      program fptest
        use, intrinsic :: xlf_fp_util
        integer(fpscr_kind) old_fpscr
        if ( get_round_mode() == fp_rnd_rn ) then
        print *, 'Before test: Rounding mode is towards nearest'
        print *, '             2.0 / 3.0 = ', 2.0 / 3.0
        print *, '            -2.0 / 3.0 = ', -2.0 / 3.0
        end if

        old_fpscr = set_round_mode( fp_rnd_rp )
        r = 2.0 / 3.0
        print *, 'Round towards +infinity:  2.0 / 3.0 = ', r

        old_fpscr = set_round_mode( fp_rnd_rm )
        r = -2.0 / 3.0
        print *, 'Round towards -infinity: -2.0 / 3.0 = ', r
      end

Open XL Fortran 提供了 ieee_arithmetic 模块中的 ieee_get_rounding_mode()ieee_set_rounding_mode() 过程。 这些可移植过程分别检索并设置当前浮点取整方式。

例如:
      program fptest
        use, intrinsic :: ieee_arithmetic
        type(ieee_round_type) current_mode
        call ieee_get_rounding_mode( current_mode )
        if ( current_mode == ieee_nearest ) then
        print *, 'Before test: Rounding mode is towards nearest'
        print *, '             2.0 / 3.0 = ', 2.0 / 3.0
        print *, '            -2.0 / 3.0 = ', -2.0 / 3.0
        end if

        call ieee_set_rounding_mode( ieee_up )
        r = 2.0 / 3.0
        print *, 'Round towards +infinity:  2.0 / 3.0 = ', r

        call ieee_set_rounding_mode( ieee_down )
        r = -2.0 / 3.0
        print *, 'Round towards -infinity: -2.0 / 3.0 = ', r
      end
备注信息:
  1. 扩展精度浮点值必须仅在舍入到最近的方式下使用。
  2. 对于线程安全和重新连接,包含文件 /usr/include/fpdc.h 包含受触发器常量 IBMT保护的 THREADLOCAL 伪指令。 缺省情况下,调用命令 xlf_rxlf90_rxlf95_rxlf2003_rxlf2008_r 打开 -qthreaded 编译器选项,这反过来意味着触发常量 IBMT。 如果要将文件 /usr/include/fpdc.h 包含在并非旨在线程安全的代码中,请不要将 IBMT 指定为触发器常量。
  3. 编译将取整方式更改为 -qfloat=rrm 的程序。

有关 FPSCR 寄存器中对应于 fpstat 阵列元素的位的更多信息,请参阅 POWERstation and POWERserver Hardware Technical Reference-General Information