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)
に設定し、すべての例外をクリアし、不停止
(nonstop)
(例外が起きても継続する)
モードとするように規定されている。
fegetenv()
関数は、現在の浮動小数点環境を、オブジェクト
*envp に保存する。
feholdexcept()
関数も同じ動作を行い、
さらに可能であれば、全ての例外フラグをクリアし、
nonstop
(例外時にも実行を継続)
モードに設定する。
fesetenv()
関数は、浮動小数点環境を、オブジェクト
*envp
から取り出した値に戻す。
このオブジェクトは、有効であることが事前に分かっていなければならない。
例えば、
fegetenv() や
feholdexcept()
を呼び出した結果であるとか、
FE_DFL_ENV
に等しいとかでなければならない。
この関数の呼び出しは例外を発生しない。
feupdateenv()
関数は、オブジェクト
*envp
が表現する浮動小数点環境をインストールする。
ただし、現在発生している例外はクリアされない。
この関数を呼んだ後に立っている例外は、
関数を呼ぶ前の値と
*envp
の値とのビットごとの
OR
を取ったものになる。
上記と同様に、オブジェクト
*envp
は、事前に有効であることが分かっていなければならない。
これらの関数は、成功の場合
0
を返し、エラーが発生すると
0 以外を返す。
これらの関数は glibc
バージョン 2.1
で初めて登場した。
この節で使用されている用語の説明については、
attributes(7) を参照。
インターフェース |
属性 |
値 |
feclearexcept(), fegetexceptflag(),
feraiseexcept(), fesetexceptflag(), fetestexcept(),
fegetround(), fesetround(), fegetenv(),
feholdexcept(), fesetenv(), feupdateenv(),
feenableexcept(), fedisableexcept(),
fegetexcept() |
Thread safety |
MT-Safe |
IEC 60559 (IEC 559:1989), ANSI/IEEE 854, C99, POSIX.1-2001.
可能な場合には、GNU C Library
はマクロ
FE_NOMASK_ENV
を定義する。このマクロはすべての例外でトラップが生じるような環境を表す。
#ifdef
を使ってこのマクロをテストできる。これは
_GNU_SOURCE
が定義されている場合に限って定義される。
C99
標準は浮動小数点マスク
(例えば特定のフラグでのトラップなど)
の各ビットの設定方法については定義していない。
バージョン 2.2 以降の glibc
は、
feenableexcept() 関数と
fedisableexcept()
関数をサポートしており、
各々の浮動小数点トラップを設定できるようになっている。
また
fegetexcept()
によって状態の問い合わせもできるようになっている。
#define _GNU_SOURCE /* feature_test_macros(7) 参照 */
#include <fenv.h>
int feenableexcept(int excepts);
int fedisableexcept(int excepts);
int fegetexcept(void);
feenableexcept() 関数と
fedisableexcept()
関数は
excepts
によって表現される各例外のトラップを有効
(無効) にする。
成功した場合は直前に有効になっていた例外のセットを返す。
失敗した場合は -1
を返す。
fegetexcept()
関数は現在有効になっている例外全てからなるセットを返す。
C99 の規定では、
FLT_ROUNDS
の値には
fesetround()
で設定された現在の丸めモードが反映されるべきであるとされている。
現在のところ、
このようになっておらず、
FLT_ROUNDS は常に値 1
となる。
math_error(7)
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。