Pergunta

Eu gostaria de usar números complexos como definido no C99, mas eu preciso compiladores de apoio que não o suportam (MS compiladores vêm à mente).

Eu não preciso de muitas funções, e implementar as funções necessárias em compiladores sem apoio não é muito difícil. Mas eu tenho um tempo difícil implementar o 'tipo' em si. Idealmente, eu gostaria de fazer algo como:

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

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

Mas eu não estou certo que eu veja como fazer isso se o compilador não pode reconhecer 'float complexo'. Eu realmente acho que é impossível, mas a biblioteca C por Dinkumware parece indicar o contrário. Qual é a solução ? Eu não me importo usando funções / macros para operações sobre o tipo, mas eu preciso de uma maneira de valores atribuir a um número complexo, e voltar a sua real / parte imaginária de uma forma whichi é compatível com C99.

Solução

eu acabei fazendo algo parecido com isto:

#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

para a definição de tipo, e como descrito a seguir para definir um conjunto de funções complexas:

#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

Isso é um pouco complicado, mas isso me permite facilmente reutilização funções C lib quando disponível, e pode ser parcialmente automatizado através de gerador de código.

Foi útil?

Solução

Não importa o que você faz, você não pode fazer "flutuar complexo" parse corretamente em um compilador não-C99. Então, ao invés de escrever isso, fazer alguns typedefs. É muito mais fácil se você só tem que suportar um tipo complexo, por isso vou demonstrar com float complex.

Em primeiro lugar, definir os tipos:

#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

Então, precisamos ser capazes de criar números complexos, e imitar creal e 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

Em seguida, as funções de gravação que a adição envoltório, subtração, multiplicação, divisão, e comparações.

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

Note que add_complex(c, 5) não funciona em modo de C89 no código acima, porque o compilador não sabe como fazer 5 em um complexo. Este é um problema complicado para correção em C sem suporte do compilador - você tem que recorrer a truques como os novos usos tgmath.h, que são específicas do compilador

.

Infelizmente, o efeito de tudo isto é que a ótima sintaxe C99 como a+b para adicionar números complexos tem de ser escrito add_complex(a, b).

Outra opção (como outro autor apontado) é usar std::complex C ++ em compiladores não-C99. Isso pode ser OK se você pode embrulhar as coisas no typedefs e #ifdefs. No entanto, você iria exigir quer C ++ ou C99.

Outras dicas

Há uma biblioteca que eu encontrei no site MSDN. Aqui está um link. http://msdn.microsoft.com/en-us/library/0352zzhd. aspx

Espero que ajuda.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top