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 の値でコンパイルできます。