python - Cython 中的 abs(双复合体)

标签 python cython complex-numbers

如何获得 double complex 的绝对值变量?

def f():
    cdef double complex aaa = 1 + 2j
    cdef double bbb = abs(aaa)

第二个作业在cython -a中以黄色突出显示。 html 输出:aaa在应用 abs() 之前转换为 python 对象.

如何调用abs()在 c/cpp 级别?

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 中工作。 block 。

一旦我查看了这些问题,我可能会将其提交到 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 block ),Cython 似乎定义了 abs 的快速版本(以及其他有用的函数)适用于所有这些类型,但无法智能地使用它们,而是退回到 Python 实现。

如果您要使用 C,则需要告诉 Cython cabs来自complex.h :

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 中类型,所以你需要自己告诉它这个函数:

cdef extern from "<complex>":
    double abs(double complex)

def f():
    cdef complex aaa = 1 + 2j
    cdef double bbb = abs(aaa)
    return bbb

如果 CYTHON_CCOMPLEX 我不知道该怎么办未定义,但我认为无论如何您都必须明确执行此操作。

关于python - Cython 中的 abs(双复合体),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43067131/

相关文章:

python - Cython 发出 'unnecessary' 警告

c++ - 将 STL complex<double> 转换为 fftw_complex 的问题

algorithm - 如何计算离散傅里叶变换?

python - 未实现错误: Wrong number or type of arguments for overloaded function 'new_RoutingModel'

python - 如何使用 aiosmtpd 正确支持 STARTTLS?

python - Cython:加速简单代码

c - 如何在 Cython 中动态声明二维 c 数组

c++ - 在 C++ 中使用 std::complex<T> 创建复无穷大

python - 如何管理 while 循环来反转此打印

python - Caffe Net 不训练(训练时损失不会改变)