MATHERR(3) | Linux Programmer's Manual | MATHERR(3) |
名前
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() が返った後に、システムは数学関数に戻り、それから呼び出し元に返る。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 に設定されるデフォルトの返り値を示す。
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() は数学関数の返り値として代わりに引き数で指定した値を割り当てる。$ ./a.out 0.0
errno: Numerical result out of range
x=-inf
$ ./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
$ ./a.out 0.0 1
matherr SING exception in log() function
args: 0.000000, 0.000000
retval: -340282346638528859811704183484516925440.000000
x=-340282346638528859811704183484516925440.000000
$ ./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.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2010-09-10 | Linux |