Initialise Eigen::Vector with Std::Vector

Initialise Eigen::vector with std::vector

According to Eigen Doc, Vector is a typedef for Matrix, and the Matrix has a constructor with the following signature:

Matrix (const Scalar *data)

Constructs a fixed-sized matrix initialized with coefficients starting at data.

And vector reference defines the std::vector::data as:

std::vector::data

T* data();
const T* data() const;

Returns pointer to the underlying array serving as element storage.
The pointer is such that range [data(); data() + size()) is always a
valid range, even if the container is empty.

So, you could just pass the vector's data as a Vector3d constructor parameter:

Eigen::Vector3d v2(v1.data());

Also, as of Eigen 3.2.8, the constructor mentioned above defined as:

template<typename _Scalar, int _Rows, int _Cols, int _Options, int _MaxRows, int _MaxCols>
inline Matrix<_Scalar, _Rows, _Cols, _Options, _MaxRows, _MaxCols>
::Matrix(const Scalar *data)
{
this->_set_noalias(Eigen::Map<const Matrix>(data));
}

As you can see, it also uses Eigen::Map, as noted by @ggael and @gongzhitaao.

How to convert an std::vector to a matrix in Eigen?

How about trying to use the vectors data() method, which gives you access to the memory array used internally by the vector, like this:

    std::vector<float> test_vector = { 2,1,3 };
float* test_array = test_vector.data();
Eigen::MatrixXf test = Eigen::Map<Eigen::Matrix<float, 3, 1> >(test_array);

Or shorter:

    std::vector<float> test_vector = { 2,1,3 };
Eigen::MatrixXf test = Eigen::Map<Eigen::Matrix<float, 3, 1> >(test_vector.data());

Beware The asignment actually copies the data, therefore this is safe. However, you can also directly use the data of the vector like this

    std::vector<float> test_vector(3,2);
Eigen::Map<Eigen::Matrix<float, 3, 1> > dangerousVec (test_vector.data());

If vector goes out of scope the memory is deallocated and dangerousVec's data is dangeling.

std::vector to Eigen::VectorXf

Your code seems correct. No need to initialize ev(N), though. You can just write

Eigen::VectorXf ev = Eigen::VectorXf::Map(&v[0], N);

Eigen vector constructor initialization vs comma initialization

One advantage of the first version is that it will fail at compile time if you pass the wrong number of arguments, e.g. because you misstyped Vector2d as Vector3d.

Performance-wise, the compiler is able to optimize both the same. Checked it with GCC.

Eigen::Vector; Initialize Vector with Values of Eigen::Matrix3f in a function, bigger than 4 entries

For dynamically filling a big matrix at runtime you can't use the CommaInitializer (without abusing it). Just allocate a matrix large enough and set individual blocks:

Matrix<float, Dynamic, 6> Vges(2*views, 6);
for(int i=0; i<views; ++i) {
Matrix<float, 2, 6> foo;
foo << 1,2,3,4,5,6,7,8,9,10,11,12; // or combine from two Matrix<float, 1, 6>

Vges.middleRows<2>(2*i) = foo;
}

You may also consider computing Vges.transpose() * Vges on-the-fly (i.e., by accumulating foo.transpose()*foo into a 6x6 matrix and do a SelfAdjointEigendecomposition instead of a SVD (perhaps use double instead of single precision then).

Eigen::Matrix<double, 6, 6> VtV; VtV.setZero();

for(int i=0; i<views; ++i) {
foo = ...;
VtV.selfadjointView<Upper>().rankUpdate(foo);
}

Eigen library -- initialize matrix with data from file or existing std::vectorstring content (c++)

The following code works with files containing matrices of arbitrary size:

#include <iostream>
#include <fstream>
#include <string>
#include <Eigen/Dense>

using namespace std;
using namespace Eigen;

#define MAXBUFSIZE ((int) 1e6)

MatrixXd readMatrix(const char *filename)
{
int cols = 0, rows = 0;
double buff[MAXBUFSIZE];

// Read numbers from file into buffer.
ifstream infile;
infile.open(filename);
while (! infile.eof())
{
string line;
getline(infile, line);

int temp_cols = 0;
stringstream stream(line);
while(! stream.eof())
stream >> buff[cols*rows+temp_cols++];

if (temp_cols == 0)
continue;

if (cols == 0)
cols = temp_cols;

rows++;
}

infile.close();

rows--;

// Populate matrix with numbers.
MatrixXd result(rows,cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
result(i,j) = buff[ cols*i+j ];

return result;
};

Regards.

Error storing data from std::Vector to Eigen::Vector

You can only use the constructor to initialize a vector that was not previously declared.
In this case, the Eigen vectors are already declared in the header file.

Eigen::Map() can be used to copy the data from the std::vector<double> to the Eigen::VectorXd, like this:

currentStartMassVector_ = Eigen::Map<Eigen::VectorXd>(StartMassVector_.data(),StartMassVector_.size()) ;

Initialize an Eigen::MatrixXd from a 2d std::vector

Sure thing. You can't do the entire matrix at once, because vector<vector> stores single rows in contiguous memory, but successive rows may not be contiguous. But you don't need to assign all elements of a row:

std::vector<std::vector<double> > data;
MatrixXd mat(10, 4);
for (int i = 0; i < 10; i++)
mat.row(i) = VectorXd::Map(&data[i][0],data[i].size());

Efficient way to initialize Eigen Matrix or Vector with random numbers from a specific range?

First of all, initializing (seeding) a default_random_engine with one number of a Mersenne-twister does not really make sense. If the simple random engine is good enough, directly seed it with time(0) or whatever you prefer. If you need longer sequences of truly independent pseudo-random numbers, directly pass the mt19937 object to your distribution.

Also, you are not using the high argument of your operator(), so you should actually use a NullaryExpr. Also, you can make dis a member variable, and probably better store a reference to the generator instead of making it a global variable:

template<typename Scalar>
struct RandomRange {
RandomRange(const Scalar& low, const Scalar& high,
std::default_random_engine &gen) : dis(low, high), gen(gen) {}
const Scalar operator()() const { return dis(gen); }
mutable std::uniform_int_distribution<> dis;
std::default_random_engine &gen;
};

And call it like:

std::default_random_engine gen(time(0));
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,RandomRange<int>(5,100, gen));

or

std::default_random_engine gen(time(0));
RandomRange<int> uniform(5,100, gen)
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10, uniform);

With C++11 you can also just define your distribution locally and call it using a lambda expression:

std::default_random_engine gen(time(0));
std::uniform_int_distribution<> dis(5,100);
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,[&](){ return dis(gen); });

Or

std::default_random_engine gen(time(0));
std::uniform_int_distribution<> dis(5,100);
auto uni = [&](){ return dis(gen); };
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,uni);

Or

std::default_random_engine gen(time(0));
Eigen::VectorXi testVec = Eigen::VectorXi::NullaryExpr(10,[&gen](){
std::uniform_int_distribution<> dis(5,100);
return dis(gen);
});

Some godbolt compilation examples: https://godbolt.org/z/uG0j__

Unless you find that this is a bottle-neck, I would not care too early about what variant is most performant (with proper optimization they should all be equivalent), but use whatever variant is most easy to read and maintain inside your code base.



Related Topics



Leave a reply



Submit