在 Cython 中使用 C++ 复杂函数

Using c++ complex functions in Cython

我正在尝试在 Cython 中进行复指数运算。

我已经能够为我的 pyx 拼凑出以下代码:

from libc.math cimport sin, cos, acos, exp, sqrt, fabs, M_PI, floor, ceil

cdef extern from "complex.h":
    double complex cexp(double complex z)

import numpy as np
cimport numpy as np
import cython
from cython.parallel cimport prange, parallel

def try_cexp():
    cdef:
        double complex rr1
        double complex rr2
    rr1 = 1j
    rr2 = 2j

    print(rr1*rr2)

    #print(cexp(rr1))

请注意 print(cexp(rr1)) 已注释。当线路处于活动状态时,当 运行ning setup.py:

时出现以下错误
error: command 'C:\WinPYthon\Winpython-64bit-3.4.3.6\python-3.4.3.amd64\scripts\gcc.exe' failed with exit status 1

请注意,当 cexp 被注释掉时,一切都是 运行 预期的......我可以 运行 setup.py,当我测试它打印出来的功能时两个复数的乘积。

这是我的 setup.py 文件。请注意,它包含使用 g++ 在 Cython 中 运行 openmp 的代码:

from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy as np
import os
os.environ["CC"] = "g++-4.7"
os.environ["CXX"] = "g++-4.7"

# These were added based on some examples I had seen of cexp in Cython. No effect.
#import pyximport
#pyximport.install(reload_support=True)

ext_modules = [
    Extension('complex_test',
              ['complex_test.pyx'],
              language="c++",
              extra_compile_args=['-fopenmp'],
              extra_link_args=['-fopenmp', '-lm'])  # Note that '-lm' was
              # added due to an example where someone mentioned g++ required
              # this. Same results with and without it.
    ]

setup(
    name='complex_test',
    cmdclass={'build_ext': build_ext},
    ext_modules=ext_modules,
    include_dirs=[np.get_include()]
    )

最终我的目标是加快看起来像 k*exp(z) 的计算,其中 kz 是复杂的。目前我正在使用数值表达式,但是它有很大的内存开销,我相信可以进一步优化它。

感谢您的帮助。

您使用的 cexp instead of expC++ 中的一样。将您的 cdef extern 更改为:

cdef extern from "<complex.h>" namespace "std":
    double complex exp(double complex z)
    float complex exp(float complex z)  # overload

你的 print 呼叫:

print(exp(rr1))

而且它应该很有魅力。


我知道编译消息很长,但您可以在其中找到指向罪魁祸首的错误:

complex_test.cpp: In function ‘PyObject* __pyx_pf_12complex_test_try_cexp(PyObject*)’:
complex_test.cpp:1270:31: error: cannot convert ‘__pyx_t_double_complex {aka std::complex<double>}’ to ‘__complex__ double’ for argument ‘1’ to ‘__complex__ double cexp(__complex__ double)’
   __pyx_t_3 = cexp(__pyx_v_rr1);

乱七八糟,但你能看出原因。 *您正在向需要不同类型 (__complex__ double) 的 C 函数提供 C++ 定义类型(Cython 术语中的 __pyx_t_double_complex)。