-fpen (Linux* および Mac OS* X) オプションまたは /fpe:n (Windows*) オプションを使用すると、浮動小数点例外の結果をある程度制御することができます。
-fpe0 や /fpe:0 は、オーバーフロー、ゼロ除算、および無効な浮動小数点例外を有効にすることにより、浮動小数点例外を制限します。プログラムはエラーメッセージを出力し、例外が発生したときに終了します。浮動小数点アンダーフローが発生した場合、結果はゼロに設定され、プログラムはそのまま実行されます。これは、FTZ (Flush-to-Zero) と呼ばれます。このオプションは、-fp-speculation または /Qfp-speculation オプションを指定しない場合に、-fp-speculation=strict (Linux および Mac OS X) または /Qfp-speculation (Windows) を設定します。-fpe0 オプションまたは /fpe:0 オプションは、-ftz (Linux および Mac OS X) /Qftz (Windows) を設定します。例外が発生した場所の詳細な位置の情報を取得するには、-traceback (Linux および Mac OS X) または /traceback (Windows) を使用します。
IA-32 アーキテクチャー・ベース・システムまたはインテル® 64 アーキテクチャー・ベース・システムでは、明示的に -fpe0 や /fpe:0 を設定すると、突発アンダーフロー (abrupt underflow) 修正を可能にするために、各浮動小数点命令の後、生成されたコードストリームを同期しなければならないので、パフォーマンスが低下します。
-fpe1 または /fpe:1 は、浮動小数点アンダーフローのみを制限します。浮動小数点オーバーフロー、ゼロによる浮動小数点除算、および無効な浮動小数点が発生した場合、結果は例外値 (NaN および符号付き無限大) になり、プログラムはそのまま実行されます。浮動小数点アンダーフローが発生した場合、結果はゼロに設定され、プログラムはそのまま実行されます。/fpe:1 オプションは -ftz または /Qftz を設定します。
IA-32 アーキテクチャー・ベース・システムまたはインテル® 64 アーキテクチャー・ベース・システムでは、明示的に -fpe1 や /fpe:1 を設定すると、突発アンダーフロー (abrupt underflow) 修正を可能にするために、各浮動小数点命令の後、生成されたコードストリームを同期しなければならないので、パフォーマンスが低下します。
-fpe3 または /fpe:3 は、すべてのプロセッサーのデフォルトで、浮動小数点例外動作を制限しません。浮動小数点オーバーフロー、ゼロによる浮動小数点除算、および無効な浮動小数点が発生した場合、結果は例外値 (NaN および符号付き無限大) になり、プログラムはそのまま実行されます。浮動小数点アンダーフローは漸次アンダーフロー (gradual underflow) で、結果はゼロになるまで正規化されていない値になります。
-fpe オプションまたは /fpe オプションは、Fortran メインプログラムでのみ例外を有効にします。Fortran メインプログラムによって設定された浮動小数点例外動作は、プログラマーにより変更されない限り、プログラム全体の実行に影響します。メインプログラムが Fortran ではない場合、ユーザーは Fortran 組み込み関数 FOR_SET_FPE を使用して浮動小数点例外動作を設定することができます。
プログラムに含まれる各ルーチンを別々にコンパイルする際は、-fpen または /fpe:n オプションで同じ n 値を使用してください。
次に、例を示します。
IMPLICIT NONE
real*4 res_uflow, res_oflow
real*4 res_dbyz, res_inv
real*4 small, big, zero, scale
small = 1.0e-30
big = 1.0e30
zero = 0.0
scale = 1.0e-10
! IEEE underflow condition (Underflow Raised)
res_uflow = small * scale
write(6,100)"Underflow: ",small, " *", scale, " = ", res_uflow
! IEEE overflow condition (Overflow Raised)
res_oflow = big * big
write(6,100)"Overflow:", big, " *", big, " = ", res_oflow
! IEEE divide-by-zero condition (Divide by Zero Raised)
res_dbyz = -big / zero
write(6,100)"Div-by-zero:", -big, " /", zero, " = ", res_dbyz
! IEEE invalid condition (Invalid Raised)
res_inv = zero / zero
write(6,100)"Invalid:", zero, " /", zero, " = ", res_inv
100 format(A14,E8.1,A2,E8.1,A2,E10.1)
end
次のコマンドラインについて考えてみます。
ifort fpe.f90 -fpe0 -fp-model strict -g (Linux および Mac OS X)
ifort fpe.f90 /fpe:0 /fp:strict /traceback (Windows)
次のような結果が出力されます。
Windows:
Underflow: 0.1E-29 * 0.1E-09 = 0.0E+00
forrtl: error (72): floating overflow
Image PC Routine Line Source
fpe.exe 0040115B Unknown Unknown Unknown
fpe.exe 0044DFC0 Unknown Unknown Unknown
fpe.exe 00433277 Unknown Unknown Unknown
kernel32.dll 7C816D4F Unknown Unknown Unknown
Linux および Mac OS X:
./a.out
Underflow: 0.1E-29* 0.1E-09 = 0.0E+00
forrtl: error (72): floating overflow
Image PC Routine Line Source
a.out 0804A063 Unknown Unknown Unknown
a.out 08049E78 Unknown Unknown Unknown
Unknown B746B748 Unknown Unknown Unknown
a.out 08049D31 Unknown Unknown Unknown
Aborted
次のコマンドラインでは /fpe1 を使用します。
ifort fpe.f90 -fpe1 -g (Linux および Mac OS X)
ifort fpe.f90 /fpe:1 /traceback (Windows)
次の出力が生成されます。
Underflow: 0.1E-29 * 0.1E-09 = 0.0E+00
Overflow: 0.1E+31 * 0.1E+31 = Infinity
Div-by-zero: -0.1E+31 / 0.0E+00 = -Infinity
Invalid: 0.0E+00 / 0.0E+00 = NaN
次のコマンドラインでは /fpe3 を使用します。
ifort fpe.f90 -fpe3 -g (Linux および Mac OS X)
ifort fpe.f90 /fpe:3 /traceback (Windows)
次の出力が生成されます。
Underflow: 0.1E-29 * 0.1E-09 = 0.1E-39
Overflow: 0.1E+31 * 0.1E+31 = Infinity
Div-by-zero: -0.1E+31 / 0.0E+00 = -Infinity
Invalid: 0.0E+00 / 0.0E+00 = NaN