Dav*_*eau 6 c c99 complex-numbers visual-studio
我想使用C99中定义的复数,但我需要支持不支持它的编译器(MS编译器会浮现在脑海中).
我不需要很多功能,并且在没有支持的情况下在编译器上实现所需的功能并不困难.但我很难实现'类型'本身.理想情况下,我想做的事情如下:
#ifndef HAVE_CREAL
double creal(complex z)
{
/* .... */
}
#endif
#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif
Run Code Online (Sandbox Code Playgroud)
但是如果编译器无法识别'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
Run Code Online (Sandbox Code Playgroud)
对于类型定义,以及如下定义一组复杂函数:
#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
Run Code Online (Sandbox Code Playgroud)
这有点复杂,但是这使我能够在可用时轻松地重用C lib函数,并且可以通过代码生成器部分自动化.
无论你做什么,你都不能在非C99编译器中正确解析"浮动复杂".因此,不要写它,而是制作一些typedef.如果你只需要支持一种复杂类型就容易得多,所以我只是用它来演示float complex.
首先,定义类型:
#if __STDC_VERSION__ >= 199901L
//using a C99 compiler
#include <complex.h>
typedef float _Complex float_complex;
#else
typedef struct
{
float re, im;
} float_complex;
#endif
Run Code Online (Sandbox Code Playgroud)
然后,我们需要能够创建复杂的数字,并模拟creal和cimag.
#if __STDC_VERSION__ >= 199901L
//creal, cimag already defined in complex.h
inline complex_float make_complex_float(float real, float imag)
{
return real + imag * I;
}
#else
#define creal(z) ((z).re)
#define cimag(z) ((z).im)
extern const complex_float complex_i; //put in a translation unit somewhere
#define I complex_i
inline complex_float make_complex_float(float real, float imag)
{
complex_float z = {real, imag};
return z;
}
#endif
Run Code Online (Sandbox Code Playgroud)
接下来,编写包含加法,减法,乘法,除法和比较的函数.
#if __STDC_VERSION__ >= 199901L
#define add_complex(a, b) ((a)+(b))
//similarly for other operations
#else //not C99
inline float_complex add_complex(float_complex a, float_complex b)
{
float_complex z = {a.re + b.re, a.im + b.im};
return z;
}
//similarly for subtract, multiply, divide, and comparison operations.
Run Code Online (Sandbox Code Playgroud)
请注意,在上面的代码中,`add_complex(c,5)`在C89模式下不起作用,因为编译器不知道如何将5变成复合体.在没有编译器支持的情况下修复C是一个棘手的问题 - 你必须采用新的`tgmath.h`使用的技巧,这是特定于编译器的.
不幸的是,所有这一切的效果是,添加复数的好的C99语法如`a + b`必须写成`add_complex(a,b)`.
另一个选项(另一张海报指出)是在非C99编译器上使用C++`std :: complex`.如果你可以在typedef和`#ifdef中包装东西,这可能没问题.但是,您需要C++或C99.
| 归档时间: |
|
| 查看次数: |
7841 次 |
| 最近记录: |