如何获得double complex
变量的绝对值?
def f():
cdef double complex aaa = 1 + 2j
cdef double bbb = abs(aaa)
第二个作业在cython -a
html输出中以黄色突出显示:aaa
在应用abs()
之前转换为python对象。
如何在c / cpp级别调用abs()
?
PS 我理解
cdef extern from "complex.h":
double abs(double complex)
会解决它,但我在生成的c / cpp文件中看到以下说明:
#if CYTHON_CCOMPLEX
#define __Pyx_c_abs_double(z) (::std::abs(z))
#endif
等,它应该根据编译标记选择正确的标题来包含(<complex>
或"complex.h"
或自定义代码)。
我如何使用这些说明?
答案 0 :(得分:1)
更有用的贡献:
以下是修复&#34; cython / compiler / Builtin.py&#34;的半测试添加。在哪里添加它应该是非常明显的:
BuiltinFunction('abs', None, None, "__Pyx_c_abs{0}".format(PyrexTypes.c_double_complex_type.funcsuffix),
#utility_code = UtilityCode.load('Arithmetic', 'Complex.c', PyrexTypes.c_double_complex_type._utility_code_context()),
func_type = PyrexTypes.CFuncType(
PyrexTypes.c_double_type, [
PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_double_complex_type, None)
],
is_strict_signature = True)),
BuiltinFunction('abs', None, None, "__Pyx_c_abs{0}".format(PyrexTypes.c_float_complex_type.funcsuffix),
#utility_code = UtilityCode.load('Arithmetic', 'Complex.c', PyrexTypes.c_float_complex_type._utility_code_context()),
func_type = PyrexTypes.CFuncType(
PyrexTypes.c_float_type, [
PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_float_complex_type, None)
],
is_strict_signature = True)),
BuiltinFunction('abs', None, None, "__Pyx_c_abs{0}".format(PyrexTypes.c_longdouble_complex_type.funcsuffix),
#utility_code = UtilityCode.load('Arithmetic', 'Complex.c', PyrexTypes.c_longdouble_complex_type._utility_code_context()),
func_type = PyrexTypes.CFuncType(
PyrexTypes.c_longdouble_type, [
PyrexTypes.CFuncTypeArg("arg", PyrexTypes.c_longdouble_complex_type, None)
],
is_strict_signature = True)),
似乎有效。它还没有通过完整的Cython测试套件。它还没有在您的文件顶部生成正确的代码(但可能不需要,因为您已经使用了complex double
。)它还没有在nogil
块中工作。
在我查看这些问题之后,我可能会将它提交给Cython github。
原始答案:
由于Cython尝试使用&#34; native&#34;所以整个事情变得稍微复杂一些。复杂类型的布局。从Cython生成的代码:
#if CYTHON_CCOMPLEX
#ifdef __cplusplus
typedef ::std::complex< double > __pyx_t_double_complex;
#else
typedef double _Complex __pyx_t_double_complex;
#endif
#else
typedef struct { double real, imag; } __pyx_t_double_complex;
#endif
在所有情况下,类型都应该具有兼容的内存布局(我认为),所以最糟糕的情况是一些类型转换应该允许你使用任何实现的abs
函数。
为了增加混乱,如果你看一下生成的Cython代码(在生成的文件中搜索各种#if CYTHON_CCOMPLEX
块),看来Cython定义了abs
的快速版本(和其他有用的)函数)用于所有这些类型,但未能智能地使用它们,回到Python实现。
如果你要通过C,你需要告诉Cython关于来自cabs
的{{1}}:
complex.h
如果您正在使用C ++,则需要告诉Cython有关C ++标准库cdef extern from "complex.h":
double cabs(double complex)
def f():
cdef double complex aaa = 1 + 2j
cdef double bbb = cabs(aaa)
return bbb
的信息。不幸的是,它无法在预定义包装器中的abs
与libcpp.complex.complex
类型之间建立链接,因此您需要自己告诉它有关该功能的信息:
double complex
如果cdef extern from "<complex>":
double abs(double complex)
def f():
cdef complex aaa = 1 + 2j
cdef double bbb = abs(aaa)
return bbb
未定义,我不会立即知道该怎么做,但我认为这无论如何都必须明确做。