views:

818

answers:

2

I would like to use complex numbers as defined in C99, but I need to support compilers which do not support it (MS compilers come to mind).

I don't need many functions, and implementing the needed functions on compilers without support is not too difficult. But I have a hard time implementing the 'type' itself. Ideally, I would like to do something like:

#ifndef HAVE_CREAL
double creal(complex z)
{
/* .... */
}
#endif

#ifndef HAVE_CREALF
float creal(float complex z)
{
/* ... */
}
#endif

But I am not sure I see how to do this if the compiler cannot recognize 'float complex'. I would actually think it is impossible, but the C library by Dinkumware seems to indicate otherwise. What is the solution ? I don't mind using functions/macros for operations on the type, but I need a way to assign values to a complex number, and get back its real/imaginary part in a way whichi is compatible with C99.

Solution

I ended up doing something like this:

#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

for the type definition, and as follows to define a set of complex functions:

#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

That's a bit complicated, but this enables me to easily reuse C lib functions when available, and it can be partly automated through code generator.

A: 

There is a library that I found on the msdn website. Here's a link. http://msdn.microsoft.com/en-us/library/0352zzhd.aspx

I hope that helps.

mikeyickey
+2  A: 
Doug
C++ does not work, because you cannot have std::complex in the signature of functions with C linkage. I could add a wrapper around this, but then, there is not much point in using C++ at all. As the project does not depend on C++ for now, that represents a big dependency anyway - I need to support many platforms, not just recent gcc and MS compilers.
David Cournapeau
If you are worried about what style of linkage you're using, I presume you need to have link-time (binary) compatibility between object files compiled at different times, not just source compatibility. In that case, it might be better to always use the struct float_complex approach. Otherwise, someone could compile a file in a compiler's C89 mode, try to call a function in a library compiled in C99 mode, and see strange results because the calling conventions for _Complex and float_complex structs aren't the same.
Doug