Skip to content

Latest commit

 

History

History
466 lines (341 loc) · 36.5 KB

cmath.md

File metadata and controls

466 lines (341 loc) · 36.5 KB

cmath

  • cmath[meta header]

<cmath>ヘッダでは、一般的な数学関数および各種マクロを提供する。

<cmath>は基本的には、標準 C ライブラリの <math.h> に準拠しているが、いくつかの変更点がある。

  • 各関数は std 名前空間に定義されている。
  • fabs と等価の関数 abs を追加している。
  • pow の第 2 引数が int のオーバーロードを追加している。
  • 各関数(上記 2 関数を含む)に対して、引数および戻り値の double に対応する箇所が float および long double になっているオーバーロードバージョンを追加している。
  • 各関数は std 名前空間に定義されている。

  • fabs と等価の関数 abs を追加している。

  • 引数に double を含む各関数(上記 abs を含む)に対して、引数および戻り値の double に対応する箇所が floatlong double のオーバーロードバージョンを追加している。
    なお、C99 にも同様の関数(接尾辞が f および l のもの)が存在するが、それらについては規格書では言及されていない。
    ただし、nan については、引数の型では区別がつかないため、C99 の nanf および nanl をそのまま使用する。

  • 数値分類、および、数値比較の各マクロの替わりに、引数が各浮動小数点型で、戻り値が bool の関数を追加している。

  • 上記に加えて、以下のようなオーバーロード解決ができるように、更にオーバーロードを追加している。

    1. double 型の仮引数に対応する実引数のいずれかが long double である場合、double 型の仮引数に対応する全ての実引数を long double にキャストしてからオーバーロード解決を行う。
    2. 上記以外で、double 型の仮引数に対応する実引数のいずれかが double 型または整数型である場合、double 型の仮引数に対応する全ての実引数を double にキャストしてからオーバーロード解決を行う。
    3. 上記以外の場合、double 型の仮引数に対応する全ての実引数を float にキャストしてからオーバーロード解決を行う。

    これらの規則は、C99 で導入された <tgmath.h> の type-generic マクロとほぼ等価であるが、以下の点が異なる。

    • C99 では modf は type-generic マクロの対象ではないが、C++11 ではオーバーロード解決の対象である。
    • C99 では列挙型も整数型とみなされるが、C++11 では列挙型は(スコープ付き・スコープ無し共に)整数型とはみなされない。
    • C++ のクラス型は変換演算子を持つことができるため、実引数の型が変換演算子を持つクラス型の場合も上記に従ってオーバーロード解決が行われる。

    しかし、上記のオーバーロード解決の規則に厳密に従うと、列挙型や変換演算子を持つクラス型の引数が float と等価の扱いになってしまう。
    このため、上記に記載のある無条件の「キャスト」は、C++14 ではその対象が「算術型」のみに限られることになり、列挙型や変換演算子を持つクラス型は上記の「キャスト」の対象とはならなくなった。
    (もちろん、オーバーロード解決の後の暗黙の変換は依然として有効であるため、スコープ無し列挙型や explicit でない変換演算子を持つクラス型は、明示的なキャスト無しで実引数になり得る。)
    なお、C++11 の記載にある無条件のキャストは規格のバグとされたため、C++11 であってもスコープ付き列挙型や explicit な変換演算子のあるクラス型に、上記規則にある無条件のキャストが適用されると想定すべきではない。
    LWG 2086. Overly generic type support for math functions 参照)

    各関数の個別ページでは、上記のオーバーロード関数をコードで示す際には、引数や戻り値の型を斜体で示す。

    Integral      // 任意の整数型
    Arithmetic    // 任意の算術型
    Promoted      // 決定された戻り値型
    • Integral[italic]
    • Arithmetic[italic]
    • Promoted[italic]

    複数の引数がある場合には、数字のサフィックスで区別する。 例を以下に示す。

    double atan(Integral x);
    
    Promoted atan2(Arithmetic1 y, Arithmetic2 x);
    • Integral[italic]
    • Arithmetic1[italic]
    • Arithmetic2[italic]
    • Promoted[italic]

constexpr対応

C++23では、多くの数学関数がconstexprに対応し、定数式内で使用できるようになった。C++23時点では、コンパイラベンダの負担が少ない機能をconstexpr対応した。

C++23でconstexpr対応する関数の条件は以下:

  1. 有理数の集合、または実数のどこにも密でない部分集合に作用すると見なされ、関数が閉じていること
  2. 関数が丸めモードに強く依存しないこと

exp()log()sqrt()cos()sin()は1. の条件を満たさないため、C++23ではconstexprに対応しない。

nearbyint()は2. の条件を満たさないため、C++23ではconstexprに対応しない。

ただし、コンパイラが先行してconstexpr非対応の関数も対応している可能性がある。

なお、C++20ではlerp()のみconstexprに対応している。これはC標準ライブラリからの移植ではなく、C++で標準化された関数だからである (errnoや浮動小数点例外のようなグローバル状態を使用しない)。

拡張浮動小数点数型への対応

C++23では<stdfloat>に拡張浮動小数点数型が追加された。その対応として、以下のようなfloatdoublelong doubleに対するオーバーロードは、

float abs(float x);
double abs(double x);
long double abs(long double x);

以下のようにfloating-point-typeへのオーバーロードに統合され、拡張浮動小数点数型も扱えるようになった。

floating-point-type abs(floating-point-type x);

<cmath> で提供される各関数は、特に明記されていない限り、引数の型が表現できる全ての値についての挙動が定義されている。 なお、ここで言う「挙動が定義されている」とは、未定義動作を引き起こさないというだけで、エラーが発生したり、実装依存の挙動となる場合がある事に注意。

<cmath> で提供される各関数においてエラーが発生した場合、errno、あるいは、浮動小数点例外のいずれか、もしくは両方によってエラーが通知される。
C++11 以降の場合、どちらの方法によって通知されるかは math_errhandling の値によって判別可能である。(利用者が選択する事はできない)
C++03 までの場合、errno でしか通知されない。

errno によるエラーの通知

errno によってエラーが通知される場合、エラー内容は errno に設定された値によって判別可能である。
なお、エラーが発生しなかった場合でも errno がクリアされる事は無いので、エラー発生の有無を errno で判断するためにはあらかじめ errno にゼロを設定しておく必要がある。

浮動小数点例外によるエラーの通知(C++11 以降)

名称に「例外」と付いているが、C++ の例外とは全く関係ないため注意。
浮動小数点例外によってエラーが通知される場合、エラー内容は浮動小数点状態フラグに設定されるため、fetestexcept によって判別可能である。
なお、エラーが発生しなかった場合でも浮動小数点状態フラグがクリアされる事は無いので、エラー発生の有無を浮動小数点状態フラグで判断するためにはあらかじめ feclearexcept で浮動小数点状態フラグをクリアしておく必要がある。

<cmath> で提供される各関数で発生するエラーは、以下の 5 種類ある。

定義域エラー(domain error)

引数の値が、関数の数学的な定義域の範囲外であることを示すエラー。(例:sqrt(-1.0) や、asin(2.0) 等)

定義域エラーが発生しなければならない条件は関数毎に規格で規定されているが、数学的な定義と整合的である場合には追加の条件で定義域エラーが発生する事が処理系に許されている。

定義域エラーが発生した場合、通知は以下のように行われる。

  • errno によってエラーが通知される場合、EDOM(定義域エラー、Error DOMain)が設定される。
  • 浮動小数点例外によってエラーが通知される場合、FE_INVALID(無効演算浮動小数点例外)が設定される。

定義域エラーが発生した場合、関数の戻り値は処理系定義であるが、戻り値の型が quiet NaN(quiet Not a Number:静かな非数)を表現可能(std::numeric_limits<T>::has_quiet_NaN が真)の場合、一般的には quiet NaN が返る。

極エラー(pole error)

引数の値が有限値である場合に、関数の当該値に対する数学的な極限値が無限大であることを示すエラー。(例:log(0.0) や、atanh(1.0) 等)
引数の値が無限大の場合には、極エラーではないので注意。

極エラーが発生しなければならない条件は関数毎に規格で規定されているが、数学的な定義と整合的である場合には追加の条件で極エラーが発生する事が処理系に許されている。

極エラーが発生した場合、通知は以下のように行われる。

  • errno によってエラーが通知される場合、ERANGE(値域エラー、Error RANGE)が設定される。
  • 浮動小数点例外によってエラーが通知される場合、FE_DIVBYZERO(ゼロ除算浮動小数点例外)が設定される(注:「ゼロ除算浮動小数点例外」は誤記では無い)。

極エラーが発生した場合、関数の戻り値は処理系定義であるが、戻り値の型が浮動小数点数の場合、一般的には HUGE_VALdouble)、HUGE_VALFfloat 、C++11 以降のみ)、HUGE_VALLlong double、C++11 以降のみ)に正しい符号を付加した値が返る。 また、戻り値の型が無限大を表現可能(std::numeric_limits<T>::has_infinity が真)の場合、一般的には無限大(std::numeric_limits<T>::infinity())が返る。 なお、マクロ INFINITY も、定義されている場合には無限大を表すものではあるが、float 型であることに注意。

オーバーフローエラー(overflow error)

戻り値が有限だが大きすぎるため、余分な丸め誤差無しでは戻り値の型で表す事が出来ないことを示すエラー。

オーバーフローエラーが発生した場合、通知は以下のように行われる。

  • errno によってエラーが通知される場合、ERANGE(値域エラー、Error RANGE)が設定される。
  • 浮動小数点例外によってエラーが通知される場合、FE_OVERFLOW(オーバーフロー浮動小数点例外)が設定される。

オーバーフローエラーが発生した場合、戻り値の型が浮動小数点型でデフォルトの丸めモードが有効であれば、HUGE_VALdouble)、HUGE_VALFfloat 、C++11 以降のみ)、HUGE_VALLlong double、C++11 以降のみ)に正しい符号を付加した値が返る。

アンダーフローエラー(underflow error)

戻り値の絶対値が小さすぎるため、余分な丸め誤差無しでは戻り値の型で表す事が出来ないことを示すエラー。

アンダーフローエラーが発生した場合でも処理系によってはエラーの通知が行われないが(規格でエラーの通知が任意となっているため)、通知される場合には以下のように行われる。

  • errno によってエラーが通知される場合、ERANGE(値域エラー、Error RANGE)が設定される。
  • 浮動小数点例外によってエラーが通知される場合、FE_UNDERFLOW(アンダーフロー浮動小数点例外)が設定される。

アンダーフローエラーが発生した場合、関数の戻り値は処理系定義であるが、戻り値の絶対値はその型における最小の正の正規化数(std::numeric_limits<T>::min())以下である。(非正規化数、あるいは、ゼロを含む)

不正確エラー(inexact error)

戻り値が戻り値の型では正確に表す事が出来ないことを示すエラー。(例:exp(1.0) や、sqrt(2.0) 等)
浮動小数点演算ではほとんどの場合に発生する。

不正確エラーが発生した場合でも処理系によってはエラーの通知が行われないが(規格でエラーの通知が任意となっているため)、通知される場合には以下のように行われる。

  • errno によるエラーの通知は行われない。
  • 浮動小数点例外によってエラーが通知される場合、FE_INEXACT(不正確浮動小数点例外)が設定される。

不正確エラーが発生した場合、関数の戻り値は真の値を丸めた値となるが、その際の丸め方式は処理系定義である。(関数に特別に規定がある場合を除く)
特に、fesetround で設定した丸め方式に従うとは限らないため、注意が必要である。

定数式になる条件

constexpr対応する数学関数において、以下のいずれかの条件に合致する場合、定数式とならない (引数によってコンパイルエラーになる)

名前 説明 対応バージョン
sin 正弦関数(サイン)
cos 余弦関数(コサイン)
tan 正接関数(タンジェント)
asin 逆正弦関数(アークサイン)
acos 逆余弦関数(アークコサイン)
atan 逆正接関数(アークタンジェント)
atan2 対辺と隣辺からの逆正接関数(アークタンジェント)
名前 説明 対応バージョン
sinh 双曲線正弦関数(ハイパボリックサイン)
cosh 双曲線余弦関数(ハイパボリックコサイン)
tanh 双曲線正接関数(ハイパボリックタンジェント)
asinh 逆双曲線正弦関数(エリアハイパボリックサイン) C++11
acosh 逆双曲線余弦関数(エリアハイパボリックコサイン) C++11
atanh 逆双曲線正接関数(エリアハイパボリックタンジェント) C++11
名前 説明 対応バージョン
exp e (ネイピア数) を底とする指数関数
exp2 2 を底とする指数関数 C++11
expm1 e (ネイピア数) を底とする指数関数から 1 を引いた値 C++11
log e (ネイピア数) を底とする自然対数
log10 10 を底とする常用対数
log1p 引数に 1 を足した値の、e (ネイピア数) を底とする自然対数 C++11
log2 2 を底とする二進対数 C++11
名前 説明 対応バージョン
ldexp 2 の累乗との乗算
frexp 仮数部と 2 の累乗への分解
ilogb 指数部を符号付き整数値として抽出 C++11
logb 指数部を浮動小数点数値として抽出 C++11
modf 整数部と小数部への分解
scalbn 内部表現の基数 (FLT_RADIX) の累乗との乗算 C++11
scalbln 内部表現の基数 (FLT_RADIX) の累乗との乗算。乗数としてlongをとる C++11
名前 説明 対応バージョン
pow 累乗
sqrt 平方根
cbrt 立方根 C++11
hypot 平方和の平方根 C++11
abs 絶対値
fabs 絶対値
名前 説明 対応バージョン
erf 誤差関数 C++11
erfc 相補誤差関数 C++11
tgamma ガンマ関数 C++11
lgamma ガンマ関数の自然対数 C++11

以下の関数は引数に NaN が渡された場合、 NaN を返さなければならないが定義域エラーを報告してはならない。 引数が NaN ではないが次の条件を一つでも満たす場合、定義域エラーを報告しなければならない:

  • 規格が関数の定義域を明示していて (各解説ページを参照)、その定義域内にない
  • 数学関数の値の虚部が 0 でない
  • 数学関数が数学的に定義されていない

数学関数が数学的に定義されるのは以下のいずれかの場合である:

  • ある集合において明示的に定義されている
  • 極限が存在する (右極限と左極限が存在し、一致する)

特記のない限り、以下の関数は全ての有限値と正負の無限大において定義される。

名前 説明 対応バージョン
assoc_laguerre ラゲール陪多項式 C++17
assoc_legendre ルジャンドル陪関数 C++17
beta ベータ関数 C++17
comp_ellint_1 第1種完全楕円積分 C++17
comp_ellint_2 第2種完全楕円積分 C++17
comp_ellint_3 第3種完全楕円積分 C++17
cyl_bessel_i 第1種変形ベッセル関数 C++17
cyl_bessel_j 第1種ベッセル関数 C++17
cyl_bessel_k 第2種変形ベッセル関数 C++17
cyl_neumann 第2種ベッセル関数 C++17
ellint_1 第1種不完全楕円積分 C++17
ellint_2 第2種不完全楕円積分 C++17
ellint_3 第3種不完全楕円積分 C++17
expint 指数積分 C++17
hermite エルミート多項式 C++17
laguerre ラゲール多項式 C++17
legendre ルジャンドル多項式 C++17
riemann_zeta リーマンのゼータ関数 C++17
sph_bessel 第1種球ベッセル関数 C++17
sph_legendre 球面調和関数の θ 成分 C++17
sph_neumann 第2種球ベッセル関数 C++17
名前 説明 対応バージョン
ceil 天井関数(引数より小さくない最近傍の整数)
floor 床関数(引数より大きくない最近傍の整数)
trunc ゼロ方向への丸め C++11
round 四捨五入による丸め C++11
lround long 型への四捨五入による丸め C++11
llround long long 型への四捨五入による丸め C++11
nearbyint 現在の丸めモードによる丸め C++11
rint 現在の丸めモードによる丸め C++11
lrint long 型への現在の丸めモードによる丸め C++11
llrint long long 型への現在の丸めモードによる丸め C++11
名前 説明 対応バージョン
fmod 浮動小数点剰余
remainder 符号付きの浮動小数点剰余 C++11
remquo 商と浮動小数点剰余 C++11
名前 説明 対応バージョン
copysign 符号のコピー C++11
nan 文字列から quiet NaN への変換 C++11
nanf 文字列から quiet NaN への変換 C++11
nanl 文字列から quiet NaN への変換 C++11
nextafter 指定方向への次の表現可能な値 C++11
nexttoward 指定方向への次の表現可能な値 C++11
名前 説明 対応バージョン
fmax 最大値 C++11
fmin 最小値 C++11
fdim 正の差 C++11
名前 説明 対応バージョン
fma 乗算と加算の合成 C++11
名前 説明 対応バージョン
lerp 線形補間 C++20
名前 説明 対応バージョン
fpclassify 数値を NaN、無限大、正規化数、非正規化数、0 または他の処理系定義のカテゴリに分類 C++11
isfinite 数値が有限であるか判定 C++11
isinf 数値が無限大であるか判定 C++11
isnan 数値が NaN であるか判定 C++11
isnormal 数値が正規化数であるか判定 C++11
signbit 数値の符号が負であるか判定 C++11
名前 説明 対応バージョン
isgreater 第 1 引数が第 2 引数より大きいか判定 C++11
isgreaterequal 第 1 引数が第 2 引数以上か判定 C++11
isless 第 1 引数が第 2 引数より小さいか判定 C++11
islessequal 第 1 引数が第 2 引数以下か判定 C++11
islessgreater 第 1 引数が第 2 引数より小さいか、あるいは大きいか判定 C++11
isunordered 第 1 引数と第 2 引数が順序付けられていないか判定 C++11
名前 説明 対応バージョン
float_t float 以上の浮動小数点数型 C++11
double_t double 以上の浮動小数点数型 C++11
名前 説明 対応バージョン
HUGE_VAL double 型の正の巨大値
HUGE_VALF float 型の正の巨大値 C++11
HUGE_VALL long double 型の正の巨大値 C++11
INFINITY float 型の正の無限大 C++11
NAN float 型の quiet NaN C++11
名前 説明 対応バージョン
FP_INFINITE 数値分類で無限大を表す整数定数式 C++11
FP_NAN 数値分類で NaN を表す整数定数式 C++11
FP_NORMAL 数値分類で正規化数を表す整数定数式 C++11
FP_SUBNORMAL 数値分類で非正規化数を表す整数定数式 C++11
FP_ZERO 数値分類で浮動小数点数の 0 を表す整数定数式 C++11
名前 説明 対応バージョン
FP_FAST_FMA double 型の fma 関数がより高速な実装であるか C++11
FP_FAST_FMAF float 型の fma 関数がより高速な実装であるか C++11
FP_FAST_FMAL long double 型の fma 関数がより高速な実装であるか C++11
FP_ILOGB0 ilogb(0) の戻り値を表す整数定数式 C++11
FP_ILOGBNAN ilogb(NaN) の戻り値を表す整数定数式 C++11
MATH_ERRNO 数学ライブラリ内でerrnoにエラーが設定されたかを表す整数定数 C++11
MATH_ERREXCEPT 数学ライブラリ内で浮動小数点例外が発生したかを表す整数定数 C++11
math_errhandling <cmath> 内の関数がエラーをどのように取り扱うかを表すマクロ C++11

関連項目

参照