Mapping array back to an existing Eigen matrix - c++

I want to map an array of double to an existing MatrixXd structure. So far I've managed to map the Eigen matrix to a simple array, but I can't find the way to do it back.
void foo(MatrixXd matrix, int n){
double arrayd = new double[n*n];
// map the input matrix to an array
Map<MatrixXd>(arrayd, n, n) = matrix;
//do something with the array
.......
// map array back to the existing matrix
}

I'm not sure what you want, but I'll try to explain.
You're mixing double and float in your code (a MatrixXf is a matrix where every entry is a float). I'll assume for the moment that this was unintentional amd that you want to use double everywhere; see below for if this was really your intention.
The instruction Map<MatrixXd>(arrayd, n, n) = matrix copies the entries of matrix into arrayd. It is equivalent to the loop
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
arrayd[i + j*n] = matrix(i, j);
To copy the entries of arrayd into matrix, you would use the inverse assignment: matrix = Map<MatrixXd>(arrayd, n, n).
However, usually the following technique is more useful:
void foo(MatrixXd matrix, int n) {
double* arrayd = matrix.data();
// do something with the array
}
Now arrayd points to the entries in the matrix and you can process it as any C++ array. The data is shared between matrix and arrayd, so you do not have to copy anything back at the end. Incidentally, you do not need to pass n to the function foo(), because it is stored in the matrix; use matrix.rows() and matrix.cols() to query its value.
If you do want to copy a MatrixXf to an array of doubles, then you need to include the cast explicitly. The syntax in Eigen for this is: Map<MatrixXd>(arrayd, n, n) = matrix.cast<double>() .

You do not need to do any reverse operation.
When using Eigen::Map you are mapping a raw array to an Eigen class.
This means that you can now read or write it using Eighen functions.
In case that you modify the mapped array the changes are already there. You can simply access the original array.
float buffer[16]; //a raw array of float
//let's map the array using an Eigen matrix
Eigen::Map<Eigen::Matrix4f> eigenMatrix(buffer);
//do something on the matrix
eigenMatrix = Eigen::Matrix4f::Identity();
//now buffer will contain the following values
//buffer = [1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1]

Related

C++: storing a matrix in a 1D array

I am very new to C++, but I have the task of translating a section of C++ code into python.
Going through the file, I found this section of code, which confuses me:
int n_a=(e.g 10)
int n_b=n_a-1;
int l_b[2*n_b];
int l_c[3*n_b];
int l_d[4*n_b];
for (int i=0; i<n_b; i++){
for (int j=0; j<2; j++) l_b[i*2+j]=0;
for (int j=0; j<3; j++) l_c[i*3+j]=0;
for (int j=0; j<4; j++) l_d[i*4+j]=0;
I know that it creates 3 arrays, the length of each defined by the action on the n_b variable, and sets all the elements to zero, but I do not understand what exactly this matrix is supposed to look like, e.g. if written on paper.
A common way to store a matrix with R rows and C columns is to store all elements in a vector of size R * C. Then when you need element (i, j) you just index the vector with i*C + j. This is not the only way your "matrix" could be stored in memory, but it is a common one.
In this code there are 3 C arrays that declared and initialized with zeros. The l_b array seems to be storage for a n_a x 2 matrix, the l_c array for a n_a x 3 matrix and the l_d array for a n_a x 4 matrix.
Of course, this is only an impression since to be sure we would need to see how these arrays are used later.
As in the comments, if you are going to convert this to python then you should probably use numpy for the matrices. In fact, the numpy arrays will store the elements in memory exactly like indexing I mentioned (by default, but you can also choose an alternative way passing an extra argument). You could do the same of this C++ code in oython with just
import numpy as np
n_a = (e.g 10)
l_b = np.zeros(shape=(n_a, 2))
l_c = np.zeros(shape=(n_a, 3))
l_d = np.zeros(shape=(n_a, 4))
These variables in numpy are 2D arrays and you can index them as usual.
Ex:
l_d[2, 1] = 15.5
We can also have a nice syntax for working with vector, matrices and linear algebra in C++ by using one of the available libraries. One such library is armadillo. We can create the three previous matrices of zeros using armadillo as
#include <armadillo>
int main(int argc, char *argv[]) {
unsigned int n_a = 10;
// A 10 x 3 matrix of doubles with all elements being zero
// The 'arma::fill::zeros' argument is optional and without it the matrix
// elements will not be initialized
arma::mat l_b(n_a, 2, arma::fill::zeros);
arma::mat l_c(n_a, 3, arma::fill::zeros);
arma::mat l_d(n_a, 4, arma::fill::zeros);
// We use parenthesis for index, since "[]" can only receive one element in C/C++
l_b(2, 1) = 15.5;
// A nice function for printing, but it also works with operator<<
l_b.print("The 'l_b' matrix is");
return 0;
}
If you inspect armadillo types in gdb you will see that it has a mem atribute which is a pointer. This is in fact a C array for the internal elements of the matrix and when you index the matrix in armadillo it will translate the indexes into the proper index in this internal 1D array.
You can print the elements in this internal arry in gdb. For instance, print l_b.mem[0] will print the first element, print l_b.mem[1] will print the second element, and so one.

Memcpy matrix to another matrix

I would like to copy the 2 matrices. With a copy element by element through 2 for loops (row and column), after several mathematical operations and copies the final result is correct while using "memcpy" the final result is wrong in the decimal places. The code is as follows.
double **L_original;
double **L;
int nF,nU;
L = new double*[nU]();
L_original = new double*[nU]();
for(int i=0; i<nU; i++){
L_original[i] = new double[nF]();
L[i] = new double[nF]();
}
// copy element to element
/*for(int i=0; i<nU; i++)
for(int j=0; j<nF; j++)
L[i][j] = L_original[i][j];*/
memcpy(L, L_original, sizeof(L_original));
This is the correct result:Matrix Correct
This is the output: output when using memcpy
your L and L_original are 2D matrices, made of an array of pointers to separately allocated 1D vectors. These memory addresses may not be in a contiguous memory space. So you can't use a single memcpy to copy all subvectors.
you will have to use a for loop to apply memcpy between each L[i] and L_original[i].
also, your sizeof() operator is used incorrectly. what you need to copy is the byte length of the data (of the 1D subvector), not the length of the pointer. You need something like
for(int i=0; i<nU; i++)
memcpy(L[i],L_original[i], sizeof(double)*nF);

C++ - A 3-d data structure - should I use vector of pointers or vector of vectors?

I have to maintain a data structure which is 3 dimensional. So let us say it's dimensions are :- l x m x n. In the program that I wish to write l and m will be known since the time the data structure is being constructed . But n has to be dynamic throughout runtime. And n may be different for the different vectors in the grid lxm. (Once this structure is created I never intend to destruct it as I will be needing it throughout).
For the moment let us assume it's a 2-dimensional data structure that I wish to make, should I make a vector<vector<int>> or a vector<vector<int>*> ? Also I know how I might initialise the vector to the required size in the first case, i.e I might do something like :-
vector<vector<int> > A(m)
to initialise the size of the outer dimension to m. But in the second case, once I have created a vector of pointers to vectors, how do I create the vectors to which the pointers point.
Carrying this to the 3-d case, should I use ,
a vector<vector<vector>> or a vector<vector<vector*>> or some other combination ?
Please, suggest any changes so that I may reframe the question if it's not framed properly.
You're better using a single vector (and not nested ones), since the memory is guaranteed to be contiguous in this case and your code will be way faster due to no cache misses. In this case, you need to map from 3D (2D) to 1D and vice-versa, but this is pretty straightforward
for 2D:
(x,y) <-> y*DIM_X + x;
for 3D:
(x,y,z) <-> z*(DIM_Y*DIM_X) + y*DIM_X + x;
If you really insist to use nested vectors, you can do something like:
#include <vector>
template<typename T>
using vec = std::vector<T>; // to save some typing
int main()
{
// creates a 5 x 4 x 3 vector of vector of vector
vec<vec<vec<double>>> v{5, vec<vec<double>>{4, vec<double>{3}}};
}
EDIT
Responding to your latest edit: use
std::vector<std::vector<double>> v{DIM_X*DIM_Y, std::vector<double>};
// address (x,y,z)
v[y*DIM_X+x, z] = val_x_y_z;
If you further happen to know the dimensions of the inner vectors, you can preallocate memory for them using std::vector::reserve. This will speed things up since there won't be any (slow) re-allocations.
No, use a proper multidimensional array: Boost MultiArray http://www.boost.org/doc/libs/1_59_0/libs/multi_array/doc/user.html
#include "boost/multi_array.hpp"
int main () {
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array<int, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
}

How do you fill with 0 a dynamic matrix, in C++?

How do you fill with 0 a dynamic matrix, in C++? I mean, without:
for(int i=0;i<n;i++)for(int j=0;j<n;j++)a[i][j]=0;
I need it in O(n), not O(n*m) or O(n^2).
Thanks.
For the specific case where your array is going to to be large and sparse and you want to zero it at allocation time then you can get some benefit from using calloc - on most platforms this will result in lazy allocation with zero pages, e.g.
int **a = malloc(n * sizeof(a[0]); // allocate row pointers
int *b = calloc(n * n, sizeof(b[0]); // allocate n x n array (zeroed)
a[0] = b; // initialise row pointers
for (int i = 1; i < n; ++i)
{
a[i] = a[i - 1] + n;
}
Note that this is, of course, premature optimisation. It is also C-style coding rather than C++. You should only use this optimisation if you have established that performance is a bottleneck in your application and there is no better solution.
From your code:
for(int i=0;i<n;i++)for(int j=0;j<n;j++)a[i][j]=0;
I assume, that your matrix is two dimensional array declared as either
int matrix[a][b];
or
int** matrix;
In first case, change this for loop to a single call to memset():
memset(matrix, 0, sizeof(int) * a * b);
In second case, you will to do it this way:
for(int n = 0; n < a; ++n)
memset(matrix[n], 0, sizeof(int) * b);
On most platforms, a call to memset() will be replaced with proper compiler intrinsic.
every nested loop is not considered as O(n2)
the following code is a O(n),
No 1
for(int i=0;i<n;i++)for(int j=0;j<n;j++)a[i][j]=0;
imagine that you had all of the cells in matrix a copied into a one dimentional flat array and set zero for all of its elements by just one loop, what would be the order then? ofcouse you will say thats a O(n)
No 2 for(int i=0;i<n*m;i++) b[i]=0;
Now lets compare them, No 2 with No 1, ask the following questions from yourselves :
Does this code traverse matrix a cells more than once?
If I can measure the time will there be a difference?
Both answers are NO.
Both codes are O(n), A multi-tier nested loop on a multi-dimentional array produces a O(n) order.

Speed gains: Converting 2D array to 1D array

I initially had a 2D array. The results were taking time to get back the results. So, I converted the 2D array into 1D array but still there is not much improvement in speed of my program.
Here is my code:
for( counter1=0; counter1< size ; ++counter1)
{
y=buffer[counter1];
x=buffer[counter1+1];
IndexEntries index= OneDTable[x*256+y];
SingleTableEntries NewNextState=NewSingleTable[Next*blocksize+index];
Next=NewNextState.Next_State;
if(NewNextState.accept[index.serialnumber]=='1' )
{
return 1;
}
}
In my code above: OneDTable is a 1D array generated from a 2D array of 256 * 256 elements.
NewSingleTable is a 1D array generated from a 2D array of blocksize* (Total Next Elements).
Actually , I was expecting large speed gains after converting into 1D arrays. Is this the right way to extract value from a 1D array or certain improvements can be done to the above code?
More Details:
Both 2D arrays are of structure type:
Structure type of IndexEntries consists of:
int
int
Structure type of NewSingleTable consists of:
int
vector<char>
You could gain something changing from a vector of vector to a plain vector. E.g. from:
std::vector<std::vector<my_struct>> table(total_rows,
std::vector<my_struct>(total_columns,
my_struct()));
// do something with table[row][column]...
to
std::vector<my_struct> table(total_rows * total_columns);
// do something with table[row * total_columns + column]...
This because a vector of vector is not really a matrix and you lose data locality.
Changing from:
my_struct table[total_rows][total_columns];
to
my_struct table[total_rows * total_columns];
is worthless since the memory layout between the two is (usually) precisely the same.
The only difference is the semantic type of the array and the fact that you now have to implement the 2D element lookup yourself (of course changing from table[row * 256 + column] to table[row << 8 + column] is useless since any decent compiler will automatically perform this "optimization").
The 1D array could be a bit faster when you have to perform an operation on every element. This because of the simpler for loop:
for (unsigned row(0); row < total_rows; ++row)
for (unsigned column(0); column < total_columns; ++column)
// do something with table[row][column]
const unsigned stop(total_rows * total_columns);
for (unsigned i(0); i < stop; ++i)
// do something with table[i]
but this isn't your case.
As laune said in is comment, copying a NewSingleTable just to extract a couple of integers is bad:
SingleTableEntries NewNextState=NewSingleTable[Next*blocksize+index];
From your example it seems that a const reference should be enough:
...
const SingleTableEntries &NewNextState(NewSingleTable[Next * blocksize + index]);
if (NewNextState.accept[index.serialnumber] == '1' )
return 1;
Next = NewNextState.Next_State;
...