Access 2D array with 1D iteration - c++

If I define an array as follows:
int rows = 10;
int cols = 10;
double **mat;
mat = new double*[rows];
mat[0] = new double[rows*cols];
for(int r=1; r<10; r++)
mat[r] = &(mat[0][r*cols]);
How do I iterate over this array via 1-dimension?
E.g. I'd like to do the following:
mat[10] = 1;
to achieve the same thing as
mat[1][0] = 1;
Is there a way to dereference the double** array to do this?

With your definition of mat, you can do this:
double* v = mat[0]; 'use v a uni-dimensional vector
for(int i =0; i< rows* cols; i++) v[i] = 1;
Alternatively,if what you wanted was to define mat itself as a uni-dimensional vector and use it as bi-dimensional in a tricky way:
double mat[rows * cols];
#define MAT(i, j) mat[i*cols + j]
MAT(1, 0) = 1;
<=>
mat[10] = 1
now you have the options to span the matrix in one-dimension using mat or bi-dimension using the MAT macro

mat[row * cols + column]
where row is the row you want to access and column is the column you want to access.
Of course an iteration over the array would just involve some kind of loop (best suited would be for) and just applying the pattern every time.

Related

vector<vector<double>> to mxArray using memcpy

I have correlation matrix of a data and i want to use pca to transform them to uncorrelated set.
so i've decided to use matlab engine(c++ mex API) to perform the pca
my question is how to copy the matrix contents to mxArray efficiently
i used loops to allocate each element of matrix...on the other hand i've looked up for memcpy and it seems error prone.
although i've tested the following and it just copies the first column!
memcpy((double *)mxGetPr(T), &rho_mat[0][0], rows * sizeof(double));
what is the best way to copy the data (matrix -> mxArray and mxArray -> matrix) ?
void pca(vector<vector<double>>& rho_mat)
{
Engine *ep;
mxArray *T = NULL, *result = NULL;
if (!(ep = engOpen(""))) {
fprintf(stderr, "\nCan't start MATLAB engine\n");
return;
}
size_t rows = rho_mat.size();
size_t cols = rho_mat[0].size();
T = mxCreateDoubleMatrix(rows, cols, mxREAL);
double * buf = (double *)mxGetPr(T);
for (int i = 0; i<rows; i++) {
for (int j = 0; j<cols; j++) {
buf[i*(cols)+j] = rho_mat[i][j];
}
}
engPutVariable(ep, "T", T);
engEvalString(ep, "PC = pcacov(T);");
result = engGetVariable(ep, "PC");
}
Thanks
Regards
You can try using std::memcpy in a loop for each row.
for (int i = 0; i<rows; i++)
{
std::memcpy(buf + i*cols, &rho_mat[i][0], cols * sizeof(double));
}
Please note you have to use cols in you memcpy to ensure each row is copied. In your example, it might have been coincidental if your matrix was square.
You can refer to this answer on how to copy a 1-d vector using memcpy.
Edit:
To copy from 2-D array to 2-D vector(assuming vector is already of size rows*cols)
for (int i = 0; i<rows; i++)
{
std::memcpy(&rho_mat[i][0], buf + i*cols, cols * sizeof(double));
}
Please note the assumption made
OR
A much cleaner way would be to use std::assign or constructor to std::vector
if(rho_mat.size() == 0)
{
for (int i = 0; i<rows; i++)
{
rho_mat.push_back(vector<int>(buf + i*cols, buf + i*cols + cols));
//OR
//rho_mat.push_back(vector<int>());
//rho_mat[i].assign(buf + i*cols, buf + i*cols + cols);
}
}

return value of mxGetPr() -- equivalent looping

I am trying to implement a mexFunction() into "pure" C++ (OpenCV), but the returned value by mxGetPr() is not clear at all for me.
The following code is aimed to be implemented:
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int *D = new int[N*L];
// where N and L are dimensions (cols and rows) of matrix prhs[3]
// prhs[3] is a NxL matrix containing floating point value
for (int i=0; i<N*L; i++)
D[i] = mxGetPr(prhs[3])[i];
}
My question is, what kind of value is given by mxGetPr(prhs[3])[i] and mxGetPr(prhs[4])[i]? And how is it looping through matrix?
I tried to do something like this:
for (int i=0; i<l; i++)
{
for(int j=0; j<n; j++)
{
D[iCounter] = (int)d.at<uchar>(i,j);
iCounter++;
}
}
Looping through d matrix which is the same as input value prhs[3], but apparently it is not correct.
I guess the order/type of the returned value is not the same as in the original mexFunction.
EDIT
Now I have cv::Mat d; instead of prhs[3] and try to do the same as in mexfunction.
int *D = new int[N*L];
int iCounter = 0;
for (int i=0; i<L; i++)
{
for(int j=0; j<N; j++)
{
D[iCounter] = (int)d.at<uchar>(i,j);
iCounter++;
}
}
But here (int)d.at(i,j) returns value of the "d" matrix...where in the roiginal code a pointer was returned by mxGetPr().
mxGetPr returns a pointer of type double so you can access your data using pointer arithmetic. Also, you must remember that the pointer returned to you has the data in column-major order. This means that you must traverse your data row-wise instead of column-wise like in traditional C order.
In column-major order, you access location (i, j) with the following linear index:
j * rows + i
rows is the number of rows in your matrix, with i and j being the row and column you want to access. In row-major or C order, the way you access data is:
i * cols + j
Here cols is the number of columns in your matrix. I'm assuming you want to lay out your data in row-major format rather than column major. Therefore if you want to loop through the data using two for loops, do something like this:
double *ptr = mxGetPr(prhs[3]);
// A L x N matrix - L rows, N columns
for (int i = 0; i < L; i++)
{
for (int j = 0; j < N; j++)
{
D[i * N + j] = (int) ptr[j * L + i];
}
}
Here D is a pointer pointing to integer data. You have to cast the data in order to do this as the pointer to the data from MATLAB is already double. It's nasty but that's what you have to do. You can use D in row-major order so it's compatible with the rest of your code. I'm assuming that you are using MATLAB MEX as way of making pre-written C++ code to be interfaced with MATLAB.

Extract rows/columns from ** matrices in C/C++

I have a square matrix double **A
I know how to iterate through this matrix:
for (int i = 0; i < MATRIX_SIZE; i++) {
for (int j = 0; j < MATRIX_SIZE; j ++) {
int val = A[i][j];
printf("val: %d\n", val);
}
}
However, I'm wondering how I can assign an entire row or column to a variable given I have this ** matrix (The ** pointer to pointer nonsense is still a little confusing. I believe its saying a list of list of doubles).
To add a little more background, I'm trying to extract rows and columns so I can perform a cuda matrix multiplication. I see a lot of documentation online that uses one-dimensional vectors to represent matrices (i.e. double* A) However, I am getting confused with the **
A two-dimensional array of doubles (double **) can be looked at as a one-dimensional array of one-dimensional arrays of doubles.
double **arr; // properly initialized
for(int rowNumber = 0; rowNumber < MATRIX_SIZE; ++rowNumber)
{
double *row = arr[rowNumber];
// do something with this row
for(int colNumber = 0; colNumber < MATRIX_SIZE; ++colNumber)
{
double value = row[colNumber];
// do something with value
}
}
In the above example, row is a pointer to a contiguous row of values from the initial array. This works because a two dimensional array is usually allocated like this:
double **arr = new double*[ROW_COUNT];
for(int rowNumber = 0; rowNumber < ROW_COUNT; ++rowNumber)
{
arr[rowNumber] = new double[COL_COUNT];
}
Getting a pointer to a column in the matrix (like we did with row above) is not possible because the values in a column are not contiguous, only the values in each row are contiguous.
In C++, you can use std::array
std::array< std::array<int, MATRIX_SIZE>, MATRIX_SIZE> A;
std::array<int, MATRIX_SIZE> ith_row = A[i];
std::array<int, MATRIX_SIZE> &ith_row_ref = A[i];
A[i][j] is a type of int, but A[i] is a int pointer, so if you want get a row to a variable, you can do this:
for (int i = 0; i < MATRIX_SIZE; i ++) {
int* val = A[i];
for (int j = 0; j < MATRIX_SIZE; j ++) {
printf("%d\n", val[j]);
}
}
but you can't get a column to a variable.
You can assign rows to variables easily but you can't assign columns because of the way that memory is laid out.
You can think of double pointers like this.
The first pointer points to the item to give you the row.
I'm going to make a 3w 4c matrix to show you an example
Theoretical (How you should think about it in your head)
Your first double pointer
p
|
V 0 1 2 <-indexes
0 [p1]->[1,2,3]
1 [p2]->[0,2,3]
2 [p3]->[1,0,3]
3 [p4]->[1,2,0]
which corresponds to the matrix
1,2,3
0,2,1
1,0,3
1,2,0
So you can thinking about getting the 0 at index (1,0) as
int **p = //some place that holds the matrix;
int *row2 = p[1];
int value = p[0];
The reason why it's not as straightforward as declaring a two dimensional
array is because when get the double pointer, you're not sure of the layout of the memory. The numbers could be stored like this
p1 p3 p2 p4
| | | |
[123103021120...] <- //this is basically RAM or "memory"
and you would have no idea as the programmer.
I hope this cleared some things up!

Take off pads with OpenCV

I have to translate from Matlab to C this code:
% take off the pads
x = (1 + padSize) : (rows - pad8Size);
y = (1 + padSize) : (cols - padSize);
rpad=rpad(x,y);
1st and 2nd create 2 array, but I don t know how I have to delete it from rpad Mat object It can be something like(subtract every element)
for(int i=1+pad;i<=rows-pad;i++){
for(int j=1+pad;i<=cols-pad;j++){
subtract(rpad,x,rpad);
subtract(rpad,y,rpad);}}
Or something like(delete the external element)
int a=(rows-pad)-(1+pad);
int b=(cols-pad)-(1+pad);
rpad.create(img.rows - a,img.cols - b,original.type());
img.copyTo(rpad);
Try
cv::Rect roi(padSize, padSize, rpad.cols-2*padSize, rpad.rows-2*padSize);
cv::Mat result = rpad(roi);
And depending on whether you want continuous memory, you can choose to directly use result (discontinuous, usually okay for most OpenCV functions) or copy it to back to rpad (continuous)
Is it possible to multiply a Mat object with a bidimensional array? Imfft is obviously the Mat object
for (int i = 0; i < rows; i++){
for (int j = 0; j < cols; j++){
imfft=imfft*filter[i][j]
}
}

How to input values in a multidimensional array?

I have
main(){...
float **tree;
//How to set some values here for e.g. If I want tree to be a 15x2 array of some values?
reprVectorsTree *r1 = new reprVectorsTree(tree,8,2);
...}
reprVectorsTree(float **tree, int noOfReprVectors, int dimensions)
{.....
How to use malloc here so that I can set some data inside the tree array?
To allocate memory for tree, try something like:
float** tree;
tree = (float**)malloc(15 * sizeof(float*));
for(i = 0; i < 15; i++)
tree[i] = (float*)malloc(2 * sizeof(float));
Now you can set values:
for(i = 0; i < 15; i++)
for(j = 0; j < 2; j++)
tree[i][j] = 2;
Don't forget to free it later, although I don't understand why you are combining new and malloc together?
I guess it's the tree variable you want to allocate for.
You can do like this:
float **tree;
// Allocate 15 "arrays"
tree = new float*[15];
for (int i = 0; i < 15; i++)
{
// Allocate a new "array" of two floats
tree[i] = new float[2];
// Fill the newly allocated floats with "random" data
tree[i][0] = 1.0;
tree[i][1] = 2.0;
}
However, if it's possible I would recommend that you change the reprVectorsTree object to accept std::vector< std::vector< float > > instead.