【问题标题】:invalid types ‘float[int]’ for array subscript error and passing variables to scipy.weave.inline数组下标错误的无效类型'float [int]'并将变量传递给scipy.weave.inline
【发布时间】:2011-09-28 18:32:03
【问题描述】:

我一直在玩 Scipy 的内联工具(通过 weave),但我遇到了一些麻烦。我的 C 生锈了,我感觉我缺少一些简单的东西。

下面的函数设计为采用 3D float32 numpy 数组。我正在使用大量网格化大气数据,但这应该适用于任何 3D 阵列。然后获取网格并获得跨轴 i 的算术平均值,对于每个点 j,k(即,如果 i 是时间轴,j 和 k 是纬度/经度,那么我对每个网格点的时间进行平均)。

我希望我的代码这样做并避免使用 numpy NaN(我相信 isnan() 在内联 C/C++ 中工作......?)。但是,无论是否这样做,我都无法让代码编译而不会出现以下错误:

tools.py: In function ‘PyObject* compiled_func(PyObject*, PyObject*)’:
tools.py:93:45: error: invalid types ‘float[int]’ for array subscript
tools.py:95:51: error: invalid types ‘float[int]’ for array subscript
tools.py: In function ‘PyObject* compiled_func(PyObject*, PyObject*)’:
tools.py:93:45: error: invalid types ‘float[int]’ for array subscript
tools.py:95:51: error: invalid types ‘float[int]’ for array subscript

我认为我正在正确声明和初始化,所以也许某些东西没有按照我认为的方式传递给 weave?如果有人可以帮助我解决这个问题,我会很高兴。这是函数:

from scipy.weave import inline

def foo(x):
    xi = np.shape(x)[0]
    xj = np.shape(x)[1]
    xk = np.shape(x)[2]
    code = """
           #line 87 "tools.py"
           int n;
           float out[xj][xk];
           for (int k = 0; k < xk; k++) {
               for (int j = 0; j < xj; j++) {
                   n = 0;
                   for (int i = 0; i < xi; i++) {
                       if (!isnan(x[i][j][k])) {
                           n += 1;
                           out[j][k] += x[i][j][k];
                       }
                   }
                   out[j][k] = out[j][k]/n;
               }
           }
           return_val = out;
           """
    awesomeness = inline(code, ['x', 'xi', 'xj', 'xk'], compiler = 'gcc')
    return(awesomeness)

【问题讨论】:

    标签: python c numpy scipy


    【解决方案1】:

    您可以先在 python 中创建 out 数组,然后将其传递给 C++。在 C++ 中,您可以通过 Nx[0]、Nx[1]、Nx[2] 获得 x 的形状。您可以使用为数组定义的宏来访问它的元素。例如:X3(k,j,i) 与 python 中的 x[k,j,i] 相同,OUT2(j,i) 与 python 中的 out[j,i] 相同。您可以查看自动创建的 C++ 代码,以了解可用于数组的变量和宏。获取C++代码的文件夹:

    from scipy import weave
    print weave.catalog.default_dir()
    

    我的编译器不支持 isnan(),所以我使用 tmp==tmp 来检查它。

    # -*- coding: utf-8 -*-
    import scipy.weave as weave
    import numpy as np
    
    def foo(x):
        out = np.zeros(x.shape[1:])
        code = """
        int i,j,k,n;
        for(i=0;i<Nx[2];i++)
        {
            for(j=0;j<Nx[1];j++)
            {
                n = 0;
                for(k=0;k<Nx[0];k++)
                {
                    double tmp = X3(k,j,i);
                    if(tmp == tmp) // if isnan() is not available
                    {
                        OUT2(j,i) += tmp;
                        n++;
                    }
                }
                OUT2(j,i) /= n;
            }
        }
        """
        weave.inline(code, ["x","out"], headers=["<math.h>"], compiler="gcc")
        return out
    
    np.random.seed(0)    
    x = np.random.rand(3,4,5)
    x[0,0,0] = np.nan
    mx = np.ma.array(x, mask=np.isnan(x))
    avg1 = foo(x)
    avg2 = np.ma.average(mx, axis=0)
    print np.all(avg1 == avg2)
    

    您还可以使用 blitz 转换器在 C++ 中访问数组。有关详细信息,请尝试 google:weave.converters.blitz

    【讨论】:

    • 太棒了!有用!非常便利!我将不得不深入研究。
    【解决方案2】:

    C 不支持像 out[xj][xk] 这样的动态数组大小调整。您要么必须对大小进行硬编码,要么使用 malloc 或 Weave 支持的东西来动态分配数据。

    【讨论】:

    • 这不就是我通过将 xj 和 xk 作为 int 传递并使用它们来初始化数组所做的吗?
    猜你喜欢
    • 2016-08-23
    • 1970-01-01
    • 2021-12-25
    • 2015-09-26
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    相关资源
    最近更新 更多