FENV(3) | Linux Programmer's Manual | FENV(3) |
名前¶
feclearexcept, fegetexceptflag, feraiseexcept, fesetexceptflag, fetestexcept, fegetenv, fegetround, feholdexcept, fesetround, fesetenv, feupdateenv, feenableexcept, fedisableexcept, fegetexcept - 浮動小数点の丸めと例外の取り扱い
書式¶
#include <fenv.h> int feclearexcept(int excepts);
int fegetexceptflag(fexcept_t *flagp, int excepts);
int feraiseexcept(int excepts);
int fesetexceptflag(const fexcept_t *flagp, int excepts);
int fetestexcept(int excepts); int fegetround(void);
int fesetround(int rounding_mode); int fegetenv(fenv_t *envp);
int feholdexcept(fenv_t *envp);
int fesetenv(const fenv_t *envp);
int feupdateenv(const fenv_t *envp);
-lm でリンクする。
説明¶
これらの 11 個の関数は C99 で定義されており、 浮動小数点の丸めと例外 (オーバーフロー、ゼロによる除算など) の取り扱いを規定する。
例外¶
divide-by-zero 例外は、有限の数値に対する演算が、 無限大の答えを生成するような場合に起こる。
overflow 例外は、結果が浮動小数点数値で表記されなければならないのに、 その絶対値が表現可能な浮動小数点数の (有限の) 最大値よりも (ずっと) 大きくなってしまうような場合に起こる。
underflow 例外は、結果が浮動小数点数値で表記されなければならないのに、 その絶対値が正の正規化浮動小数点数の最小値よりも 小さくなってしまう (そして 非正規化数で表現した場合に非常に精度を失ってしまう) ような場合に起こる。
inexact 例外は、丸め後の演算結果が、 無限精度の結果と異なるような場合に起こる。 overflow 例外か underflow 例外が起きたときには、常にこの例外も起こる。
invalid 例外は、演算結果がうまく定義できない結果を生じるような場合に起こる。 例えば 0/0、無限大 - 無限大、sqrt(-1) など。
例外処理¶
例外の表し方には 2 つの方法がある。 ひとつは、単一のビットで (例外があったかなかったかを) 表す方法で、 これらのビットは整数のあるビット位置に対応し、ビットの対応付けは 実装依存である。もう一つは、内部構造体を使って表す方法で、 この方法の方が例外に関するより多くの情報 (例えば例外が起こったコードのアドレスなど) が含まれる。
FE_DIVBYZERO, FE_INEXACT, FE_INVALID, FE_OVERFLOW, FE_UNDERFLOW の各マクロは、それぞれ対応する例外の処理を 実装がサポートしている場合に定義される。 このとき対応するビットをそれぞれ定義することになるので、 例外処理関数の呼び出しを、例えば FE_OVERFLOW|FE_UNDERFLOW という整数の引き数を用いて行うことができる。 他の例外もサポートされているかもしれない。 FE_ALL_EXCEPT マクロは、サポートされている例外に対応するビットが全てセットされている (サポートされている例外全ての論理和である)。
feclearexcept() 関数は、引き数 excepts のビット列で指定された例外をクリアする (処理は実装でサポートされている例外についてのみ行われる)。
fegetexceptflag() 関数は、引き数 excepts で指定された例外フラグの状態を *flagp が指す内部オブジェクトに保存する。
feraiseexcept() 関数は、 excepts のビット列で指定された例外のうち、 実装がサポートしているものを発生させる。
fesetexceptflag() 関数は、 excepts で指定された例外に対応するフラグの状態を *flagp の値に設定する。 *flagp の値は、この関数を呼ぶ前に fegetexceptflag() 関数を呼び出して取得しておかなければならない (このとき、 fegetexceptflag() の最後の引き数には、 fesetexceptflag() に渡す excepts のすべてのビットを含む値を指定すること)。
fetestexcept() 関数は、 excepts 引き数でセットされているビットのうち、 現在設定されている例外に対応するビットが 1 になったワードを返す。
丸めモード¶
丸めモードは、結果が仮数部だけで正確に表現できない際に、 浮動小数点操作の結果をどのように扱うかを決めるものである。 さまざまな丸めモードを提供することができる: 最も近い値に丸める (デフォルト)、 (正の無限大に向かって) 大きくなる方向に丸める、 (負の無限大に向かって) 小さくなる方向に丸める、 0 に向けて丸める、である。
FE_TONEAREST, FE_UPWARD, FE_DOWNWARD, FE_TOWARDZERO の各マクロは、それぞれ対応する丸めの方向を 実装がサポートしている場合に定義される。
fegetround() 関数は現在の丸めモードに対応するマクロを返す。
fesetround() 関数は丸めモードを引き数に与えられた値にし、 成功したらゼロを返す。
C99 と POSIX.1-2008 では FLT_ROUNDS という識別子が規定されており、 <float.h> で定義されている。この識別子は 浮動小数点数の加算についての実装定義された丸め動作を表し、 以下のいずれかの値を持つ。
- -1
- 丸めモードは決められていない。
- 0
- 0 に向けて丸める。
- 1
- 最も近い数に丸める。
- 2
- 正の無限大に向けて丸める。
- 3
- 負の無限大に向けて丸める。
他の値はマシン依存であり、標準的ではない丸めモードである。
FLT_ROUNDS の値には、 fesetround() で設定された現在の丸めモードが反映されるべきである (但し、「バグ」の節を参照)。
浮動小数点関連の環境¶
浮動小数点関連の環境の全体は、 制御モードや状態フラグも含め、 fenv_t 型の内部オブジェクト一つで取り扱うことができる。 デフォルトの環境は、 (const fenv_t * 型の) FE_DFL_ENV で示されるものである。 これはプログラムの開始時に構築される環境であり、 ISO C では、丸めモードを最も近い値への丸め (FE_TONEAREST) に設定し、すべての例外をクリアし、不停止 (non-stop) (例外が起きても継続する) モードとするように規定されている。
fegetenv() 関数は、現在の浮動小数点環境を、オブジェクト *envp に保存する。
feholdexcept() 関数も同じ動作を行い、 さらに可能であれば、全ての例外フラグをクリアし、 non-stop (例外時にも実行を継続) モードに設定する。
fesetenv() 関数は、浮動小数点環境を、オブジェクト *envp から取り出した値に戻す。 このオブジェクトは、有効であることが事前に分かっていなければならない。 例えば、 fegetenv() や feholdexcept() を呼び出した結果であるとか、 FE_DFL_ENV に等しいとかでなければならない。 この関数の呼び出しは例外を発生しない。
feupdateenv() 関数は、オブジェクト *envp が表現する浮動小数点環境をインストールする。 ただし、現在発生している例外はクリアされない。 この関数を呼んだ後に立っている例外は、 関数を呼ぶ前の値と *envp の値とのビットごとの OR を取ったものになる。 上記と同様に、オブジェクト *envp は、事前に有効であることが分かっていなければならない。
返り値¶
これらの関数は、成功の場合 0 を返し、エラーが発生すると 0 以外を返す。
バージョン¶
これらの関数は glibc バージョン 2.1 で初めて登場した。
準拠¶
IEC 60559 (IEC 559:1989), ANSI/IEEE 854, C99, POSIX.1-2001.
注意¶
glibc での注意¶
可能な場合には、GNU C Library はマクロ FE_NOMASK_ENV を定義する。このマクロはすべての例外でトラップが生じるような環境を表す。 #ifdef を使ってこのマクロをテストできる。これは _GNU_SOURCE が定義されている場合に限って定義される。 C99 標準は浮動小数点マスク (例えば特定のフラグでのトラップなど) の各ビットの設定方法については定義していない。 glibc 2.2 は feenableexcept() 関数と fedisableexcept() 関数をサポートしており、 各々の浮動小数点トラップを設定できるようになっている。 また fegetexcept() によって状態の問い合わせもできるようになっている。
#define _GNU_SOURCE
#include <fenv.h> int feenableexcept(int excepts);
int fedisableexcept(int excepts);
int fegetexcept(void);
feenebleexcept() 関数と fedisableexcept() 関数は excepts によって表現される各例外のトラップを有効 (無効) にする。 成功した場合は直前に有効になっていた例外のセットを返す。 失敗した場合は -1 を返す。 fegetexcept() 関数は現在有効になっている例外全てからなるセットを返す。
バグ¶
C99 の規定では、 FLT_ROUNDS の値には fesetround() で設定された現在の丸めモードが反映されるべきであるとされている。 現在のところ、 このようになっておらず、 FLT_ROUNDS は常に値 1 となる。
関連項目¶
2008-08-11 | Linux |