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!
Related
I'm taking a c++ programming course (we are still mostly using C) and we just got to dynamic allocation of memory. For one of my homeworks, I'm asked to create a function that transposes any given matrix. This function is given the following arguments as inputs: a pointer, in which are saved the matrix elements, the number of rows and of colunms. I would like this to be a void type function that changes the order of the stored elements without returning any new pointer.
I tried creating a new pointer, in which I save the elemtens in the correct order (using 2 for loops). Then what I would like to do is deallocating the original pointer (using the delete command), assinging it to the new pointer and finally deleting the new pointer.
This unfortunately does not work (some elements turn out to be random numbers), but I don't understand why.
I hope my code is more precise and clear than my explanation:
void Traspose(float *matrix, const int rows, const int cols ){
auto *tras = new float [rows * cols];
int k = 0;
for(int i = 0; i < cols; i++){
for(int j = 0; j < rows * cols; j += cols){
tras[k] = matrix[j + i];
k++;
}
}
delete[] matrix;
matrix = tras;
delete[] tras;
}
All those lines are wrong:
delete[] matrix;
matrix = tras;
delete[] tras;
You didn't allocate matrix so you don't want do delete it.
You assign tras to matrix and then you delete tras, after that, tras points nowhere, nor does matrix.
matrix = tras is pointless anyway, because matrix is a local variable, and any changes to local variables are lost after the function ends.
You're inventing a problem where none should exist.
A matrix AxB in dimension will transpose to a matrix BxA in size. While the dimensional difference is obvious the storage requirements might not be so. Your storage is identical.
Per the function signature, the change must be done in the same memory allocated to matrix. E.g., the results should be stored back into matrix memory. So, don't delete that memory; leave it alone. It is both large enough to hold the transposition, and owned by the caller regardless.
Rather, do this:
void Traspose(float *matrix, const int rows, const int cols)
{
float *tras = new float[ rows * cols ];
int k = 0;
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows * cols; j += cols)
tras[k++] = matrix[j + i];
}
for (int i=0; i<k; ++i)
matrix[i] = tras[i];
delete [] tras;
}
Note this gets quite a bit simpler (and safer) if the option to use the standard library algorithms and containers is on the table:
void Traspose(float *matrix, const int rows, const int cols)
{
std::vector<float> tras;
tras.reserve(rows*cols);
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows * cols; j += cols)
tras.emplace_back(matrix[j + i]);
}
std::copy(tras.begin(), tras.end(), matrix);
}
Finally, probably worth investigating in your spare time, there are algorithms to do this, even for non-square matrices, in place without temporary storage using permutation chains. I'll leave researching those as an exercise to the OP.
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.
I have declared a 2D array in the following way (please note that I'm very beginner!)
double **A=new double*[10];
for(int i=0;i<10;i++)
A[i]=new double[5];
So I guess this already defines a matrix of size 10 by 5.
I know that to refer to its row I can use
A[i]
But the question is, how to refer to a column of A? something like A[][i]?
You cannot access a column directly.
You can either access a row by A[i] (which is an array itself) or an element A[i][j] (which is a single double in your case).
If you want to get a column you have to iterate throw the array
for(unsigned int i = 0; i < 10; i++)
{
A[i][2] // do something
}
Accesses the third column.
So it is useful to think about if you want to create a 10x5 or a 5x10 matrix. If you often need to work with just a row or an column, it may be a good idea to invert the array layout (here switch columns and rows)
EDIT:
Here is some simplified explanation:
Imagine the following code
int** A = new int*[2];
for(int i=0;i<2;i++)
A[i]=new int[3];
// more init code
Then the array in memory may look like this:
So it is simple to see that the "blue row" can be accessed directly as you have its startaddress in A[0]
But if you want every third element of the sub arrays you have to iterate through A and add 2 to every startadress. Especially as there is no guaranteed fixed distance in memory between the subarrays if you use heap memory via "new".
But you often can speedup computations by choosing the layout of your arrays in a good way. One could for example store the second matrix transposed when implementing matrix multiplication.
Enother way using pointers.
// Matrix dimentions
int n_rows = 10;
int n_cols = 5;
// create rows as pointers to columns
double **A = new double*[n_rows];
// create columns
for (int i = 0; i < n_rows; i++)
{
A[i] = new double[n_cols];
}
// Fill our matrix
int count=0;
for (int i = 0; i < n_rows; i++)
{
for (int j = 0; j < n_cols; j++)
{
A[i][j]=count;
++count;
}
}
// Create pointers columns
double ***A_t = new double**[n_cols];
// create matrix pointers rows
for (int i = 0; i < n_cols; i++)
{
A_t[i] = new double*[n_rows];
}
// And fill it with pointers to transposed main matrix elements
for (int i = 0; i < n_rows; i++)
{
for (int j = 0; j < n_cols; j++)
{
A_t[j][i]=&A[i][j];
}
}
// output first row/column for each case
for (int i = 0; i < n_cols; i++)
{
cout << *(A[0]+i) << endl;
}
cout << "-------------"<< endl;
for (int i = 0; i < n_rows; i++)
{
cout << **(A_t[0]+i) << endl;
}
// Work with matrices here
// Don't forget to clean everything.
A 2D array looks something like this
if ur 2d array is a[i][j]
then i will be ur rows and j will be ur columns.
if u want to access columns of first row you can do something like this
a[0][1] a[0][2] a[0][3]
see the link it will clear you more.
http://i.stack.imgur.com/21Bqr.png
Rows and columns are sort of abstracted away, you can consider the spatial orientation to go in either direction if you want (10 columns, or 5 columns if you see what I mean). But obviously you need to keep your use consistent.
It probably makes sense to keep the 'outer' array the column, so that A[x][y] makes sense in a cartesian coordinate type sense. From your example, you want to be indexing like A[i][] (i.e. your i index is the column, or X coordinate).
You cannot refer to a column in this way. This is because you dont really have a matrix, you specified an array of arrays. The arrays are your rows, but the columns are not directly stored. If you want to get a whole column, you have to run through all rows, receive the value stored in that column and store it in a different array.
auto column = new double[10];
for(int i = 0; i < 10; i++){
column[i] = A[i][2] //if you want to get the 2nd column
}
Elements of any row can be referred by arr[row_num][i].
Similarly elements of any column can be referred by arr[i][col_num].
Note that indexes are zero-based in C/C++. So if your column/row size is x, i can vary from 0 to x-1.
As you are a beginner, i would also like to tell you a bit more about arrays in C/C++. Firstly, i would suggest you to read about pointers if you are not familiar with them.
When you declare an array, say, int arr[10], arr[0] means the first element. Also, arr + 0 (or simply arr) means the address of the first element. Similarly, arr[i] means ith element, arr + i means address of the ith element. To print the value at an address, in c/c++, you can use value-at operator, represented by (*), e.g. *(arr + i) will be equivalent to arr[i], i.e. the ith element. Also, address of operator (&) gives to the address of an element, &arr[i] is equivalent to (arr + i).
If arr is a 2-d array, arr[i][j] means jth element of ith row. arr[i] means address of first element of ith row. c/c++ are row-major, which means first row is filled first and then second and so on. and we have to specify the row size always while declaring a 2-d array.
Note: In pointer-arithmetic, arr+i, and arr+i+1, etc. are not being incremented by 1, but by the size of the element it is pointing to.
So, to refer to a row, we can do the following:
//note that arr[row_num] is an address
int * new_1d_arr = arr[row_num];
for(int i = 0; i < row_size; i++)
cout << new_1d_arr[i] << endl;
Similarly, we can also refer to an column, but it would be a bit more complex, as we will have to increment i, not by 1, but by the row_size, due to the fact that arrays in c/c++ are row-major, and we would have to skip over number of elements (equal to row_size) to get to the next element in the same column.
I had been trying to allocate dynamic memory for a two-dimensional array. After searchin a lot I've found a code that looks easier than others still I'm unable to understand each and every detail of it. Can someone explain me how does the following code assigns memory to the array dynamically. Really looking forward for help and sorry but I'm new to C++ and want to learn it.
void main()
{
int m,n;
cin>>m;
cin>>n;
//Allocate
int *a = new int[m*n];
//Use a[m][n]
for( int i = 0 ; i < m ; i++)
for ( int j = 0 ; j < n ; j++)
a[i*n + j] = 1;
}
The code just uses a single memory block to represent all elements, so to access a sample ( i, j ) it needs to calculate the index being i * num_rows + j (or num_colums depending how you look at it).
But as commented, don't use new int...., use something like
std::vector< int > a( m * n );
First of all, what you're doing, is adding 1 to different slots of a ONE-dimensional array.
Here's a commented version of your code:
int *a = new int[m*n]; // declares a pointer a, that points to a newly
// allocated space on the heap, for an array of size m*n.
for( int i = 0 ; i < m ; i++) // loop through m number of times
for ( int j = 0 ; j < n ; j++) // loop through n number of times PER m
a[i*n + j] = 1; // assigns 1 to a spot [i*n + j]
THIS is how you make a dynamic 2D array (in other words, array of pointers to arrays):
const int sizeX = 10;
const int sizeY = 5;
int** arrayOfPointers = new int*[sizeX];
for(int i = 0; i < sizeX; i++)
arrayOfPointers[i] = new int[sizeY];
Then, you can add multiple elements to that array using a double loop (NOT TESTED):
for(int i = 0 ; i < sizeY ; i++) // loop through all the rows
for (int j = 0 ; j < sizeX ; j++) // loop through all columns for row i
arrayOfPointers[i][j] = i*j; // assigns i*j to a spot at row i, column j
This is how you can print out the contents of the 2D array:
for(int i = 0 ; i < sizeY ; i++) {
for (int j = 0 ; j < sizeX ; j++)
cout << arrayOfPointers[i][j];
cout << endl; // go to the next line when the row is finished
}
First, let me point out that this is not a two-dimensional array, but rather a one-dimensional one. You can see that int* a = new int[ m*n ] allocates an array for integers of size m*n.
To obtain a two-dimensional array, you might use int** a = new int*[m]. Note the two asterisks (*) that are used here. Having allocated the "first" dimension of the array, you now have to allocate the second one via:
for( int i = 0; i < m; i++ )
{
a[i] = new int[n];
}
Afterwards, you can loop over m and n and use a[i][j] to access the array contents.
Using the STL in C++, you can obtain two-dimensional arrays by using a two-dimensional vector, like so:
std::vector< std::vector<int> > array( rows,
std::vector<int>( columns ) );
This would allocate a two-dimensional vector containing integers, with rows elements in the first dimension and columns elements in the second dimension. Such use is sometimes frowned upon, but std::vector manages memory for your, which might be nice.
Despite what Paul R said and which I fully support, the comment in the code above is wrong, you cannot use a[m][n] for proper addressing of an array that has been allocated as one dimensional memory.
what you can do, if you really must work without using C++ standard containers like vector or array is to allocate the full block and then store addresses to the start of the rows
int** createTwoDimMatrix(unsinged int rows, unsigned int columns)
{
int** rowAdressTable = new int*[rows];
int* baseMemory = new int[rows*columns];
//fill the rowAddressTable
for(unsinged int r=1; r<rows; ++r)
{
rowAdressTable[r] = rowsAdressTable[r-1]+columns*sizeof(int)
}
return rowAdressTable;
}
But let me repeat: Please, consider using C++ containers
For the memory it doesn't matter what kind of arrays you have they are all stored as one block of memory, those can the visualised as an 1d array.
In this example, since you want to cave an m x n array you alocate a block of m*n size. The difference between this way and the others is that now you have to acess your array as 1d.
For exemple having the follwoing 2d array:
1 2 3
4 5 6
7 8 9
It will be stored in the memory as follows:
1 2 3 4 5 6 7 8 9
I think you can see the pattern: in order to acces a[i][j] from your 2d array, the 1d equivalent would be a[i*dim+j] where dim is the length of your row.
The way you access your array depends solely on the way you allocate it. In order to be able to acces you elements directly as arr[i][j] you have to allocate the memory ass follows:
int **arr = new int *[n];
for (int i=0; i<n; i++)
arr[i] = new int [m];
This will create an nxm array.
Dynamic is like
int *p = new int [10][10]
then *(p+(i*noofcols)+j) gives value
I was wondering if there is a clever way of presenting the information in a vector as a 1D array. Example:
Let's create a vector of vectors of 5x3 int elements
vector< vector<int>> iVector;
ivector.resize( 5 );
for(i = 0; i < 5; i++){
iVector[i].resize(3);
}
But now I want this structure to be converted into a 1D array:
int* myArray = new int[5*3];
So I could access each element which I want as follows:
for (i =0;i < 5; i++)
for(j =0; j< 3; j++)
myArray[i*3+j] = ...
I know I could just copy the vector to the array element by element, but I was wondering if there is a method that directly addresses the vector to array conversion. I also know that the vector can me addressed as iVector[i][j] , but unfortunately it needs to be an array as it will be sent to a GPU and GPUs dont understand vectors.
Just use std::copy 5 times.
int* ptrArray = myArray;
for (i =0;i < 5; i++) {
std::copy(iVector[i].begin(), iVector[i].end(), ptrArray);
ptrArray += iVector[i].size();
}
There's really nothing you can do here except copy it into an array. The GPU will not understand any abstraction you create any more than it can understand std::vector. All you can do is make an array and copy it over.
Vectors supposed to store the elements in a linear fashion, so in theory you can refer to the entire underlying vector (only a single vector):
std::vector<int> numbers;
int data[4] = &(numbers[0]);
Similarily, perhaps you can try the same approach for the 2D version.
However in your place I would consider to use a class that is specifically designed to handle matrices (it is easy to write one similar to std::vector().
Or you can use plain old C.
You first initialize the array size to be the number of rows * the number of columns your vector of vectors has. Then you use memcpy to copy each vector to the array.
vector<vector<int> > v = { {1,2},{3,4},{5,6} }; //v is 3 by 2 matrix
int *arr = (int*)malloc( (3*2) * sizeof(int)); // arr has size 3*2 = 6
for (int i = 0; i < 3; i++)
memcpy(arr + v[i].size() * i, &(v[i][0]), v[i].size() * sizeof(int));
Here's a function that I wrote that does this for you:
template<typename T>
T *vectorToArray(vector<vector<T> > const &v) {
T *rv = (T*)malloc((v.size()*v[0].size()) * sizeof(T)); //Assuming all rows have the same size
for (unsigned i = 0; i < v.size(); i++)
memcpy(rv + v[i].size() * i, &(v[i][0]), v[i].size() * sizeof(T));
return rv;
}
So now you can do something like this:
vector<vector<int> > v = { {1,2},{3,4},{5,6} }; //v is 3 by 2 matrix
int *arr = vectorToArray(v);
I hope this helps