# マニュアルページ fex_setexcepthandler.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 とリンク
         する方法についての詳細は、『数値計算ガイド』を参照してくださ
         い。