2

I'm a beginner when it comes to Eigen. I have searched but not found an answer to this question.

I have a an array of double pointers, i.e. double** x which I have no control over. It comes in this format and there is nothing I can do about it. I want to construct an Eigen::VectorXd vec that use the same memory as pointed to by x.

In other words, I would like the following to hold true:

vec(i) == *(x[i]) for each i

and

&vec(i) == x[i] for each i

I hope this makes sense. How can I achieve this?

Thanks in advance!

DoubleTrouble
  • 902
  • 2
  • 7
  • 19

2 Answers2

1

You want to use a series of Eigen::Maps, but with one caveat: it's not &vec that equals x[i] but vec.data(). Here is a full example:

#include "Eigen/Core"
#include <iostream>

int main()
{
    int outerLength = 4;

    int *szPointer;
    double **dblPointer;

    szPointer = new int[outerLength];
    dblPointer = new double*[outerLength];

    for (int i = 0; i < outerLength; i++)
    {
        szPointer[i] = 3 + i;
        dblPointer[i] = new double[szPointer[i]];
    }

    for (int i = 0; i < outerLength; i++)
    {
        Eigen::Map<Eigen::VectorXd> mapThatActsLikeVector(dblPointer[i], szPointer[i]);
        mapThatActsLikeVector.setLinSpaced(0, 8);

        std::cout << "----------------------------------\n";
        std::cout << "Eigen Map :\t" << mapThatActsLikeVector.transpose() << "\n";
        std::cout << "dblPointer:\t" << dblPointer[i][0];
        for (int j = 1; j < szPointer[i]; j++)
        {
            std::cout << " " << dblPointer[i][j];
        }

        std::cout << "\n\nAddresses:\n";
        std::cout << "Eigen:\t" << mapThatActsLikeVector.data() << "\n";
        std::cout << "Raw  :\t" << dblPointer[i] << "\n\n";
    }

    for (int i = 0; i < outerLength; i++)
    {
        delete[] dblPointer[i];
    }
    delete[] dblPointer;
    delete[] szPointer;

    return 0;
}

which outputs something like:


Eigen Map : 0 4 8
dblPointer: 0 4 8

Addresses:
Eigen: 00622B00
Raw : 00622B00


Eigen Map : 0 2.66667 5.33333 8
dblPointer: 0 2.66667 5.33333 8

Addresses:
Eigen: 0061D218
Raw : 0061D218


Eigen Map : 0 2 4 6 8
dblPointer: 0 2 4 6 8

Addresses:
Eigen: 0061D240
Raw : 0061D240


Eigen Map : 0 1.6 3.2 4.8 6.4 8
dblPointer: 0 1.6 3.2 4.8 6.4 8

Addresses:
Eigen: 006204B0
Raw : 006204B0

If you wanted to use a single VectorXd-like object, see this question.

Community
  • 1
  • 1
Avi Ginsburg
  • 10,323
  • 3
  • 29
  • 56
  • Thanks for the answer and sorry for my late response. However, I think you misunderstood my question, or I wasn't clear enough. x in my post contains the pointers to the variables I need in my Eigen::VectorXd, i.e. they are not (necessarily) in contiguous memory. I want *x[0] to be the first value in vec, *x[1] the second, etc. – DoubleTrouble Mar 06 '16 at 22:33
  • It doesn't really matter anymore since I was hoping to use the Unsupported Levenerg Marquardt solver but it seems as it doesn't support Eigen::Maps anyways. However, I'm still very interested to know if my OP can be solved. – DoubleTrouble Mar 06 '16 at 22:36
0

Start with double **xarray which has nrow and ncol.

xarray = new double *[nrow];
    for (i = 0; i < nrow; i++)
        xarray[i] = new double[ncol];

Fill it with values.

Then create double *xtemparray which is a vector of dimension nrow * ncol.

xtemparray = new double [nrow*ncol];

Put the values from xarray into xtemparray.

for (i = 0; i < nrow; i++) {
    for (j = 0; j < ncol; j++)
        xtemparray[nrow*i + j] = xarray[i][j];
}

Declare the matrix.

MatrixXd xmatrix(nrow, ncol);

You can then map xtemparray into xmatrix.

xmatrix = Map<Matrix<double,Dynamic,Dynamic,RowMajor>>(xtemparray, nrow, ncol);

To map the matrix back to the temparray:

Map<MatrixXd>(xtemparray, xmatrix.rows(), xmatrix.cols()) = xmatrix;

Finally, you can convert the xtemparray to a post xarray.

for (i = 0; i < nrow; i++) {
    for (j = 0; j < ncol; j++)
        xpostarray[i][j] = xtemparray[nrow*i + j];
}
Gerry
  • 1
  • 1