Cython 中的 abs(双复数)
abs(double complex) in Cython
如何获得 double complex
变量的绝对值?
def f():
cdef double complex aaa = 1 + 2j
cdef double bbb = abs(aaa)
第二个分配在 cython -a
html 输出中突出显示为黄色:aaa
在应用 abs()
之前转换为 python object .
如何在 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
等,应该根据编译标志选择正确的 header 来包含(<complex>
或 "complex.h"
或自定义代码)。
如何使用这些说明?
更有用的贡献:
以下是修复 "cython/compiler/Builtin.py" 的半测试补充。添加它的位置应该很明显:
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 尝试对复杂类型使用 "native" 布局,因此整个事情变得稍微复杂一些。来自 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 你需要从 complex.h
:
告诉 Cython 关于 cabs
cdef extern from "complex.h":
double cabs(double complex)
def f():
cdef double complex aaa = 1 + 2j
cdef double bbb = cabs(aaa)
return bbb
如果你正在学习 C++,你需要告诉 Cython C++ 标准库 abs
。不幸的是,它无法在其预定义包装器中的 libcpp.complex.complex
和 double complex
类型之间创建 link ,因此您需要自己告诉它函数:
cdef extern from "<complex>":
double abs(double complex)
def f():
cdef complex aaa = 1 + 2j
cdef double bbb = abs(aaa)
return bbb
如果 CYTHON_CCOMPLEX
未定义,我不会立即知道该怎么做,但我认为这是您无论如何都必须明确执行的事情。
如何获得 double complex
变量的绝对值?
def f():
cdef double complex aaa = 1 + 2j
cdef double bbb = abs(aaa)
第二个分配在 cython -a
html 输出中突出显示为黄色:aaa
在应用 abs()
之前转换为 python object .
如何在 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
等,应该根据编译标志选择正确的 header 来包含(<complex>
或 "complex.h"
或自定义代码)。
如何使用这些说明?
更有用的贡献:
以下是修复 "cython/compiler/Builtin.py" 的半测试补充。添加它的位置应该很明显:
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 尝试对复杂类型使用 "native" 布局,因此整个事情变得稍微复杂一些。来自 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 你需要从 complex.h
:
cabs
cdef extern from "complex.h":
double cabs(double complex)
def f():
cdef double complex aaa = 1 + 2j
cdef double bbb = cabs(aaa)
return bbb
如果你正在学习 C++,你需要告诉 Cython C++ 标准库 abs
。不幸的是,它无法在其预定义包装器中的 libcpp.complex.complex
和 double complex
类型之间创建 link ,因此您需要自己告诉它函数:
cdef extern from "<complex>":
double abs(double complex)
def f():
cdef complex aaa = 1 + 2j
cdef double bbb = abs(aaa)
return bbb
如果 CYTHON_CCOMPLEX
未定义,我不会立即知道该怎么做,但我认为这是您无论如何都必须明确执行的事情。