このセクションでは、IEEE で推奨される関数、役立つ値を提供する関数、ieee_flags、ieee_retrospective、および standard_arithmetic と nonstandard_arithmetic について説明します。関数 ieee_flags と ieee_handler の詳細は、例外と例外処理を参照してください。
ieee_functions(3m) および ieee_sun(3m) で説明される関数は、IEEE 規格に必要な機能か、またはその付録で推奨されている機能を提供します。これらは、効率的なビットマスク演算として実装されます。
|
|
remainder(x,y) は、IEEE 規格 754-1985 で指定された演算です。remainder(x,y) と fmod(x,y) の違いは、remainder(x,y) によって返される結果の符号が x または y のどちらかの符号と一致しない可能性があるのに対して、fmod(x,y) は常に、符号が x と一致する結果を返す点にあります。どちらの関数も正確な結果を返し、不正確の例外を生成しません。
|
|
無限大、NaN、最大と最小の正の浮動小数点数などの IEEE 値は、ieee_values(3m) のマニュアルページで説明されている関数によって提供されます。 表 22、表 23、表 24、および表 25 は、ieee_values(3m) 関数によって提供される値の 10 進数値と 16 進数の IEEE 表現を示しています。
|
|
|
|
ieee_flags (3m) は、次のための Oracle インタフェースです。
ieee_flags(3m) を呼び出すための構文は次のとおりです。
i = ieee_flags(action, mode, in, out);
パラメータに指定できる値の ASCII 文字列を表 26 に示します。
|
ieee_flags(3m) のマニュアルページでは、これらのパラメータが詳細に説明されています。
ieee_flags を使用して変更できる演算機能のいくつかについては、次の段落で説明します。第 4 章には、ieee_flags と IEEE 例外フラグに関する詳細情報が含まれています。
mode が direction である場合は、指定されたアクションが現在の丸め方向に適用されます。指定できる丸め方向は、もっとも近い値に向けた丸め、0 に向けた丸め、+· に向けた丸め、または -· に向けた丸めです。IEEE のデフォルトの丸め方向は、もっとも近い値に向けた丸めです。つまり、演算の数学的な結果が 2 つの隣接する表現可能な数値の間に厳密に存在する場合、数学的な結果にもっとも近い数値が提供されます。(数学的な結果が 2 つのもっとも近い表現可能な数値の正確に中央に存在する場合、提供される結果は最下位ビットが 0 である数値です。この点を強調するために、もっとも近い値に向けた丸めモードは、もっとも近い偶数値への丸めと呼ばれる場合があります。)
0 に向けた丸めは、IEEE が現れる以前の多くのコンピュータの動作方法であり、数学的には結果の切り捨てに対応しています。 たとえば、2/3 が 10 進数 6 桁に丸められた場合の結果は、丸めモードがもっとも近い値に向けた丸めであるときは .666667 ですが、丸めモードが 0 に向けた丸めであるときは .666666 です。
ieee_flags を使用して丸め方向を検査、クリア、または設定する場合に、4 つの入力パラメータに指定できる値を表 27 に示します。
|
mode が precision である場合は、指定されたアクションが現在の丸め精度に適用されます。x86 ベースのシステムでは、指定できる丸め精度は単精度、倍精度、および拡張です。デフォルトの丸め精度は拡張です。このモードでは、結果を x87 浮動小数点レジスタに渡す算術演算は、その結果を拡張倍精度レジスタ形式の完全な 64 ビット精度に丸めます。丸め精度が単精度または倍精度である場合、結果を x87 浮動小数点レジスタに渡す算術演算は、その結果をそれぞれ 24 または 53 の上位ビットに丸めます。ほとんどのプログラムは少なくとも同程度に正確な結果を生成しますが、拡張の丸め精度が使用されている場合、IEEE 演算のセマンティクスへの厳格な遵守が必要な一部のプログラムは拡張の丸め精度モードでは正しく機能しないため、必要に応じて、単精度または倍精度に設定された丸め精度で実行する必要があります。
丸め精度は、SPARC プロセッサを使用したシステム上では設定できません。これらのシステムでは、mode = precision で ieee_flags を呼び出しても計算には影響を与えません。
最後に、mode が exception である場合は、指定されたアクションが現在の IEEE 例外フラグに適用されます。ieee_flags を使用して IEEE 例外フラグを検査したり、制御したりする方法の詳細は、例外と例外処理を参照してください。
libsunmath 関数である ieee_retrospective は、未処理の例外および非標準の IEEE モードに関する情報を出力します。次の内容が報告されます。
必要な情報は、ハードウェア浮動小数点ステータスレジスタから取得されます。
ieee_retrospective は、設定された例外フラグ、およびトラップが有効になっている例外に関する情報を出力します。これらの 2 つの (関連はしていても) 個別の情報を混同しないでください。例外フラグが設定されている場合は、プログラム実行中のある時点でその例外が発生しました。例外に対してトラップが有効になっている場合は、その例外はまだ実際に発生していない可能性がありますが、発生している場合は、SIGFPE シグナルが提供されています。ieee_retrospective メッセージは、例外フラグが設定されている場合は、調査を必要としている可能性がある例外についてユーザーに警告すること、また例外のトラップが有効になっている場合は、その例外がシグナルハンドラによって処理された可能性がある点をユーザーに知らせることを目的にしています。例外と例外処理では、例外、シグナル、およびトラップについて説明するとともに、発生した例外の原因を調査する方法を示しています。
プログラムは、いつでも ieee_retrospective を明示的に呼び出すことができます。–f77 互換モードの f95 でコンパイルされた Fortran プログラムは、自動的に ieee_retrospective を呼び出してから終了します。デフォルトモードの f95 でコンパイルされた C/C++ プログラムおよび Fortran プログラムは、自動的に ieee_retrospective を呼び出しません。
ただし、f95 コンパイラは共通例外に対するトラップをデフォルトで有効にするため、プログラムがトラップを明示的に無効にするか、または SIGFPE ハンドラをインストールしないかぎり、このような例外が発生するとプログラムがただちに異常終了することに注意してください。–f77 互換モードでは、コンパイラがトラップを有効にしないため、浮動小数点例外が発生してもプログラムは実行を継続し、終了時に ieee_retrospective 出力でこれらの例外を報告します。
この関数を呼び出すための構文は次のとおりです
C、C++ - ieee_retrospective(fp);
Fortran - call ieee_retrospective()
C 関数の場合、引数 fp は、出力が書き込まれるファイルを指定します。Fortran 関数は、常に出力を stderr に出力します。
次の例は、ieee_retrospective の 6 つの警告メッセージのうちの 4 つを示しています。
Note: IEEE floating-point exception flags raised: Inexact; Underflow; Rounding direction toward zero IEEE floating-point exception traps enabled: overflow; See the Numerical Computation Guide, ieee_flags(3M), ieee_handler(3M), ieee_sun(3m)
警告メッセージは、トラップが有効になっているか、または例外が発生した場合にのみ表示されます。
ieee_retrospective メッセージは、Fortran プログラムから 3 つの方法のいずれかで抑制できます。 1 つの方法は、プログラムが終了する前に、未処理の例外をすべてクリアし、トラップを無効にして、もっとも近い値への丸め、拡張精度、および標準モードに戻す方法です。これを行うには、ieee_flags、ieee_handler、および standard_arithmetic を次のように呼び出します。
character*8 out i = ieee_flags('clearall', '', '', out) call ieee_handler('clear', 'all', 0) call standard_arithmetic()
ieee_retrospective メッセージが表示されないようにするための別の方法は、stderr のファイルへのリダイレクトです。もちろん、プログラムが ieee_retrospective メッセージ以外の出力を stderr に送信する場合は、この方法を使用してはいけません。
3 番目の方法は、たとえば次のように、プログラム内にダミーの ieee_retrospective 関数を含める方法です。
subroutine ieee_retrospective return end
IEEE 演算で説明されているように、IEEE 演算ではアンダーフローした結果を、段階的 アンダーフローを使用して処理します。SPARC ベースの一部のシステムでは、段階的アンダーフローは多くの場合、演算のソフトウェアエミュレーションを部分的に使用して実装されます。 多くの計算がアンダーフローすると、これによってパフォーマンスが低下する場合があります。
特定のプログラムがこれに該当するかどうかについての何らかの情報を取得するには、ieee_retrospective または ieee_flags を使用してアンダーフロー例外が発生したかどうかを判定し、さらにプログラムによって使用されているシステム時間数をチェックできます。プログラムがオペレーティングシステムで異常に多い時間を費やし、アンダーフロー例外を発生させている場合は、段階的アンダーフローが原因である可能性があります。この場合は、IEEE 以外の演算を使用すると、プログラムの実行が速くなる可能性があります。
関数 nonstandard_arithmetic は、IEEE 以外の演算モードをサポートしているプロセッサ上で、これらの演算モードを有効にします。SPARC システムでは、この関数は、浮動小数点ステータスレジスタ内の NS (非標準の演算) ビットを設定します。SSE 命令をサポートしている x86 システムでは、この関数は、MXCSR レジスタ内の FTZ (0 へのフラッシュ) ビットを設定します。また、DAZ (非正規数が 0) ビットをサポートしているプロセッサ上の MXCSR レジスタ内のこのビットも設定します。非標準モードの影響はプロセッサによって異なり、通常は堅牢なソフトウェアの誤動作を引き起こす場合もあることに注意してください。非標準モードは、通常の使用にはお勧めできません。
関数 standard_arithmetic は、デフォルトの IEEE 演算を使用するようにハードウェアをリセットします。どちらの関数も、デフォルトの IEEE 754 の演算方法のみを提供するプロセッサには影響を与えません。このようなプロセッサの 1 つに SPARC T4 があります。