Комплексные числа в Cython

Как правильно работать с комплексными числами в Cython?

Я хотел бы написать чистый цикл C, используя numpy.ndarray dtype np.complex128. В Cython связанный тип C определен вCython/Includes/numpy/__init__.pxd как

ctypedef double complex complex128_t

так что, похоже, это простой C-двойной комплекс.

Тем не менее, легко получить странное поведение. В частности, с этими определениями

cimport numpy as np
import numpy as np
np.import_array()

cdef extern from "complex.h":
    pass

cdef:
    np.complex128_t varc128 = 1j
    np.float64_t varf64 = 1.
    double complex vardc = 1j
    double vard = 1.

линия

varc128 = varc128 * varf64

может быть скомпилирован Cython, но gcc не может скомпилировать полученный код C (ошибка «testcplx.c: 663: 25: ошибка: два или более типов данных в спецификаторах объявления» и, вероятно, из-за строкиtypedef npy_float64 _Complex __pyx_t_npy_float64_complex;). Об этой ошибке уже сообщалось (например,Вот) но я не нашел хорошего объяснения и / или чистого решения.

Без включенияcomplex.h, нет ошибки (я думаю, потому чтоtypedef тогда не входит).

Тем не менее, по-прежнему существует проблема, так как в HTML-файл, созданныйcython -a testcplx.pyx, линияvarc128 = varc128 * varf64 желтый, что означает, что он не был переведен на чистый C. Соответствующий код C:

__pyx_t_2 = __Pyx_c_prod_npy_float64(__pyx_t_npy_float64_complex_from_parts(__Pyx_CREAL(__pyx_v_8testcplx_varc128), __Pyx_CIMAG(__pyx_v_8testcplx_varc128)), __pyx_t_npy_float64_complex_from_parts(__pyx_v_8testcplx_varf64, 0));
__pyx_v_8testcplx_varc128 = __pyx_t_double_complex_from_parts(__Pyx_CREAL(__pyx_t_2), __Pyx_CIMAG(__pyx_t_2));

и__Pyx_CREAL а также__Pyx_CIMAG оранжевые (вызовы Python).

Интересно, что линия

vardc = vardc * vard

не выдает никакой ошибки и переводится на чистый C (просто__pyx_v_8testcplx_vardc = __Pyx_c_prod(__pyx_v_8testcplx_vardc, __pyx_t_double_complex_from_parts(__pyx_v_8testcplx_vard, 0));), тогда как он очень и очень похож на первый.

Я могу избежать ошибки, используя промежуточные переменные (и это переводит на чистый C):

vardc = varc128
vard = varf64
varc128 = vardc * vard

или просто путем приведения (но это не переводит в чистый C):

vardc = <double complex>varc128 * <double>varf64

Так что же происходит? В чем смысл ошибки компиляции? Есть ли чистый способ избежать этого? Почему умножение np.complex128_t и np.float64_t, похоже, включает вызовы Python?

Версии

Cython версии 0.22 (самая последняя версия в Pypi, когда был задан вопрос) и GCC 4.9.2.

вместилище

Я создал крошечный репозиторий с примером (hg clone https://bitbucket.org/paugier/test_cython_complex) и крошечный Makefile с 3 целями (make clean, make build, make html) так что легко проверить что угодно.

Ответы на вопрос(1)

Ваш ответ на вопрос