【C言語】tgmath.hを使って簡単に数学関数を実装【標準ライブラリ】
tgmath.hとは
`tgmath.h` は C 言語の標準ライブラリに含まれるヘッダーファイルで、型に依存せず数学関数を使用できるようにするものです。 これは、浮動小数点数 (`float`、`double`、`long double`) や複素数 (`_Complex` 型) に対して適切な関数を自動的に選択するマクロを提供します。
tgmath.hの主な特徴
`tgmath.h` の主な特徴は以下の通りです。
- 数学関数 (`math.h`) と複素数関数 (`complex.h`) を統合
- 型に応じた適切な関数を自動的に選択
- マクロとして定義されているためコンパイル時に展開
- C99 以降で標準ライブラリとして利用可能
tgmath.hの基本的な使い方
`tgmath.h` を使うことで、通常は `float`、`double`、`long double` ごとに異なる関数を明示的に呼び出す必要があった数学関数を統一的に使用できます。
#include <stdio.h>
#include <tgmath.h>
int main() {
double x = 4.0;
float y = 4.0f;
long double z = 4.0L;
printf("%f\n", sqrt(x)); // double 用の sqrt を呼ぶ
printf("%f\n", sqrt(y)); // float 用の sqrtf を呼ぶ
printf("%Lf\n", sqrt(z)); // long double 用の sqrtl を呼ぶ
return 0;
}
tgmath.hの使用例
1. 型を意識せずに使える数学関数
通常、数学関数は型ごとに異なる名前を持ちますが、`tgmath.h` を使うことで統一的に扱えます。
#include <stdio.h>
#include <tgmath.h>
int main() {
float a = 9.0f;
double b = 9.0;
long double c = 9.0L;
printf("%f\n", sqrt(a)); // sqrtf(a) が呼ばれる
printf("%f\n", sqrt(b)); // sqrt(b) が呼ばれる
printf("%Lf\n", sqrt(c)); // sqrtl(c) が呼ばれる
return 0;
}
2. 三角関数と指数関数
`tgmath.h` を使えば `sin()`, `cos()`, `exp()` なども型を意識せずに記述できます。
#include <stdio.h>
#include <tgmath.h>
int main() {
float x = 0.5f;
double y = 0.5;
long double z = 0.5L;
printf("%f\n", sin(x)); // sinf(x)
printf("%f\n", cos(y)); // cos(y)
printf("%Lf\n", exp(z)); // expl(z)
return 0;
}
3. 複素数の計算
`tgmath.h` を使うと、複素数の演算も型を意識せずに行えます。
#include <stdio.h>
#include <tgmath.h>
#include <complex.h>
int main() {
double complex z1 = 1.0 + 2.0*I;
float complex z2 = 1.0f + 2.0f*I;
long double complex z3 = 1.0L + 2.0L*I;
printf("%f + %fi\n", creal(sqrt(z1)), cimag(sqrt(z1)));
printf("%f + %fi\n", creal(sqrt(z2)), cimag(sqrt(z2)));
printf("%Lf + %Lfi\n", creal(sqrt(z3)), cimag(sqrt(z3)));
return 0;
}
tgmath.hの制約と注意点
`tgmath.h` を使用する際の注意点もあります。
- 演算子 `+`, `-`, `*`, `/` には適用できない
- マクロ展開されるため、デバッグが難しくなることがある
- 整数型 (`int` など) には対応していない
- 型の推論がうまくいかない場合、エラーの原因になることがある
まとめ
`tgmath.h` は、C言語で数学関数を型を意識せずに利用できる便利なヘッダーです。 `float`、`double`、`long double` の違いを気にせずに関数を呼び出せるため、汎用的なコードを書くのに適しています。 ただし、演算子には適用できないことやデバッグの難しさなどの注意点もあるため、適切に使用する必要があります。