名 前
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) が 発 生 し た (関 数 の 引 き 数 が 関 数 が |
定 義 さ れ た 範 囲 外 で あ っ た )。 返 り 値 は 関 数 に よ っ て 異 な り 、 errno に は EDOM が 設 定 さ れ る 。
SING 極 エ ラ ー |
(pole error) が 発 生 し た (関 数 の 結 果 が 無 限 大 で あ |
る )。 返 り 値 は ほ と ん ど の 場 合 HUGE (最 大 の 単 精 度 浮 動 小 数 点 数 ) と な り 、 た い て い は 符 号 付 き で あ る 。 ほ と ん ど の 場 合 、 errno に は EDOM が 設 定 さ れ る 。
OVERFLOW オ ー バ ー フ ロ ー が 発 生 し た 。 ほ と ん ど の 場 合 、 値 |
れ 、 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> で 定 義
さ れ る 定 数
属 性
マ ル チ ス レ ッ デ ィ ン グ (pthreads(7) 参 照 )
matherr() 関 数 は ス レ ッ ド セ ー フ で あ る 。
例
以 下 の サ ン プ ル プ ロ グ ラ ム は 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.79 の 一 部 で あ る 。 プ ロ ジ ェ ク ト の 説 明 と バ グ 報 告 に 関 す る 情 報 は http://www.kernel.org/doc/man−pages/ に 書 か れ て い る 。