Provided by: manpages-ja-dev_0.5.0.0.20131015+dfsg-2_all
名前
matherr - SVID 数学ライブラリの例外処理
書式
#define _SVID_SOURCE /* feature_test_macros(7) 参照 */ #include <math.h> int matherr(struct exception *exc); extern _LIB_VERSION_TYPE _LIB_VERSION; -lm でリンクする。
説明
System V Interface Definition (SVID) では、各種の数学関数は数学的な 例外を検出した場合に matherr() を呼ばれる関数を起動すべきである、 と規定されている。この関数は数学関数が返る前 に呼び出される。 matherr() が返った後に、システムは数学関数に戻り、 それから呼び出し元に返 る。 matherr() の仕組みは glibc によりサポートされているが、 現在は廃止予定の扱いである。 新し くアプリケーションを作成する際には、 math_error(7) と fenv(3) で説明されている手法を使用す べきである。 このマニュアルページでは、古いアプリケーションを保守したり移植する際の 助けと なるよう、 glibc の matherr() の仕組みについて説明する。 matherr() を使用するためには、 プログラマは (どのヘッダファイルをインクルードするよりも前 に) _SVID_SOURCE 機能検査マクロを定義し、値 _SVID_ をグローバル変数 _LIB_VERSION に代入し なければならない。 デフォルト版の matherr() がシステムによって提供されている。 デフォルト版は何も行わず、0 を 返す (このことの重要性については 下記を参照)。プログラマが matherr() を定義することで、 デ フォルト版を上書きすることができる。 プログラマが定義した関数は例外が発生した際に起動され る。 この関数は引き数 1 個で起動され、その引き数は以下に示す exception 構造体へのポインタ である。 struct exception { int type; /* Exception type */ char *name; /* Name of function causing exception */ double arg1; /* 1st argument to function */ double arg2; /* 2nd argument to function */ double retval; /* Function return value */ } type フィールドは以下の値のいずれかである。 DOMAIN 領域エラー (domain error) が発生した (関数の引き数が関数が定義された範囲外で あった)。 返り値は関数によって異なり、 error には EDOM が設定される。 SING 極エラー (pole error) が発生した (関数の結果が無限大である)。 返り値はほとんど の場合 HUGE (最大の単精度浮動小数点数) となり、 たいていは符号付きである。 ほ とんどの場合、errno には EDOM が設定される。 OVERFLOW オーバーフローが発生した。 ほとんどの場合、値 HUGE が返され、 errno には ERANGE が設定される。 UNDERFLOW アンダーフローが発生した。 0.0 が返され、 errno に ERANGE が設定される。 TLOSS Total loss of significance が発生した。 0.0 が返され、 errno に ERANGE が設定 される。 PLOSS Partial loss of significance が発生した。 この値は glibc (や他の多くのシステ ム) で使用されていない。 フィールド arg1 と arg2 は関数に渡された引き数である (引き数を一つしか取らない関数の場合は arg2 は不定となる)。 retval フィールドはその数学関数が呼び出し元に返そうとしている返り値 を示す。プログラマが定 義した matherr() でこのフィールドを変更する ことで、その数学関数の返り値を変更することがで きる。 matherr() 関数が 0 を返した場合、 システムは errno を上記の通り設定し、標準エラー出力に エ ラーメッセージを表示することがある (下記参照)。 matherr() 関数が 0 以外の値を返した場合、 システムは errno を設定せず、エラーメッセージの 表示も行わない。 matherr() を利用している数学関数 下記の表は、関数と matherr() が呼び出される状況の一覧である。 "Type" 列 は matherr() が呼 び出される際に exc->type に 設定される値を示す。 "Result" 列は exc->retval に 設定されるデ フォルトの返り値を示す。 "Msg?" 列と "errno" 列は matherr() が 0 を返した場合のデフォルトの 動作を示す。 "Msg?" 列 に "y" が入っている場合、システムは標準エラー 出力にエラーメッセージを表示する。 以下の表では、下記の記法と省略形を使用している。 x 関数の最初の引き数 y 関数の二番目の引き数 fin 引き数の値が無限大 neg 引き数が負の値 int 引き数が整数値 o/f 結果のオーバーフロー u/f 結果のアンダーフロー |x| x の絶対値 X_TLOSS <math.h> で定義される定数 Function Type Result Msg? errno acos(|x|>1) DOMAIN HUGE y EDOM asin(|x|>1) DOMAIN HUGE y EDOM atan2(0,0) DOMAIN HUGE y EDOM acosh(x<1) DOMAIN NAN y EDOM atanh(|x|>1) DOMAIN NAN y EDOM atanh(|x|==1) SING (x>0.0)? y EDOM HUGE_VAL : -HUGE_VAL cosh(fin) o/f OVERFLOW HUGE n ERANGE sinh(fin) o/f OVERFLOW (x>0.0) ? n ERANGE HUGE : -HUGE sqrt(x<0) DOMAIN 0.0 y EDOM hypot(fin,fin) o/f OVERFLOW HUGE n ERANGE exp(fin) o/f OVERFLOW HUGE n ERANGE exp(fin) u/f UNDERFLOW 0.0 n ERANGE exp2(fin) o/f OVERFLOW HUGE n ERANGE exp2(fin) u/f UNDERFLOW 0.0 n ERANGE exp10(fin) o/f OVERFLOW HUGE n ERANGE exp10(fin) u/f UNDERFLOW 0.0 n ERANGE j0(|x|>X_TLOSS) TLOSS 0.0 y ERANGE j1(|x|>X_TLOSS) TLOSS 0.0 y ERANGE jn(|x|>X_TLOSS) TLOSS 0.0 y ERANGE y0(x>X_TLOSS) TLOSS 0.0 y ERANGE y1(x>X_TLOSS) TLOSS 0.0 y ERANGE yn(x>X_TLOSS) TLOSS 0.0 y ERANGE y0(0) DOMAIN -HUGE y EDOM y0(x<0) DOMAIN -HUGE y EDOM y1(0) DOMAIN -HUGE y EDOM y1(x<0) DOMAIN -HUGE y EDOM yn(n,0) DOMAIN -HUGE y EDOM yn(x<0) DOMAIN -HUGE y EDOM lgamma(fin) o/f OVERFLOW HUGE n ERANGE lgamma(-int) or SING HUGE y EDOM lgamma(0) tgamma(fin) o/f OVERFLOW HUGE_VAL n ERANGE tgamma(-int) SING NAN y EDOM tgamma(0) SING copysign( y ERANGE HUGE_VAL,x) log(0) SING -HUGE y EDOM log(x<0) DOMAIN -HUGE y EDOM log2(0) SING -HUGE n EDOM log2(x<0) DOMAIN -HUGE n EDOM log10(0) SING -HUGE y EDOM log10(x<0) DOMAIN -HUGE y EDOM pow(0.0,0.0) DOMAIN 0.0 y EDOM pow(x,y) o/f OVERFLOW HUGE n ERANGE pow(x,y) u/f UNDERFLOW 0.0 n ERANGE pow(NaN,0.0) DOMAIN x n EDOM 0**neg DOMAIN 0.0 y EDOM neg**non-int DOMAIN 0.0 y EDOM scalb() o/f OVERFLOW (x>0.0) ? n ERANGE HUGE_VAL : -HUGE_VAL scalb() u/f UNDERFLOW copysign( n ERANGE 0.0,x) fmod(x,0) DOMAIN x y EDOM remainder(x,0) DOMAIN NAN y EDOM
例
以下のサンプルプログラムは log(3) を呼び出した際の matherr() の使用法を示したものである。 最初の引き数は log(3) に渡す浮動小数点数である。 省略可能な第二引き数を指定した場合、 _LIB_VERSION に _SVID_ が設定され、 matherr() が呼ばれるようになる。 このコマンドライン引 き数で指定した整数は、 matherr() からの返り値として使用される。 省略可能な第三引き数を指定 した場合、 matherr() は 数学関数の返り値として代わりに引き数で指定した値を割り当てる。 以下の実行例では、 log(3) に引き数 0.0 が渡しているが、 matherr() は使用しない。 $ ./a.out 0.0 errno: Numerical result out of range x=-inf 以下の実行例では、 matherr() が呼び出され、返り値 0 が返される。 $ ./a.out 0.0 0 matherr SING exception in log() function args: 0.000000, 0.000000 retval: -340282346638528859811704183484516925440.000000 log: SING error errno: Numerical argument out of domain x=-340282346638528859811704183484516925440.000000 メッセージ "log: SING error" は C ライブラリによって出力されている。 次の実行例では、 matherr() が呼び出され、0 以外の返り値が返される。 $ ./a.out 0.0 1 matherr SING exception in log() function args: 0.000000, 0.000000 retval: -340282346638528859811704183484516925440.000000 x=-340282346638528859811704183484516925440.000000 この場合は、C ライブラリはメッセージを出力しておらず、 errno は設定されていない。 次の実行例では、 matherr() が呼び出され、 数学関数の返り値が変更され、0 以外の返り値が返さ れている。 $ ./a.out 0.0 1 12345.0 matherr SING exception in log() function args: 0.000000, 0.000000 retval: -340282346638528859811704183484516925440.000000 x=12345.000000 プログラムのソース #define _SVID_SOURCE #include <errno.h> #include <math.h> #include <stdio.h> #include <stdlib.h> static int matherr_ret = 0; /* Value that matherr() should return */ static int change_retval = 0; /* Should matherr() change function's return value? */ static double new_retval; /* New function return value */ int matherr(struct exception *exc) { fprintf(stderr, "matherr %s exception in %s() function\n", (exc->type == DOMAIN) ? "DOMAIN" : (exc->type == OVERFLOW) ? "OVERFLOW" : (exc->type == UNDERFLOW) ? "UNDERFLOW" : (exc->type == SING) ? "SING" : (exc->type == TLOSS) ? "TLOSS" : (exc->type == PLOSS) ? "PLOSS" : "???", exc->name); fprintf(stderr, " args: %f, %f\n", exc->arg1, exc->arg2); fprintf(stderr, " retval: %f\n", exc->retval); if (change_retval) exc->retval = new_retval; return matherr_ret; } int main(int argc, char *argv[]) { double x; if (argc < 2) { fprintf(stderr, "Usage: %s <argval>" " [<matherr-ret> [<new-func-retval>]]\n", argv[0]); exit(EXIT_FAILURE); } if (argc > 2) { _LIB_VERSION = _SVID_; matherr_ret = atoi(argv[2]); } if (argc > 3) { change_retval = 1; new_retval = atof(argv[3]); } x = log(atof(argv[1])); if (errno != 0) perror("errno"); printf("x=%f\n", x); exit(EXIT_SUCCESS); }
関連項目
fenv(3), math_error(7), standards(7)
この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.54 の一部 である。プロジェクト の説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。