基本ハンドラが浮動小数点例外を重大 (severe) または非重大のどちらで処理するかは,/fpe および /check:underflow コンパイラ・オプションの選択に依存します。/fpe オプションは,基本例外ハンドラの動作以上を制御します。
/fpe オプションは,特定の浮動小数点例外動作を選択します。ia32 システムに対して,現在,サポートする動作が 2 つあります。
ia32 システムの基本設定の /fpe:3 を使用すると,完全な IEEE サポートが適用されます。浮動小数点例外は浮動小数点ステイタス・ワードに記録されますが,このモードでは浮動小数点トラップはありません。
第 2 オプション /fpe:0 は,浮動小数点例外のトラップを可能にし,アンダーフローの結果を 0.0 にフラッシュします。
/fpe コンパイラ・オプションの完全な結果は,ビルドするアプリケーションのタイプに依存します。基本実行時例外ハンドラを置き換えてないと仮定すると,Fortran Console または QuickWin/Standard Graphics アプリケーションでの選択した動作に対して完全なサポートを得られます。完全な動作を実行するための作業は,基本実行時ハンドラ,Fortran コンパイラ,算術ライブラリー,ハードウェア,およびオペレーティング・システムの各々が部分的に実行します。
以下の内容について説明します。
Fortran Console,Fortran QuickWin,および Fortran Standard Graphics アプリケーションでの浮動小数点例外
Fortran Console アプリケーションをビルドする時,基本コンパイラ・オプションまたは選択したコンパイラ・オプションのどちらかで環境を初期化するFortran 実行時ルーチンを呼び出す幾つかの呼び出しを,コンパイラは Fortran 主プログラムの先頭に生成します。
浮動小数点例外処理に対して,/fpe:3 が ia32 システムの基本設定です。実行時システムは,全ての例外をマスクするようにハードウェアを初期化します。/fpe:3 を指定すると,以下のことが行われます。
Visual Fortran 実行時システムは, (コンパイルされたコードからの呼び出しなしで) 自動的にこの初期化を行います。
ia32 ハードウェアは,例外結果に対して基本 IEEE 結果を自動的に生成します。
トラップが /fpe:3 でマスクされるため,トラップはなく,計算結果で NaN,無限大,および規格化されていない数字のような例外値を見ることになります。
例外が発生した時,ユーザーは GETSTATUSFPQQ で浮動小数点ステイタス・ワードを調査することができ,CLEARSTATUSFPQQ でステイタス・レジスタをクリアすることができます。
/fpe:0 を指定した場合,コンパイラは,浮動小数点コントロール・ワードのすべての浮動小数点トラップをアンマスクする引数で Visual Fortran 実行時ルーチン FOR_SET_FPE の呼び出しを生成します。この場合,ハードウェアは基本 IEEE 結果を提供しません。それはオペレーティング・システムでトラップされ,ハンドラを探します。
Fortran Console または Fortran QuickWin アプリケーションでは,Visual Fortran 実行時システムは,専用のハンドラを確立しない限り,基本ハンドラを提供します。アンダーフローを除くすべての例外に対して,実行時システムはエラー・メッセージを表示し,アプリケーションを終了します。アンダーフローに対して,実行時システムは結果をゼロで置き換えます。/fpe:0 を指定した時の規格化されていない数字のこの取り扱いは,不意のアンダーフロー (Abrupt Underflow) と呼ばれ 0 (ゼロ) になります。その逆の 漸進的なアンダーフロー は /fpe:3 で 0 になります。
/fpe:0 では規格化されていない数字はありません。さらに,/check:underflow を /fpe:0 と一緒に選択すると,浮動小数点アンダーフローの最初の 2 回とアプリケーションが終了した時点でのアンダーフローの総数の各々に対して実行時にメッセージが発行されます。/check:underflow オプションは,/fpe:3 ではサポートされません。
アンダーフロー結果をゼロに修正することは,ia32 アプリケーションの性能を著しく低下させます。アンダーフローが頻繁に発生する場合,アンダーフローが発生しないようにコードを変更する,または,アンダーフロー・とラップをマスクし,規格化されない数字をハードウェアが操作できるようにすることを考慮してください。ia32 ハードウェアは,規格化されない範囲で正しく動作するように設計されており,そのようにすることは結果をゼロに修正するためのトラップを行うことよりも高速になります。
/fpe オプションの選択について理解することの他の重要な点は,生成されたコードがトラッピング・モードをサポートしなければならないことです。ia32 浮動小数点命令が例外結果を生成する時,トラップを得る必要はありません。命令は,トラップを発生させるようにするために,fwait 命令または浮動小数点演算命令に従わなければなりません。
Visual Fortran コンパイラは,/fpe オプションの選択に関連するこれらの要求をサポートするための機械語コードを生成します。言い換えれば,生成されたコードは,トラッピング・モードをサポートしなえればなりません。簡単なテスト・プログラムをコンパイルすることで,これを見ることができます。まず,/fpe:0 で,次に /fpe:3 でコンパイルして機械語コード・リストを調べます。/fpe:3 では,fwait 命令がありません。自分独自のハンドラで基本実行時例外ハンドラを置き換えた場合でも,トラッピングをサポートするコードを生成するために,/fpe:0 でコンパイルすることもできます。
DLL では,(Fortran で主プログラムを書かなければ) 主 Fortran プログラムがありません。そのため,環境を初期化する実行時ルーチンの自動呼出しがありません。/fpe:0 を選択したとしても,実行時システムにハードウェアでのトラップをアンマスクさせることはありません。そのため,トラップを見ることができません。ハードウェアが生成する基本 IEEE 結果 (計算での NaN, 無限大,規格化されていない数字) を見つづけることになります。生成されたコードは,fwait 命令などを提供することで部分的に行いますが,トラップがどこかでアンマスクされない限り,トラップは発生しません。浮動小数点コントロール・ワードでトラップをアンマスクするために SETCONTROLFPQQ または FOR_SET_FPE を使用することができます。
DLL では,基本例外処理もありません。DLL を呼び出す主アプリケーションがこれを提供するか,DLL のコードがそれが呼び出される時に何かを提供しなければなりません。アンダーフロー処理 (0 に修正など) が基本 Fortran 実行時システム・ハンドラで行われるため,DLL は自動的にはその機能を持っていません。
一般的なやり方としては,/fpe:0 でコンパイルします。しかし,浮動小数点コントロール・ワードの浮動小数点のゼロによる除算,浮動小数点オーバーフロー,および浮動小数点の不正確な値のトラップのみをアンマスクします。浮動小数点アンダーフロー・トラップをマスクしたままにしておくことによって,ハードウェアは規格化されない範囲を通して漸進的なアンダーフローを提供しつづけます。しかし他の浮動小数点例外は,トラップを生成するので,ユーザーは希望に応じて処理することができます。
Fortran Windows アプリケーションでの浮動小数点例外
Fortran Windows アプリケーションでは,状況は Fortran DLL アプリケーションに似ています。アプリケーションの主エントリ・ポイントとして Fortran コードに WinMain ルーチンを定義します。Fortran 実行時システムは,Fortran Console または Fortran QuickWin (または Standard Graphics) アプリケーションで行ったような主ルーチンを定義しません。コードは,基本ハンドラで保護されませんし,基本実行時初期化ルーチンは呼び出されません。