Question

Je voudrais utiliser des nombres complexes tels que définis dans C99, mais je dois soutenir les compilateurs qui ne supportent pas (compilateurs MS viennent à l'esprit).

Je ne ai pas besoin de nombreuses fonctions, et mettre en œuvre les fonctions nécessaires sur compilateurs sans le soutien est pas trop difficile. Mais j'ai du mal à mettre en œuvre le même « type ». Idéalement, je voudrais faire quelque chose comme:

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

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

Mais je ne suis pas sûr de voir comment faire si le compilateur ne reconnaît pas «complexe flottant. Je pense effectivement qu'il est impossible, mais la bibliothèque C par Dinkumware semble indiquer le contraire. Quelle est la solution ? Je ne me dérange pas en utilisant des fonctions / macros pour les opérations sur le type, mais je besoin d'un moyen d'attribuer des valeurs à un nombre complexe, et de revenir sa partie réelle / imaginaire d'une manière whichi est compatible avec C99.

Solution

J'ai fini par faire quelque chose comme ceci:

#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

pour la définition de type, et comme suit pour définir un ensemble de fonctions complexes:

#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'est un peu compliqué, mais cela me permet de réutiliser facilement les fonctions C lib lorsqu'elles sont disponibles, et il peut être partiellement automatisé par générateur de code.

Était-ce utile?

La solution

Peu importe ce que vous faites, vous ne pouvez pas parse « flotter complexe » correctement dans un compilateur non-C99. Ainsi, au lieu d'écrire que, faire quelques typedefs. Il est beaucoup plus facile si vous suffit de soutenir un type complexe, donc je vais juste montrer avec float complex.

D'abord, définir les types:

#if __STDC_VERSION__ >= 199901L
//using a C99 compiler
#include &lt;complex.h>
typedef float _Complex float_complex;
#else
typedef struct 
{
    float re, im;
} float_complex;
#endif

Ensuite, nous devons être en mesure de créer des nombres complexes et imiter Creal et 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

Ensuite, écrire des fonctions que l'addition d'une pellicule, soustraction, multiplication, division, et des comparaisons.

#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.

Notez que ne fonctionne pas add_complex(c, 5) en mode C89 dans le code ci-dessus, parce que le compilateur ne sait pas comment faire 5 dans un complexe. Ceci est un problème difficile à résoudre en C sans le soutien du compilateur -. Vous devez recourir à des astuces comme les nouveaux usages qui tgmath.h spécifiques compilateur

Malheureusement, l'effet de tout cela est que la belle syntaxe C99 comme pour ajouter des numéros a+b complexes doit être écrit add_complex(a, b).

Une autre option (comme un autre souligné) est d'utiliser C ++ sur compilateurs non std::complex-C99. Cela pourrait être OK si vous pouvez envelopper les choses dans typedefs et s #ifdef. Cependant, vous auriez besoin C ++ ou C99.

Autres conseils

Il y a une bibliothèque que je trouve sur le site msdn. Voici un lien. http://msdn.microsoft.com/en-us/library/0352zzhd. aspx

J'espère que cela aide.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top