gpt4 book ai didi

python - 我可以通过 gsl_function 的包装或 cython 重新声明将 cython 类方法分配给 gsl_function 结构吗?

转载 作者:太空宇宙 更新时间:2023-11-03 17:23:07 26 4
gpt4 key购买 nike

这个问题建立在 here 的基础上

我有以下 cython 代码,它导入一个文件 (cGslInteg.pxd),其中包含 gsl/gsl_integration.h 相关部分的 cython 声明>gsl/gsl_math.h 头文件,然后定义一个类来计算积分:

from libc.math cimport log
from libc.math cimport sqrt
from cGslInteg cimport *

ctypedef double * double_ptr

cdef double integrand(double x, void * params):
"""integrand implemented outside class """

cdef double alpha = (<double_ptr> params)[0]
cdef double f = log(alpha*x) / sqrt(x)
return f


cdef class CalcSomething(object):

def integrate(self, double a, double b, double alpha):
"""This does the integral"""

cdef double result, error

cdef gsl_integration_workspace * W
W = gsl_integration_workspace_alloc(1000)

cdef gsl_function F

F.function = &integrand # works
# F.function = &self._integrand # doesn't work

cdef double params[1]
params[0] = alpha
F.params = &params

cdef double epsabs = 0.
cdef double epsrel = 1e-7
gsl_integration_qags(&F, a, b, epsabs, epsrel, 1000, W, &result, &error)
gsl_integration_workspace_free(W)

return result


cdef double _integrand(self, double x, void * params):
"""integrand implemented inside class """

cdef double alpha = (<double_ptr> params)[0]
cdef double f = log(alpha*x) / sqrt(x)
return f

当使用类外部的被积函数(F.function = &integrand)时,上述代码可以正确编译和运行。但是,将此行更改为下面注释掉的行 (F.function = &self._integrand) 以便使用类内的被积函数,会产生以下编译结果错误:

cython_class_gsl.pyx:31:21: Cannot assign type 'double (*)(CalcSomething, double, void *)' to 'double (*)(double, void *)'

这是有道理的,因为我在 cGslInteg.pxd 中对 gsl_function 的声明是:

cdef extern from "gsl/gsl_math.h":

# Definition of an arbitrary function with parameters
ctypedef struct gsl_function:
double (* function) (double x, void * params)
void * params

我的问题是:我可以重新声明 gsl_function 以便它需要具有类型的内容,例如double (*)(PythonObject, double, void *) 或者我可以包装 self._integrand 使其看起来具有类型 double (*)( double, void *)

编辑:一些额外的注释可以使其更接近现实生活中的问题:

  1. self._integrand 的任何包装器都必须CalcSomething 类中定义。
  2. 积分参数 alpha 不能是类变量(即它必须在 params 参数内传递给被积函数)

最佳答案

这就是 params 的用途。你会做这样的事情(大大减少示例......)

from libc.math cimport log,sqrt

cdef class CalcSomething:
cdef double integrand(self, double x, double alpha):
return log(alpha*x)/sqrt(x)

cdef double wrapped_integrand_func(double x, void* params):
cdef object params_as_object = <object>params
cdef CalcSomething instance = params_as_object[0] # we need to know the type to use cdef functions
alpha = params_as_object[1]
return instance.integrand(x,alpha)

def test(alpha):
cdef object o = (CalcSomething(),alpha) # store Calc something and alpha as a tuple
cdef void* o_ptr = <void*>o # be careful with reference counts here - o_ptr doesn't keep o alive!
print(wrapped_integrand_func(4.3,o_ptr))

这显然不是包装绑定(bind)方法问题的通用解决方案,但在这种情况下,这正是 gsl 让您传递 void* 的原因。

需要注意的是,只要您想使用 o_ptr,您就必须确保 o 保持事件状态。

更新(以匹配稍微编辑过的问题):

The integration parameter alpha cannot be a class variable (i.e. it must be passed within the params argument to the integrand)

这很容易完成。在我的原始代码中,我使用了一个类变量,但现在我已将它们作为元组单独传递。

关于python - 我可以通过 gsl_function 的包装或 cython 重新声明将 cython 类方法分配给 gsl_function 结构吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32915784/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com