C99 で定義されている複素数を使用したいのですが、それをサポートしていないコンパイラをサポートする必要があります (MS コンパイラが思い浮かびます)。
多くの関数は必要ありません。必要な関数をサポートなしでコンパイラに実装することはそれほど難しくありません。しかし、「型」自体を実装するのに苦労しています。理想的には、次のようなことをしたいと思います:
#ifndef HAVE_CREAL
double creal(complex z)
{
/* .... */
}
#endif
#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif
しかし、コンパイラが「float complex」を認識できない場合、これを行う方法がわかりません。実際には不可能だと思いますが、Dinkumwareの C ライブラリは別の方法を示しているようです。解決策は何ですか?型の操作に関数/マクロを使用してもかまいませんが、複素数に値を代入し、C99 と互換性のある方法で実数/虚数部分を取得する方法が必要です。
解決
私は最終的に次のようなことをしました:
#ifdef USE_C99_COMPLEX
#include <complex.h>
typedef complex my_complex;
#else
typedef struct {
double x, y;
} my_complex;
#endif
/*
* Those unions are used to convert a pointer of my_complex to native C99
* complex or our own complex type indenpendently on whether C99 complex
* support is available
*/
#ifdef USE_C99_COMPLEX
typedef union {
my_complex my_z;
complex c99_z;
} __complex_to_c99_cast;
#else
typedef union {
my_complex my_z;
my_complex c99_z;
} __complex_to_c99_cast;
#endif
型定義については、次のように複雑な関数のセットを定義します。
#ifndef HAVE_CREAL
double my_creal(my_complex z)
{
union {
my_complex z;
double a[2];
} z1;
z1.z = z;
return z1.a[0];
}
#endif
#ifdef HAVE_CREAL
my_complex my_creal(ny_complex z)
{
__complex_to_c99_cast z1;
__complex_to_c99_cast ret;
z1.my_z = z;
ret.c99_z = creal(z1.c99_z);
return ret.npy_z;
}
#endif
これは少し複雑ですが、これにより、利用可能な場合は C lib 関数を簡単に再利用でき、コード ジェネレーターを使用して部分的に自動化できます。