soutien complexe C99 avec visual studio
-
21-08-2019 - |
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.
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 <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.