C言語/標準ライブラリ/tgmath.h

出典: フリー教科書『ウィキブックス(Wikibooks)』
このページ「C言語/標準ライブラリ/tgmath.h」は、まだ書きかけです。加筆・訂正など、協力いただける皆様の編集を心からお待ちしております。また、ご意見などがありましたら、お気軽にトークページへどうぞ。

ISO/IEC 9899:1999(C99)で標準に追加されたヘッダー<tgmath.h>では、引数の型に応じて対応する数学関数を呼び出す型総称マクロ[1]が定義されます[2]<tgmath.h>をインクルードすると、<math.h><complex.h>が(暗黙に)インクルードされます。

C言語の数学関数には実数型と複素数型があります。それぞれ引数の型に応じて、floatdoublelong 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
<tgmath.h> で定義されている型総称マクロと展開先の数学関数
型総称マクロ 実数 複素数
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

脚註[編集]

  1. ^ Type-generic macros
  2. ^ C99: WG14/N1256 Committee Draft — Septermber 7, 2007. ISO/IEC. p. 335, §7.22 Type-generic math. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf. 
  3. ^ マクロプロセッサは、マクロ展開の結果に再びマクロを適用することはしないのでマクロ名と展開先の関数名が一致している事は問題になりません。
  4. ^ 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. http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf. 

参考文献[編集]