Оценка функции C в сетке numpy с использованием Cython

Пример в Простая упаковка кода C с помощью cython хорошо описывает, как оценить функцию, написанную на C, в массиве, переданном из numpy, и вернуть результат в массиве numpy.

Как можно сделать то же самое, но вернуть двумерный массив? т.е. Я хотел бы оценить функцию C в сетке, определенной двумя массивами numpy, и вернуть результат в виде двумерного массива numpy.

Это будет примерно так (с использованием тех же функций, что и в ссылке выше). Очевидно, что теперь нельзя использовать double z[] , но я не уверен, как передать массив 2D numpy в C.

/*  fc.cpp    */
int fc( int N, const double a[], const double b[], double z[] )
    {
    for( int i = 0;  i < N;  i ++ ){
        for( int j = 0;  j < N;  j ++ ){
            z[i][j] = somefunction(a[i],b[j]);
    }
    return N;
}

Это исходный файл .pyx (см. ниже).

import numpy as np
cimport numpy as np
cdef extern from "fc.h": 
    int fc( int N, double* a, double* b, double* z )  # z = a + b

def fpy( N,
    np.ndarray[np.double_t,ndim=1] A,
    np.ndarray[np.double_t,ndim=1] B,
    np.ndarray[np.double_t,ndim=1] Z ):
    """ wrap np arrays to fc( a.data ... ) """
       assert N <= len(A) == len(B) == len(Z)
       fcret = fc( N, <double*> A.data, <double*> B.data, <double*> Z.data )

    return fcret

Большое спасибо.


person Ron OGara    schedule 19.10.2011    source источник


Ответы (1)


Вы можете использовать обычный массив для 2D-матрицы. Вам нужно только указать длину измерения функции.

В файле C сделайте что-то вроде этого: (z теперь является массивом длины N * N)

int fc( int N, const double a[], const double b[], double z[] )
{
    for( int i = 0;  i < N;  i++ ){
        for( int j = 0;  j < N;  j ++ ){
            z[(i*N)+j] = somefunction(a[i],b[j]);
    }
    return N;
}

В Python вам нужно сделать то же самое, поэтому вы можете использовать 1D-массив с элементами N * N вместо 2D-матрицы.

Обновить 3D-кейс

(z теперь представляет собой массив длины N*N*N)

int fc( int N, const double a[], const double b[],const double c[], double z[] )
{
    for( int i = 0;  i < N;  i++ ){
        for( int j = 0;  j < N;  j ++ ){
           for( int k = 0;  k < N;  k ++ ){
            z[((i*N)+j)*N+k] = somefunction(a[i],b[j],c[k]);
    }
    return N;
}
person tune2fs    schedule 19.10.2011
comment
спасибо - это, кажется, хороший способ сделать это. У вас есть идея, как передать массив ›=3 ? - person Ron OGara; 20.10.2011