C言語にて関数csinlが使えない場合がある
数学のsin関数に複素数って渡せるんですね。 全然知りませんでした。
C言語のc99標準ライブラリにも用意されているようです。
具体的には下記の関数。
csinf, csin, csinl, sin(tgmath)
問題は、clangのlong double complexを引数とする関数がいくつか使えない事です。
例えばclangではcsinlを使おうとするとエラーになります。
clangというとFreeBSDの標準コンパイラですが、
manコマンドのマニュアルにも載ってなようなので、
少なくともFreeBSD開発側は認識できているようです。
確認した環境は下記の通り。
% freebsd-version 12.0-RELEASE-p3 % clang --version FreeBSD clang version 6.0.1 (tags/RELEASE_601/final 335540) (based on LLVM 6.0.1) Target: x86_64-unknown-freebsd12.0 Thread model: posix InstalledDir: /usr/bin
モジュール自体が存在しないので、csinlがあるとコンパイルが通りません。 tgmath.hを利用してsin関数にlong double complexを渡しても、 あれは結局マクロでcsinlにするだけなのでエラーになります。
そうなんですか、無理ですか。
完全に他人任せで実装されるまで大人しく待ってようと思います。
しかし妥協すれば解決策はいくつかあると思います。
私の大のお気に入りは、下記の極めて最低な方法。
#ifdef __clang__ #define csinl csin #endif
#include <stdio.h> #include <cmath> #include <complex> int main() { std::complex<float> f(1.2f, 3.4f); std::complex<double> d(1.2, 3.4); std::complex<long double> l(1.2L, 3.4L); f = std::sin(f); d = std::sin(d); l = std::sin(l); printf("%30.25e, %30.25e\n", real(f), imag(f)); printf("%30.25e, %30.25e\n", real(d), imag(d)); printf("%30.25Le, %30.25Le\n", real(l), imag(l)); return 0; }
実行結果
$ clang++ test.cpp $ ./a.out 1.3979410171508789062500000e+01, 5.4228153228759765625000000e+00 1.3979408806017994848502894e+01, 5.4228154724634016758955113e+00 1.3979408806017997938912767e+01, 5.4228154724634012448167275e+00
うまく行っているように見えます。
なぜC++でうまく行ってC99じゃダメなのか。
他には、clangではなくgccを利用する方法。
2月くらいのGentoo Linuxで確認しましたが、こちらは問題ありません。
そしてあまりお勧めできないのは自分でcsinlを実装する方法です。
正直csinl程度なら何とかなりそうなもんですけど、
arcsinやらになると、数値計算に自信がないならやめた方がいいかもしれません。
もしかして自分が勘違いしているだけでcsinlはc99標準じゃない? 関数clogなんて丸ごと存在しないんですよね。 わざわざ/usr/includeを確認してしまった。