fordef.for ファイルとその使用

fordef.for には、浮動小数点表現のクラスに対応するシンボルおよび INTEGER*4 の値が含まれています。これらのクラスには、正の正規化されていない数値を示すビット・パターンなどの例外も含まれています。

シンボルが含まれたこのファイルと、FP_CLASS 組み込み関数を使用することで、例外的な数値の識別が可能になります。例えば、これにより、正または負の正規化されていない数値を正のゼロに置換できます。

次は、浮動小数点のビット表現を識別する簡単な例です。

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

この例では、for_k_fp_pos_norm ファイルのシンボル fordef.for と、REAL*4 の値 57.0 を引数とした FP_CLASS 組み込み関数の戻り値を比べた結果、最初の print 文が実行されます。

次の表では、fordef.for ファイル内のシンボルとその対応する浮動小数点表現について説明します。

fordef.for のシンボル

シンボル名

浮動小数点のビット表現のクラス

FOR_K_FP_SNAN

シグナル型 NaN

FOR_K_FP_QNAN

クワイエット型 NaN

FOR_K_FP_POS_INF

正の無限大

FOR_K_FP_NEG_INF

負の無限大

FOR_K_FP_POS_NORM

正の正規化された有限数

FOR_K_FP_NEG_NORM

負の正規化された有限数

FOR_K_FP_POS_DENORM

正の正規化されていない数

FOR_K_FP_NEG_DENORM

負の正規化されていない数

FOR_K_FP_POS_ZERO

正のゼロ

FOR_K_FP_NEG_ZERO

負のゼロ

次に、fordef.for ファイルと組み込み関数 FP_CLASS を使用したもう 1 つの例を示します。このプログラムの目的は、例外が発生しても報告を行わず、書式なしファイルから 32 ビット・パターンを REAL*4 に、素早く読み取り、正規化されていない数値を正のゼロに置換します。

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

このプログラムは、任意の -fpen (Linux* および Mac OS* X) または /fpe:n (Windows*) の値でコンパイルできます。組み込み関数 FP_CLASS は、プログラムが正規化されていない数値で計算を実行しようとする前に、正規化されていない数値を検索して、ゼロに置換します。

一方、プログラムが -fpe0 または /fpe:0 でコンパイルされていて、ユニット 1 から読み込まれた正規化されていない数値がゼロに置換されない場合、正規化されていない数値を使った最初の計算で浮動小数点例外が発生します。/fpe:0 でコンパイルする場合は、FTZ (Flush-to-Zero) が有効になります。計算結果でゼロ除算、オーバーフロー、または無効な演算が発生した場合、アプリケーションは浮動小数点例外により終了します。または、そのデータを使用したプログラムは、最後まで実行されますが、おそらく異なる答えを導き出して終了します。

fordef.for ファイルと組み込み関数 FP_CLASS を一緒に使用することで、NaN を識別できます。上記の例のバリエーションとして、IF 文に for_k_fp_snan シンボルと for_k_fp_qnan シンボルを含めることもできます。より簡単にこの方法を行うには、組み込み関数 ISNAN を使用します。ISNAN を使用した、上記の例の修正は次のようになります。

! 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

このプログラムは、任意の -fpen または /fpe:n の値でコンパイルできます。