Sun Studio 12: Fortran プログラミングガイド

6.3.1 フラグと ieee_flags()

ieee_flags 関数は、例外ステータスフラグの問い合わせやクリアーに使用します。この関数は、Sun コンパイラとともに出荷される libsunmath ライブラリに組み込まれていて、次の作業を行うことができます。

ieee_flags の一般的な呼び出し方法は次のとおりです。


      
flags = ieee_flags( action, mode, in, out )

4 つの引数はすべて文字列です。入力は、actionmode、および in です。出力は、outflags です。ieee_flags は、整数値の関数です。flags は 1 ビットフラグの集合で、ここには有用な情報が返されます。詳細は、ieee_flags(3m) のマニュアルページを参照してください。

パラメータの取り得る値は次のとおりです。

表 6–1 ieee_flags( action, mode, in, out ) の引数の値

引数の 

使用可能な値 

action

getsetclearclearall のいずれか

mode

directionexception

in、out

nearesttozeronegativepositiveextendeddouble singleinexactdivisionunderflowoverflowinvalid allcommon

これらはリテラル文字列であること、出力パラメータ out は最低でも CHARACTER*9 である必要があることに注目してください。inout の取り得る値の意味は、使用時の動作とモードによって異なります。これらの関係を次の表に要約します。

表 6–2 ieee_flags の引数 in と out の意味

inout の値

意味 

nearesttozeronegativepositive

丸めの方向 

extendeddoublesingle

丸めの精度 

inexact、division、underflow、overflow、invalid

例外 

all

5 種類すべての例外 

common

一般的な例外: invalid (無効演算)、division (ゼロ除算)、overflow (オーバーフロー) 

たとえば、フラグが立てられている例外のうちで何がもっとも優先順位が高いかを判別するときは、引数の in に NULL 文字列を渡します。


      CHARACTER *9, out
      ieeer = ieee_flags( 'get', 'exception', '', out )
      PRINT *, out, ' flag raised'

また、overflow 例外フラグが立てられているかどうかを判別するときは、引数の inoverflow を設定します。復帰時に、out が overflow になっていれば、overflow 例外のフラグが立てられているということです。


      ieeer = ieee_flags( 'get', 'exception', 'overflow', out )
      IF ( out.eq. 'overflow') PRINT *, 'overflow flag raised'

例: invalid 例外をクリアーします。


      ieeer = ieee_flags( 'clear', 'exception', 'invalid', out )

例: すべての例外をクリアーします。


      ieeer = ieee_flags( 'clear', 'exception', 'all', out )

例: ゼロに近づけるように丸めます。


      ieeer = ieee_flags( 'set', 'direction', 'tozero', out )

例: 丸めの精度を double に設定します。


      ieeer = ieee_flags( 'set', 'precision', 'double', out )

6.3.1.1 ieee_flags を使用して警告メッセージを抑制する

次の例のように、動作 clear で ieee_flags を呼び出すと、クリアーされてない例外すべてがリセットされます。 プログラムが終了する前にこの呼び出しを置くと、プログラム終了時の浮動小数点例外に関するシステム警告メッセージを抑制します。

例: ieee_flags() を使用して、発生していたすべての例外をクリアーします。


      i = ieee_flags('clear', 'exception', 'all', out )

6.3.1.2 ieee_flags を使用して例外を検出する

次の例は、前の計算によってどの浮動小数点例外フラグが立ったかを決定する方法を示しています。システム include ファイル floatingpoint.h に定義されたビットマスクは、ieee_flags により返された値に適用されます。

この例 DetExcFlg.F では、インクルードファイルは #include 前処理部指令を使用して導入されます。 この指令には、.F 接尾辞のソースファイルを指定しなければいけません。アンダーフローの原因は、最小の倍精度数を 2 で除算しているためです。

例: ieee_flags を使用して例外を検出し、復号化します。


#include "floatingpoint.h"
         CHARACTER*16 out
         DOUBLE PRECISION d_max_subnormal, x
         INTEGER div, flgs, inv, inx, over, under

       x = d_max_subnormal() / 2.0                ! アンダーフローを発生

       flgs=ieee_flags('get','exception','',out)  ! どの例外が発生したのか ?

       inx   = and(rshift(flgs, fp_inexact)  , 1)  ! ieee_flags
       div   = and(rshift(flgs, fp_division) , 1)   ! によって
       under = and(rshift(flgs, fp_underflow), 1)    ! 返される
       over  = and(rshift(flgs, fp_overflow) , 1)     ! 値を
       inv   = and(rshift(flgs, fp_invalid)  , 1)      ! 復号化

       PRINT *, "もっとも優先順位が高い例外:", out
       PRINT *, ' invalid  divide  overflo underflo inexact'
       PRINT '(5i8)', inv, div, over, under, inx
       PRINT *, '(1 = 例外フラグが立っている; 0 = 立っていない)'
       i = ieee_flags('clear', 'exception', 'all', out)    ! すべてクリアー
       END

例: 前出の例 (DetExcFlg.F) をコンパイルして実行します。


demo% f95 DetExcFlg.F
demo% a.out
 もっとも優先順位が高い例外: underflow
  invalid  divide  overflo underflo inexact
       0       0       0       1       1
 (1 = 例外フラグが立っている; 0 = 立っていない)
demo%