C言語/標準ライブラリ/tgmath.h
ISO/IEC 9899:1999(C99)で標準に追加されたヘッダー<tgmath.h>
では、引数の型に応じて対応する数学関数を呼び出す型総称マクロ[1]が定義されます[2]。
<tgmath.h>
をインクルードすると、<math.h>
と<complex.h>
が(暗黙に)インクルードされます。
C言語の数学関数には実数型と複素数型があります。それぞれ引数の型に応じて、float
、double
、long double
の3種類があるので 通りの組み合わせを生じます。
C言語はC++のようなオーバーロードをサポートしていないため、引数の型が異なる関数のバリエーションには { sin, sinf, sin, sinl, csinf, csin, csinl } のような名前が付けられています。
<tgmath.h>
には、呼び出すべき正しい数学関数の選択を簡単にするマクロが含まれています。マクロは渡された型に応じて正しい関数を呼び出します。
例えば、マクロsqrt()
では、sqrt(2.0f)
は sqrtf(2.0f)
を、sqrt(2.0)
は sqrt()
を[3]、sqrt(2.0L)
ならば sqrtl(2.0L)
を呼び出します。
- コード例
#include <stdio.h> #include <tgmath.h> int main(void) { printf("%32.30f\n", sqrt(2.0f)); printf("%32.30f\n", sqrt(2.0)); printf("%32.30Lf\n", sqrt(2.0L)); float complex f = 2 + I * 2; f = sqrt(f); printf("%32.30f+%32.30fi\n", creal(f), cimag(f)); double complex d = 2 + I * 2; d = sqrt(d); printf("%32.30f+%32.30fi\n", creal(d), cimag(d)); long double complex l = 2 + I * 2; l = sqrt(l); printf("%32.30Lf+%32.30Lfi\n", creal(l), cimag(l)); }
- 結果
1.414213538169860839843750000000 1.414213562373095145474621858739 1.414213562373095048763788073032 1.553773999214172363281250000000+0.643594264984130859375000000000i 1.553773974030037363647238635167+0.643594252905582586699040348321i 1.553773974030037307377145883169+0.643594252905582624700326493938i
型総称マクロ | 実数 | 複素数 | |||||
---|---|---|---|---|---|---|---|
float
|
double
|
long double
|
float
|
double
|
long double
| ||
三角関数 | sin
|
sinf |
sin |
sinl |
csinf |
csin |
csinl
|
coscos
|
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
| |
atan2
|
atan2f |
atan2 |
atan2l |
- | - | - | |
双曲線関数 | 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
| |
指数関数及び対数関数 | exp
|
expf |
exp |
expl |
cexpf |
cexp |
cexpl
|
exp2
|
exp2f |
exp2 |
exp2l |
- | - | - | |
expm1
|
expm1f |
expm1 |
expm1l |
- | - | - | |
frexp
|
frexpf |
frexp |
frexpl |
- | - | - | |
ilogb
|
ilogbf |
ilogb |
ilogbl |
- | - | - | |
ldexp
|
ldexpf |
ldexp |
ldexpl |
- | - | - | |
log
|
logf |
log |
logl |
clogf |
clog |
clogl
| |
log10
|
log10f |
log10 |
log10l |
- | - | - | |
log1p
|
log1pf |
log1p |
log1pl |
- | - | - | |
log2
|
log2f |
log2 |
log2l |
- | - | - | |
logb
|
logbf |
logb |
logbl |
- | - | - | |
scalbln
|
scalblnf |
scalbln |
scalblnl |
- | - | - | |
scalbn
|
scalbnf |
scalbn |
scalbnl |
- | - | - | |
べき乗関数及び絶対値関数 | cbrt
|
cbrtf |
cbrt |
cbrtl |
- | - | - |
fabs
|
fabsf |
fabs |
fabsl |
cabsf |
cabs |
cabsl
| |
hypot
|
hypotf |
hypot |
hypotl |
- | - | - | |
pow
|
powf |
pow |
powl |
cpowf |
cpow |
cpowl
| |
sqrt
|
sqrtf |
sqrt |
sqrtl |
csqrtf |
csqrt |
csqrtl
| |
誤差関数及びガンマ関数 | erf
|
erff |
erf |
erfl |
- | - | - |
erfc
|
erfcf |
erfc |
erfcl |
- | - | - | |
lgamma
|
lgammaf |
lgamma |
lgammal |
- | - | - | |
tgamma
|
tgammaf |
tgamma |
tgammal |
- | - | - | |
最近接整数関数 | ceil
|
ceilf |
ceil |
ceill |
- | - | - |
floor
|
floorf |
floor |
floorl |
- | - | - | |
nearbyint
|
nearbyintf |
nearbyint |
nearbyintl |
- | - | - | |
rint
|
rintf |
rint |
rintl |
- | - | - | |
lrint
|
lrintf |
lrint |
lrintl |
- | - | - | |
llrint
|
llrintf |
llrint |
llrintl |
- | - | - | |
round
|
roundf |
round |
roundl |
- | - | - | |
lround
|
lroundf |
lround |
lroundl |
- | - | - | |
llround
|
llroundf |
llround |
llroundl |
- | - | - | |
trunc
|
truncf |
trunc |
truncl |
- | - | - | |
剰余関数 | fmod
|
fmodf |
fmod |
fmodl |
- | - | - |
remainder
|
remainderf |
remainder |
remainderl |
- | - | - | |
remquo
|
remquof |
remquo |
remquol |
- | - | - | |
実数操作関数 | copysign
|
copysignf |
copysign |
copysignl |
- | - | - |
nextafter
|
nextafterf |
nextafter |
nextafterl |
- | - | - | |
nexttoward
|
nexttowardf |
nexttoward |
nexttowardl |
- | - | - | |
最大, 最小及び正の差関数 | fdim
|
fdimf |
fdim |
fdiml |
- | - | - |
fmax
|
fmaxf |
fmax |
fmaxl |
- | - | - | |
fmin
|
fminf |
fmin |
fminl |
- | - | - | |
浮動小数点乗算加算 | fma
|
fmaf |
fma |
fmal |
- | - | - |
複素数操作 | carg
|
- | - | - | cargf |
carg |
cargl
|
conj
|
- | - | - | conjf |
conj |
conjl
| |
creal
|
- | - | - | crealf |
creal |
creall
| |
cimag
|
- | - | - | cimagf |
cimag |
cimagl
| |
cproj
|
- | - | - | cprojf |
cproj |
cprojl
|
型ジェネリック式
[編集]ISO/IEC 9899:2011(C11)で、キーワード _Generic が導入されました[4]。
_Generic は、型ジェネリック式を実現するためのもので、C++のオーバーロードの様に引数の型によって処理を選択します。
構文
_Generic( 式, 型: 値, 型: 値, 型: 値, ... 型: 値)
型ジェネリック式は、与えられた「式」と一致する型に対応した値を取ります。 特別な「型」として default があり、他の全ての型に一致しなかった場合に default に対応した値を取ります。
_Generic の使用例(C11:WG14/N1570 Committee Draft ISO/IEC.p.68, §6.5.1.1 Generic selection.から抜粋[4])
#define cbrt(X) _Generic((X), \
long double: cbrtl, \
default: cbrt, \
float: cbrtf \
)(X)
crrt()は、立方根(cube root)を返す関数ですが、引数の種類によって、
double cbrt(double x);
float cbrtf(float x);
long double cbrtl(long double x);
の3つのバリエーションがあります。
この例で示された型総称マクロcbrt()では、_Generic() で渡された仮引数 X によって呼び出す関数を切り替えています。
実際のプログラムで、このマクロを使って試してみましょう。
- コード例
#include <stdio.h> #include <math.h> #include <complex.h> #define cbrt(X) _Generic((X), \ long double: cbrtl, \ default: cbrt, \ float: cbrtf \ )(X) int main() { printf("%32.30f\n", cbrt(2.0f)); printf("%32.30f\n", cbrt(2.0)); printf("%32.30Lf\n", cbrt(2.0L)); }
- 結果
1.259921073913574218750000000000 1.259921049894873190666544360283 1.259921049894873164754112437880
脚註
[編集]- ^ Type-generic macros
- ^ C99: WG14/N1256 Committee Draft — Septermber 7, 2007. ISO/IEC. p. 335, §7.22 Type-generic math .
- ^ マクロプロセッサは、マクロ展開の結果に再びマクロを適用することはしないのでマクロ名と展開先の関数名が一致している事は問題になりません。
- ^ 4.0 4.1 C11: WG14/N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x. ISO/IEC. p. 68, §6.5.1.1 Generic selection .
参考文献
[編集]- 国際標準化機構/国際電気標準会議 ISO/IEC 9899:2018(en) Information technology — Programming languages — C(2018-07-05)
- 日本工業標準調査会(当時、現:日本産業標準調査会)『JISX3010 プログラム言語C』2003年12月20日改正