C99 support complexe avec visual studio

J’aimerais utiliser des nombres complexes tels que définis dans C99, mais je dois prendre en charge les compilateurs qui ne le supportent pas (les compilateurs MS me viennent à l’esprit).

Je n’ai pas besoin de beaucoup de fonctions, et implémenter les fonctions nécessaires sur des compilateurs sans support n’est pas trop difficile. Mais j’ai du mal à mettre en œuvre le “type” lui-même. Idéalement, j’aimerais 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 procéder si le compilateur ne peut pas reconnaître le «complexe flottant». Je pense en fait que c’est impossible, mais la bibliothèque C de Dinkumware semble indiquer le contraire. Quelle est la solution ? Cela ne me dérange pas d’utiliser des fonctions / macros pour les opérations sur le type, mais il me faut un moyen d’affecter des valeurs à un nombre complexe et de récupérer sa partie réelle / imaginaire d’une manière compatible avec C99.

Solution

J’ai fini par faire quelque chose comme ça:

 #ifdef USE_C99_COMPLEX #include  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 du 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 de Cib quand elles sont disponibles, et cela peut être partiellement automatisé via le générateur de code.

Quoi que vous fassiez, vous ne pouvez pas faire l’parsing “complexe flottant” correctement dans un compilateur non-C99. Donc, au lieu d’écrire cela, créez des types de caractères. C’est beaucoup plus facile si vous ne devez prendre en charge qu’un seul type de complexe. Je vais donc simplement présenter une démonstration avec le float complex .

D’abord, définissez les types:

 #if __STDC_VERSION__ >= 199901L //using a C99 comstackr #include  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 d’imuler creal et cimag.


si STDC_VERSION > = 199901L

// creal, cimag déjà défini dans complex.h

inline complex_float make_complex_float (float real, float imag)
{
retourne real + imag * I;
}

autre

définir creal (z) ((z) .re)

définir cimag (z) ((z) .im)

extern const complex_float complex_i; // mettre quelque part dans une unité de traduction

définir je complexe_i

inline complex_float make_complex_float (float real, float imag)
{
complex_float z = {real, imag};
retourne z;
}

fin si

Ensuite, écrivez des fonctions qui encapsulent des additions, des soustractions, des multiplications, des divisions 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 `add_complex (c, 5)` ne fonctionne pas en mode C89 dans le code ci-dessus, car le compilateur ne sait pas comment transformer 5 en complexe. C’est un problème délicat à résoudre en C sans support du compilateur – vous devez recourir à des astuces telles que les nouvelles utilisations de `tgmath.h`, spécifiques au compilateur.

Malheureusement, l’effet de tout cela est que la belle syntaxe C99 telle que `a + b` pour append des nombres complexes doit s’écrire` add_complex (a, b) `.

Une autre option (comme l’a indiqué une autre affiche) consiste à utiliser C ++ `std :: complex` sur des compilateurs non C99. Cela pourrait être correct si vous pouvez envelopper les choses dans typedefs et `# ifdef`s. Cependant, vous auriez besoin de C ++ ou de C99.

Il y a une bibliothèque que j’ai trouvée sur le site web msdn. Voici un lien. http://msdn.microsoft.com/en-us/library/0352zzhd.aspx

J’espère que ça aide.