fex_set_handling(3M)

名前
fex_set_handling, fex_get_handling, fex_getexcepthandler, fex_setexcepthandler - 浮動小数点例外処理モードの制御

形式

cc [ flag ... ] file ... -R/opt/SUNWspro/lib -L/opt/SUNWspro/lib -lm9x [ library ... ]

#include <fenv.h>

int fex_set_handling(int ex, int mode, void (*handler)());

int fex_get_handling(int ex);

void fex_getexcepthandler(fex_handler_t *buf, int ex);

void fex_setexcepthandler(const fex_handler_t *buf, int ex);

機能説明

これらの関数は、浮動小数点例外処理モードを制御します。これらの関数において、 ex 引数は、次の値 (<fenv.h> で定義されている) の任意のビット単位の 論理和により、1 つまたは複数の例外を指定します。

    FEX_INEXACT
    FEX_UNDERFLOW
    FEX_OVERFLOW
    FEX_DIVBYZERO
        ゼロによる除算
    FEX_INV_ZDZ
        0/0 の無効な演算
    FEX_INV_IDI
        infinity/infinity の無効な演算
    FEX_INV_ISI
        infinity-infinity の無効な演算
    FEX_INV_ZMI
        0*infinity の無効な演算
    FEX_INV_SQRT
        負のオペランドによる平方根
    FEX_INV_SNAN
        非数への符号付け
    FEX_INV_INT
        無効な整数変換
    FEX_INV_CMP
        無効な比較

便宜上、次の値の結合も定義されています。

    FEX_NONE
        例外なし
    FEX_INVALID
        すべての無効な演算例外
    FEX_COMMON
        オーバーフロー、ゼロによる除算、および無効な演算
    FEX_ALL
        すべての例外

fex_set_handling(ex, mode, handler) は、ex で示し た浮動小数点例外を処理するために、指定した mode を確立します。選択した mode は、指定した例外の 1 つが発生したときに行うべきアクションを決定しま す。mode は、次の値の 1 つでなければなりません。

    FEX_NOHANDLER
        トラップしますが、例外は処理しません。その代わりに、通常であれば有効である、 あらゆる種類の関連する動作を呼び出します。これは、例外のトラップが有効である ときのデフォルトの動作です。handler パラメータは無視されます。

    FEX_NONSTOP
        例外の原因となった演算に IEEE 754 デフォルト結果を提供し、例外のフラグを 設定し、実行を継続します。これは、例外のトラップが無効であるときのデフォルトの 動作です。handler パラメータは無視されます。

    FEX_ABORT
        abort(3C) を呼び出します。handler パラメータは無視されます。

    FEX_SIGNAL
        通常は sigfpe(3) 経由でインストールされたシグナルハンドラに提供されるパラ メータで、関数 *handler を呼び出します。

    FEX_CUSTOM
        関数 *handler を呼び出します (次の段落を参照)。

FEX_CUSTOM モードでは、浮動小数点例外が発生すると、ハンドラ関数が次のプロ トタイプとして呼び出されます。

    #include <fenv.h>

    void handler(int ex, fex_info_t *info);

この関数に入るとき、ex は発生した例外に対応する (上記リストの最初の 12 個の例外の) 値です。info->op は例外の原因となる演算を示します。info->op1 と info->op2 にはオペランドの値が含まれます。info->res にはデフォルトのトラップされなかった結果の値が含まれます。info->flags は、 トラップされなかった場合に演算が設定する例外フラグを反映します。ハンドラが戻る 場合、終了時に info->res に含まれている値が演算の結果に置き換えられ、 info->flags で示したフラグが設定され、例外が発生したところから実行が再開 されます。info->res と info->flags を変更すると、ハンドラは希望す る結果の値とフラグを提供できます。また、例外がアンダーフローまたはオーバーフロ ーした場合、ハンドラは次を設定できます。

    info->res.type = fex_nodata;

これによって、IEEE 754 で指定されている指数調整された結果に置き換えられま す。ハンドラが info->res または info->flags を変更しなかった場合、そ の結果は、例外がトラップされなかった場合と同じになることに注意してください。

例外の原因となる演算のデフォルトのトラップされなかった結果は常に FEX_CUSTOM ハンドラで利用できますが、一方または両方のオペランドは利用で きない場合があります。このような場合、info->op1.type== fex_nodata または info->op2.type == fex_nodata でハンドラが呼び出され、それぞれのデータ構造 体が有効なデータを持っていないことを示します。たとえば、例外の原因とな る演算が単項演算である場合は、info->op2.type == fex_nodata が設定されます。 カスタムのハンドラは、オペランド値にアクセスする前に、必ずオペランドデータ構造体 の type フィールドを検査し、有効なデータが適切な形式で入っていることを確 認しなければなりません。

fex_get_handling(ex) は、ex で指定した例外の現在の処理モード を戻します。ex は、上記リストの最初の 12 個の例外の 1 つでなければなりません。

fex_getexcepthandler(buf, ex) は、ex で指定した例外の 現在の処理モードと関連するデータを、buf が指すデータ構造体に保存します。 型 fex_handler_t は <fenv.h> に定義されています。

fex_setexcepthandler(buf, ex) は、ex で指定した例外の 現在の処理モードと関連するデータを、buf が指すデータ構造体から復元します。 このデータ構造体は、fex_getexcepthandler() への以前の呼び出しで設定さ れていなければなりません。そうでない場合は、示したフラグの影響は定義されません。

戻り値
fex_set_handling は、要求した例外処理モードが確立された場合にはゼロ以外の 値を戻し、そうでない場合はゼロを戻します。

使用例
次の例は、0/0 の無効な演算の結果を、あらかじめ決められた値に置き換える方法を示し ています。

    #include <math.h>
    #include <fenv.h>
    double k;
    void presub(int ex, fex_info_t *info) {
    	info->res.type = fex_double;
    	info->res.val.d = k;
    }
    int main() {
    	double x, w;
    	int i;
    	fex_handler_t buf;
    /*
     * 現在の 0/0 ハンドラを保存する。
     */
    	(void) fex_getexcepthandler(&buf, FEX_INV_ZDZ);
    /*
     * 0/0 用の前置換ハンドラを設定する。
     */
    	(void) fex_set_handling(FEX_INV_ZDZ, FEX_CUSTOM, presub);
    /*
     *  (k*x)/sin(x) を計算する。k = 2.0、x = 0.5, 0.4, ..., 0.1, 0.0
     */
    	k = 2.0;
    	(void) printf("Evaluating f(x) = (k*x)/sin(x)\n\n");
    	for (i = 5; i >= 0; i--) {
    	        x = (double) i * 0.1;
    	        w = (k * x) / sin(x);
    	        (void) printf("\tx=%3.3f\t f(x) = % 1.20e\n", x, w);
    	}
    /*
     * 古い 0/0 ハンドラを復元する。
     */
    	(void) fex_setexcepthandler(&buf, FEX_INV_ZDZ);
    	return 0;
    }

上記プログラムからの出力は次のようになります。

    Evaluating f(x) = (k*x)/sin(x)
    	x=0.500  f(x) =  2.08582964293348816000e+00
    	x=0.400  f(x) =  2.05434596443822626000e+00
    	x=0.300  f(x) =  2.03031801709447368000e+00
    	x=0.200  f(x) =  2.01339581906893761000e+00
    	x=0.100  f(x) =  2.00333722632695554000e+00
    	x=0.000  f(x) =  2.00000000000000000000e+00

x = 0 のとき、f(x) は 0/0 として計算され、無効な演算例外が発生するこ とに注意してください。この例では、結果が値 2.0 に置き換えられています。

属性
次の属性については、 attributes(5) を参照してください。

属性タイプ | 属性値
使用条件 | SPROm9xs
インタフェース安定性 | 安定
MT レベル | MT-安全 (次を参照)

関連項目
sigfpe(3), feclearexcept(3M), fegetenv(3M), fex_set_log(3M), attributes(5)

『 数値計算ガイド 』

注意事項
マルチスレッド化されたプログラムでは、上記関数は、呼び出したスレッドだけの例外処 理モードに影響を与えます。

このページに記述されている関数は、必要に応じて自動的に、SIGFPE ハンドラを インストールまたはインストール解除し、浮動小数点状態レジスタのトラップ有効モード ビットを設定またはクリアします。これらの関数をプログラムで使用し、個別に、 SIGFPE ハンドラをインストールしようとした場合、あるいはトラップ有効モー ドビットを制御しようとした場合、その結果の動作は定義されていません。

FEX_CUSTOM モードでインストールされている処理関数が呼び出されると、すべ ての例外トラップは無効になります。SIGFPE シグナルがブロックされていると き、このようなハンドラが呼び出されると、feclearexcept(3M)、 fegetenv(3M)、および fex_set_log(3M) に記述されている浮動小数点環境 、例外フラグ、および遡及診断関数は再びトラップを有効にしません。したがって、 ハンドラ自身は常に FEX_NONSTOP モードで、遡及診断の記録を無効にして動作 しています。ハンドラ内でこれらのモードを変更しようとすると、予期せぬ結果になり ます。

「形式」で示しているように、cc で libm9x とリンクするためには、コマンド行 で次のように指定することを推奨します。

    -Rinstall-path/lib -Linstall-path/lib -lm9x

install-path には、コンパイラがインストールされている場所を指定します (デ フォルトでは、/opt/SUNWspro)。libm9x とリンクする方法についての詳細は、 『数値計算ガイド』を参照してください。