簡體   English   中英

如何在MATLAB的mex c ++函數中循環遍歷矩陣元素?

[英]How to loop through matrix elements in mex c++ function for MATLAB?

我試圖索引為MATLAB編寫外部c ++函數使用mex來操作矩陣,並且我無法使用多維索引。 這里提供一些示例,但我還沒有找到如何解決下面描述的問題。 我有一個樣本矩陣:

>> mat
mat =
 1    10
 2    20
 3    30
 4    40
 5    50

目前我通過矩陣使用線性索引:

#include <mex.h>
#include <iostream>
using namespace std;
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{ 
 //1.get pointer to input graph_list and allocate it    
    double *graph_list = mxGetPr(prhs[0]);
    mwSize mrows = mxGetM(prhs[0]);
    mwSize ncols = mxGetN(prhs[0]);  
    cout<< mrows<<" rows\n";
    cout<< ncols<<" cols\n";
    int mm, nn;
    for (nn=0;nn<ncols;nn++) {
        for (mm=0;mm<mrows;mm++){
            cout << graph_list[nn*(mrows) +mm]  <<"\n";            
        }
    }     
}

這會產生:

>> mexTryAlex(mat)    
5 rows
2 cols
1
2
3
4
5
10
20
30
40
50

當我更改graph_list的定義並嘗試2D索引到graph_list時, mex會出現編譯錯誤:

double **graph_list = mxGetPr(prhs[0]);
cout << graph_list[nn][mm];

編輯:這是收到的錯誤消息

>> mex mexTryAlex.cpp
Warning: You are using gcc version "4.4.3-4ubuntu5)".  The version
     currently supported with MEX is "4.3.4".
     For a list of currently supported compilers see: 
     http://www.mathworks.com/support/compilers/current_release/
mexTryAlex.cpp: In function ‘void mexFunction(int, mxArray**, int, const mxArray**)’:
mexTryAlex.cpp:16: error: cannot convert ‘double*’ to ‘double**’ in initialization
mex: compile of ' "mexTryAlex.cpp"' failed.
??? Error using ==> mex at 208
Unable to complete successfully.

編譯器說明了一切。

在C中,2D數組就像一個數組數組。 因此,2D陣列與1D陣列根本不同; 它是一個指針數組,其中每個元素都包含一個指向數組的指針(因此是一個雙指針, double** )。

你要求mxGetPr()返回一個double** ,但是它返回一個double* ,例如指向一維數組的第一個元素的指針。 該1D陣列只能線性索引。

我的猜測是MATLAB以這種方式做到這一點,以保持索引數組的一致性 - 你真的希望/想要一個4-D數組的double****嗎?

而且, mxGetPr()不能通過返回類型重載(畢竟它是C)。

為了能夠對一維數組進行雙重索引,你可以潛入一個小宏:

#define A(i,j) A[(i) + (j)*numrows]

並像這樣使用它

double *A = mxGetPr(...);
int numrows = 4;   /* or get with mxGetM() or so) */

double blah = A(3,2); /* call to MACRO */

顯然,與所有宏一樣,需要注意以下幾點:

  1. 沒有界限檢查
  2. C基於0,基於Matlab 1,使所有索引不同
  3. 所有陣列都必須被稱為'A'

您可以編寫一個函數來緩解這些缺點:

double getValue(double** array, int row, int* dims);

(或使用Shai指出的mxCalcSingleSubscript ),但這並沒有真正提高表達能力恕我直言:

double blah = getValue(array, 3,4, dims);
/* or the ugliness from mxCalcSingleSubscript(); */

您也可以使用C ++編寫,使用operator()創建一個Matrix類型的類,使用mxGetPr()mxGetDims()等的指針和維度構造它,使用g++或同等程序在Matlab中編譯,但這會引入一個整體存在許多其他問題並且增加了大多數情況下所需的復雜性。

因此,為了避免所有這些混亂,我只是總是在原地計算索引:)

具有矩陣類是解決此類問題的最簡單方法。 有很多可供選擇,所以不要費心自己寫。 犰狳相當不錯,如果你使用它也可以與LAPACK集成。 http://arma.sourceforge.net/docs.html

見下面的例子

#include <mex.h>
#include <iostream>
#include <armadillo>
using namespace std;
using namespace arma;

//creates an armadillo matrix from a matlab matrix
mat armaMatrix(const mxArray *matlabMatrix[]){
    mwSize mrows = mxGetM(matlabMatrix[0]);
    mwSize ncols = mxGetN(matlabMatrix[0]);
    double *values = mxGetPr(matlabMatrix[0]);

    return mat(values, nrows, ncols);
}

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) 
{
    mat graph_list = armaMatrix(prhs);

    //print the matrix
    cout << graph_list<<"\n";
    //print the first column
    cout << graph_list(span::all,0) <<"\n";
}

正如Rody所指出的, mxGetPr返回一個指向1D數組的指針。 因此,您不能將其視為C ++中的2D數組。
你可以做的是使用mxCalcSingleSubscript函數將ND下標轉換為單個1D索引。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM