Вопрос

Я хотел бы использовать комплексные числа, как определено в C99, но мне нужно поддерживать компиляторы, которые это не поддерживают (на ум приходят компиляторы MS).

Мне не нужно много функций, и реализовать необходимые функции в компиляторах без поддержки не так уж сложно.Но мне трудно реализовать сам "тип".В идеале я хотел бы сделать что-то вроде:

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

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

Но я не уверен, что вижу, как это сделать, если компилятор не может распознать "float complex".Я бы на самом деле подумал, что это невозможно, но библиотека C с помощью Посуда для столовой посуды кажется, это указывает на обратное.Каково же решение ?Я не возражаю против использования функций / макросов для операций с типом, но мне нужен способ присвоить значения комплексному числу и вернуть его действительную / мнимую часть способом, совместимым с C99.

Решение

В итоге я сделал что-то вроде этого:

#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

для определения типа и следующим образом для определения набора сложных функций:

#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, когда они доступны, и это может быть частично автоматизировано с помощью генератора кода.

Это было полезно?

Решение

Независимо от того, что вы делаете, вы не можете заставить "float complex" правильно анализировать в компиляторе, отличном от C99.Поэтому вместо того, чтобы писать это, создайте несколько typedefs.Это намного проще, если вам нужно поддерживать только один сложный тип, поэтому я просто продемонстрирую с помощью float complex.

Во-первых, определите типы:

#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

Затем нам нужно уметь создавать комплексные числа и эмулировать creal и 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

Затем напишите функции, которые включают в себя сложение, вычитание, умножение, деление и сравнения.

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

Обратите внимание , что add_complex(c, 5) не работает в режиме C89 в приведенном выше коде, потому что компилятор не знает, как превратить 5 в сложный.Это сложная проблема, которую трудно исправить на C без поддержки компилятора - вам придется прибегнуть к трюкам, подобным новому tgmath.h использует, которые зависят от компилятора.

К сожалению, результатом всего этого является то, что приятный синтаксис C99, подобный a+b для сложения комплексных чисел необходимо записать add_complex(a, b).

Другой вариант (на который указывал другой плакат) - использовать C ++ std::complex на компиляторах, отличных от C99.Это могло бы быть нормально, если бы вы могли обернуть все в typedefs и #ifdefs.Однако вам потребуется либо C ++, либо C99.

Другие советы

Существует библиотека, которую я нашел на веб-сайте msdn.Вот ссылка.http://msdn.microsoft.com/en-us/library/0352zzhd.aspx

Я надеюсь, что это поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top