Оценка функции C на сетчатой ​​сетке с использованием Cython - PullRequest
1 голос
/ 20 октября 2011

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

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

Было бы что-то вроде этого (используя те же функции, что и в ссылке выше). Очевидно, что сейчас нельзя использовать double z [], но я не уверен, как передать двумерный массив 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

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

1 Ответ

1 голос
/ 20 октября 2011

Вы можете использовать обычный массив для 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;
}

InВ 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;
}
...