型総称数学
提供: cppreference.com
ヘッダ <tgmath.h> は、 <math.h> および <complex.h> をインクルードし、引数の型に応じて呼ぶ関数を決定する型総称マクロをいくつか定義します。
各マクロにおいて、対応する <math.h> の数学関数では double であるところの引数は、総称引数と呼ばれます (例えば pow では両方の引数が総称引数ですが、 scalbn では最初の引数のみが総称引数です)。
<tgmath.h> のマクロを使用する場合、総称引数に渡した実引数の型に応じて後述するように関数が選択されます。 実引数の型が選択された関数の仮引数の型と互換でない場合、動作は未定義です (実数のみの型総称マクロに複素数を渡した場合など)。 float complex fc; ceil(fc) や double complex dc; double d; fmax(dc, d) は未定義動作の例です。
ノート: 型総称マクロは C99 では処理系定義の方法で実装されていましたが、 C11 ではキーワード _Generic によって移植性のある方法で実装できます。
複素数および実数の型総称マクロ
実数版と複素数版の両方があるすべての関数に対して型総称マクロが存在し、以下のいずれかを呼びます。
float版の関数~fdouble版の関数~long double版の関数~lfloat complex版の関数c~fdouble complex版の関数c~long double complex版の関数c~l
fabs マクロは上記ルールの例外です (下の表を参照してください)。
呼ぶ関数は以下のように決定されます。
- 総称引数のいずれかが虚数であれば、その動作は各関数のリファレンスページで個別に規定されます (特に sin, cos, tan, cosh, sinh, tanh, asin, atan, asinh, atanh は実数版の関数を呼びますが、 sin, tan, sinh, tanh, asin, atan, asinh, atan の戻り値は虚数になり、 cos, cosh の戻り値は実数になります)
- 総称引数のいずれかが複素数であれば複素数版の関数が呼ばれ、そうでなければ実数版の関数が呼ばれます
- 総称引数のいずれかが
long doubleであればlong double版が呼ばれ、そうでなくて総称引数のいずれかがdoubleまたは整数であればdouble版が呼ばれ、そうでなければfloat版が呼ばれます。
型総称マクロは以下の通りです。
| 型総称マクロ | 実数版の関数 | 複素数版の関数 | ||||
|---|---|---|---|---|---|---|
float |
double |
long double |
floatcomplex |
doublecomplex |
long doublecomplex | |
| fabs | fabsf | fabs | fabsl | cabsf | cabs | cabsl |
| exp | expf | exp | expl | cexpf | cexp | cexpl |
| log | logf | log | logl | clogf | clog | clogl |
| pow | powf | pow | powl | cpowf | cpow | cpowl |
| sqrt | sqrtf | sqrt | sqrtl | csqrtf | csqrt | csqrtl |
| sin | sinf | sin | sinl | csinf | csin | csinl |
| cos | cosf | cos | cosl | ccosf | ccos | ccosl |
| tan | tanf | tan | tanl | ctanf | ctan | ctanl |
| asin | asinf | asin | asinl | casinf | casin | casinl |
| acos | acosf | acos | acosl | cacosf | cacos | cacosl |
| atan | atanf | atan | atanl | catanf | catan | catanl |
| sinh | sinhf | sinh | sinhl | csinhf | csinh | csinhl |
| cosh | coshf | cosh | coshl | ccoshf | ccosh | ccoshl |
| tanh | tanhf | tanh | tanhl | ctanhf | ctanh | ctanhl |
| asinh | asinhf | asinh | asinhl | casinhf | casinh | casinhl |
| acosh | acoshf | acosh | acoshl | cacoshf | cacosh | cacoshl |
| atanh | atanhf | atanh | atanhl | catanhf | catanh | catanhl |
実数のみの関数
複素数版がないすべての関数 (modf を除く) に対して型総称マクロが存在し、以下のいずれかを呼びます。
float版の関数~fdouble版の関数~long double版の関数~l
呼ぶ関数は以下のように決定されます。
- 総称引数のいずれかが
long doubleであればlong double版が呼ばれ、そうでなくて総称引数のいずれかがdoubleであればdouble版が呼ばれ、そうでなければfloat版が呼ばれます。
複素数のみの関数
実数版のないすべての複素数関数に対して型総称マクロが存在し、以下のいずれかを呼びます。
float complex版の関数~fdouble complex版の関数~long double complex版の関数~l
呼ぶ関数は以下のように決定されます。
- 総称引数のいずれかが実数、複素数または虚数の場合、適切な複素数関数が呼ばれます。
| 型総称マクロ | 複素数版の関数 | ||
|---|---|---|---|
floatcomplex |
doublecomplex |
long doublecomplex | |
| carg | cargf | carg | cargl |
| conj | conjf | conj | conjl |
| creal | crealf | creal | creall |
| cimag | cimagf | cimag | cimagl |
| cproj | cprojf | cproj | cprojl |
例
Run this code
#include <stdio.h>
#include <tgmath.h>
int main(void)
{
int i = 2;
printf("sqrt(2) = %f\n", sqrt(i)); // argument type is int, calls sqrt
float f = 0.5;
printf("sin(0.5f) = %f\n", sin(f)); // argument type is float, calls sinf
float complex dc = 1 + 0.5*I;
float complex z = sqrt(dc); // argument type is float complex, calls csqrtf
printf("sqrt(1 + 0.5i) = %f+%fi\n",
creal(z), // argument type is float complex, calls crealf
cimag(z)); // argument type is float complex, calls cimagf
}
出力:
sqrt(2) = 1.414214
sin(0.5f) = 0.479426
sqrt(1 + 0.5i) = 1.029086+0.242934i
参考文献
- C11 standard (ISO/IEC 9899:2011):
- 7.25 Type-generic math <tgmath.h> (p: 373-375)
- C99 standard (ISO/IEC 9899:1999):
- 7.22 Type-generic math <tgmath.h> (p: 335-337)