対数空間で配列の行を正規化する C 関数があります (これにより、数値のアンダーフローが防止されます)。
私のC関数のプロトタイプは次のとおりです。
void normalize_logspace_matrix(size_t nrow, size_t ncol, double* mat);
配列へのポインターを受け取り、その場で変更することがわかります。もちろん、C コードは、データが C 連続配列、つまり行連続として保存されることを前提としています。
Cython を使用して次のように関数をラップします (インポートとcdef extern from
省略):
def normalize_logspace(np.ndarray[np.double_t, ndim=2] mat):
cdef Py_ssize_t n, d
n = mat.shape[0]
d = mat.shape[1]
normalize_logspace_matrix(n, d, <double*> mat.data)
return mat
ほとんどの場合、numpy-arrays は行が連続しており、関数は正常に動作します。ただし、numpy-array が以前に転置されている場合、データはコピーされず、データへの新しいビューだけが返されます。この場合、配列が行に連続していないため、関数は失敗します。
これを回避するには、配列を Fortran 連続順序で定義して、転置後に C 連続になるようにします。
A = np.array([some_func(d) for d in range(D)], order='F').T
A = normalize_logspace(A)
明らかに、これは非常にエラーが発生しやすく、ユーザーは配列が正しい順序になっていることに注意する必要があります。これは、ユーザーが Python で気にする必要のないことです。
行と列が連続する配列の両方でこれを機能させる最善の方法は何ですか? Cython でのある種の配列順序チェックが進むべき道だと思います。もちろん、データを新しい配列にコピーする必要のない解決策が望ましいと思いますが、それは必要だと思います。