C++ (Eigen) - Coefficientwise boolean between two differently sized vector - c++
Suppose I have two Eigen Arrays defined as
Array<float, 10, 1> a;
Array<float, 4, 1> b;
Now, I would like to get an Array of Array<bool, 10, 4> result; reading true for every one of the 10 entries of a where it is larger than every of the four entries of b. One way to achieve that I thought of was:
Array<float, 10, 1> a;
Array<float, 4, 1> b;
// ... fill the arrays
Array<bool, 10, 4> result = a.replicate(1 , 4) > (b.transpose()).replicate(10, 1);
In reality, the matrix dimensions are much larger though. This approach works, but I have two questions.
First: if I replace Array<bool, 10, 4> result = ... by auto result = ...,using the result is much slower for some reason (I use it after to do some calculations based on the outcome of the bool).
Second: While this works, I wonder if this is the most efficient approach as I don't know whether replicate requires copying. I could consider iterating over one of the two dimensions
Array<float, 10, 1> a;
Array<float, 4, 1> b;
// ... fill the arrays
Array<bool, 10, 4> result;
for(int i = 0; i < 4; i++){
result.col(i) = a > b(i, 0);
}
which would remove the necessity of using replicate at the cost of adding an iteration.
Any help is greatly appreciated!
EDIT:
Here's the chunk of code of interest. It gets called very often and so speedup is of great concern. Right now, this eats up 90% of the overall execution time. It is part of line intersection detection for thousands of lines. My approach was to write all the checks in matrix expressions to avoid iterating over all line pairs. To do that, I build a matrix with n rows for all n lines and m columns for all lines the other n lines could collide with. Then, the line intersection formula can be applied coefficientwise over the big matrices which I hope brings speedup.
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x1 = rays.col(0).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x2 = (rays.col(2) + rays.col(0)).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y1 = rays.col(1).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y2 = (rays.col(3) + rays.col(1)).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x3 = obstacles.col(0).transpose().replicate(num_rays*num_ships, 1);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x4 = obstacles.col(2).transpose().replicate(num_rays*num_ships, 1);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y3 = obstacles.col(1).transpose().replicate(num_rays*num_ships, 1);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y4 = obstacles.col(3).transpose().replicate(num_rays*num_ships, 1);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> t_den = (x1-x2)*(y3-y4) -(y1-y2)*(x3-x4);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> t = (x1-x3)*(y3-y4) -(y1-y3)*(x3-x4)/t_den;
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> u = ((x1-x3)*(y1-y2) - (y1-y3)*(x1-x2));
Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> col_r = 0 <= t && 0 <= u && u <= t_den;
t_rays = col_r.select(t, 1000).rowwise().minCoeff();
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x1_ = ship_b_boxs.col(0).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x2_ = (ship_b_boxs.col(2)).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y1_ = ship_b_boxs.col(1).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y2_ = (ship_b_boxs.col(3)).replicate(1, 4*obs.size());
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x3_ = x3(Eigen::seq(0, 4*num_ships-1), Eigen::all);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> x4_ = x4(Eigen::seq(0, 4*num_ships-1), Eigen::all);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y3_ = y3(Eigen::seq(0, 4*num_ships-1), Eigen::all);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> y4_ = y4(Eigen::seq(0, 4*num_ships-1), Eigen::all);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> t_den_ = (x1_-x2_)*(y3_-y4_) -(y1_-y2_)*(x3_-x4_);
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> t_ = (x1_-x3_)*(y3_-y4_) -(y1_-y3_)*(x3_-x4_)/t_den_;
Eigen::Array<float, Eigen::Dynamic, Eigen::Dynamic> u_ = ((x1_-x3_)*(y1_-y2_) - (y1_-y3_)*(x1_-x2_));
Eigen::Array<bool, Eigen::Dynamic, Eigen::Dynamic> col_s = (0 <= t_ && t_ <= 1 && 0 <= u_ && u_ <= t_den_).rowwise().maxCoeff();
with 85% taken by inlined'Eigen::Array::Array'. I can see that probably now all the temporary array constructions take a lot of time. However, storing these temporary variables is beneficial as they are used more than once. Is there any way to speed this up?
First: if I replace Array<bool, 10, 4> result = ... by auto result =
...,using the result is much slower for some reason (I use it after to
do some calculations based on the outcome of the bool).
As mentioned by #Homer512 in a comment, do not use auto in Eigen expressions
Second: While this works, I wonder if this is the most efficient
approach as I don't know whether replicate requires copying
No, if you use replicate within an expression and you do not actively store it in some intermediate variable or otherwise force the expression to be evaluated, there is no copying involved. As in typical Eigen style replicate only returns an expression of the replication, see the doc, an actual object containing a full replica is only created if absolutely necessary.
In short, this involves copies:
Array<bool, 10, 4> a4r = a.replicate(1 , 4);
Array<bool, 10, 4> b4r = b.transpose().replicate(10, 1);
Array<bool, 10, 4> result = a4r > b4r;
while your expression does not:
Array<bool, 10, 4> result = a.replicate(1 , 4) > b.transpose().replicate(10, 1);
So I really think it's the most efficient way to do it, or close to it.
How is this magic possible? It is well explained in the doc.
Side note:
if your matrices are big you should consider switching to dynamic size, see Eigen's own recommendations "Fixed vs. Dynamic size"
on the other hand, if you do know the sizes at compile time, you could consider the templeate version of replicate: a.replicate<1,4>() > b.transpose().replicate<10,1>();
If you still do not believe there is no copying involved, you can check the source code, as of version 3.4.0
Eigen/src/Core/Replicate.h
template<typename MatrixType,int RowFactor,int ColFactor> class Replicate
: public internal::dense_xpr_base< Replicate<MatrixType,RowFactor,ColFactor> >::type
{
[...]
template<typename OriginalMatrixType>
EIGEN_DEVICE_FUNC
inline Replicate(const OriginalMatrixType& matrix, Index rowFactor, Index colFactor)
: m_matrix(matrix), m_rowFactor(rowFactor), m_colFactor(colFactor)
{
EIGEN_STATIC_ASSERT((internal::is_same<typename internal::remove_const<MatrixType>::type,OriginalMatrixType>::value),
THE_MATRIX_OR_EXPRESSION_THAT_YOU_PASSED_DOES_NOT_HAVE_THE_EXPECTED_TYPE)
}
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
inline Index rows() const { return m_matrix.rows() * m_rowFactor.value(); }
EIGEN_DEVICE_FUNC EIGEN_CONSTEXPR
inline Index cols() const { return m_matrix.cols() * m_colFactor.value(); }
EIGEN_DEVICE_FUNC
const _MatrixTypeNested& nestedExpression() const
{
return m_matrix;
}
protected:
MatrixTypeNested m_matrix;
const internal::variable_if_dynamic<Index, RowFactor> m_rowFactor;
const internal::variable_if_dynamic<Index, ColFactor> m_colFactor;
};
Eigen/src/Core/DenseBase.h
const Replicate<Derived, Dynamic, Dynamic> replicate(Index rowFactor, Index colFactor) const
{
return Replicate<Derived, Dynamic, Dynamic>(derived(), rowFactor, colFactor);
}
Eigen/src/Core/CoreEvaluators.h
template<typename ArgType, int RowFactor, int ColFactor>
struct unary_evaluator<Replicate<ArgType, RowFactor, ColFactor> >
: evaluator_base<Replicate<ArgType, RowFactor, ColFactor> >
{
[...]
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
explicit unary_evaluator(const XprType& replicate)
: m_arg(replicate.nestedExpression()),
m_argImpl(m_arg),
m_rows(replicate.nestedExpression().rows()),
m_cols(replicate.nestedExpression().cols())
{}
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
CoeffReturnType coeff(Index row, Index col) const
{
// try to avoid using modulo; this is a pure optimization strategy
const Index actual_row = internal::traits<XprType>::RowsAtCompileTime==1 ? 0
: RowFactor==1 ? row
: row % m_rows.value();
const Index actual_col = internal::traits<XprType>::ColsAtCompileTime==1 ? 0
: ColFactor==1 ? col
: col % m_cols.value();
return m_argImpl.coeff(actual_row, actual_col);
}
[...]
protected:
const ArgTypeNested m_arg;
evaluator<ArgTypeNestedCleaned> m_argImpl;
const variable_if_dynamic<Index, ArgType::RowsAtCompileTime> m_rows;
const variable_if_dynamic<Index, ArgType::ColsAtCompileTime> m_cols;
};
I know that the code is heavy and difficult to interpret if you are not familiar with this kind of mechanisms, that's why I've removed all but the most relevant part. What you need to retain is this: replicate only creates an expression of type Replicate which simply stores a reference to the original object, the number of row copies, and the number of column copies; then, when you want to retrieve a coefficient from the expression, the evaluator computes the appropriate index in the original matrix using modulo and returns the corresponding element.
Related
Eigen: How to check if Matrix is invertible
I would like to generate a random invertible Matrix using Eigen, which fulfills these criteria: Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> res(M, N + 1); Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> y(M, 1); y.setRandom(); while (true) { res.setRandom(); Eigen::FullPivLU<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> lu(res.transpose() * res); if (lu.isInvertible()) { break; } } So res^T*res should be invertible, but i need a random res.
Your check isInvertible should work here. For a diagnostic, you can check the absolute value of the determinant or the condition number of your matrix. You should be able to use the determinant member function, see: https://eigen.tuxfamily.org/dox/classEigen_1_1MatrixBase.html#a7ad8f77004bb956b603bb43fd2e3c061
Write arbitrary Eigen object to row-major plain storage
I am writing a module to write data to a file which uses by convention only row-major storage. I would like my function to be able to allow both column-major and row-major Eigen objects as input. Currently I first use Eigen to copy a column-major object to a row-major object, before I write. My code works well for most cases, but for Eigen::VectorXi compiling fails with an assertion that I don't understand. How do I solve this? Can I avoid creating many cases? The code (writing is mimicked by outputting a std::vector): #include <vector> #include <iostream> #include <Eigen/Eigen> template <class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols> std::vector<T> write(const Eigen::Matrix<T,Rows,Cols,Options,MaxRows,MaxCols>& matrix) { std::vector<T> data(static_cast<size_t>(matrix.size())); if (matrix.IsRowMajor) { std::copy(matrix.data(), matrix.data()+matrix.size(), data.begin()); return data; } else { Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix; return write(tmp); } } int main() { Eigen::VectorXi matrix = Eigen::VectorXi::LinSpaced(10, 0, 9); std::vector<int> output = write(matrix); } The compilation error: In file included from test.cpp:3: In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Eigen:1: In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Dense:1: In file included from /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/Core:457: /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/PlainObjectBase.h:903:7: error: static_assert failed "INVALID_MATRIX_TEMPLATE_PARAMETERS" EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/util/StaticAssert.h:33:40: note: expanded from macro 'EIGEN_STATIC_ASSERT' #define EIGEN_STATIC_ASSERT(X,MSG) static_assert(X,#MSG); ^ ~ /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/PlainObjectBase.h:535:7: note: in instantiation of member function 'Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 1, -1, 1> >::_check_template_params' requested here _check_template_params(); ^ /usr/local/Cellar/eigen/3.3.7/include/eigen3/Eigen/src/Core/Matrix.h:377:9: note: in instantiation of function template specialization 'Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 1, -1, 1> >::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >' requested here : Base(other.derived()) ^ test.cpp:14:79: note: in instantiation of function template specialization 'Eigen::Matrix<int, -1, 1, 1, -1, 1>::Matrix<Eigen::Matrix<int, -1, 1, 0, -1, 1> >' requested here Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix; ^ test.cpp:23:31: note: in instantiation of function template specialization 'write<int, -1, 1, 0, -1, 1>' requested here std::vector<int> output = write(matrix); ^ 1 error generated.
Understanding the static assertion Unfortunately the assertion is really not self-explanatory and the only thing you can get from it is the hint, that something is wrong with your template parameters. If we look into Eigen's source code we find the following beginning on line 903: EIGEN_STATIC_ASSERT((EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) && EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) && ((RowsAtCompileTime == Dynamic) || (RowsAtCompileTime >= 0)) && ((ColsAtCompileTime == Dynamic) || (ColsAtCompileTime >= 0)) && ((MaxRowsAtCompileTime == Dynamic) || (MaxRowsAtCompileTime >= 0)) && ((MaxColsAtCompileTime == Dynamic) || (MaxColsAtCompileTime >= 0)) && (MaxRowsAtCompileTime == RowsAtCompileTime || RowsAtCompileTime==Dynamic) && (MaxColsAtCompileTime == ColsAtCompileTime || ColsAtCompileTime==Dynamic) && (Options & (DontAlign|RowMajor)) == Options), INVALID_MATRIX_TEMPLATE_PARAMETERS) Even though the compiler indicates that EIGEN_IMPLIES(MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1, (Options&RowMajor)==RowMajor) causes the error, the following line really does: EIGEN_IMPLIES(MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1, (Options&RowMajor)==0) Understanding what triggers the assertion You provide Eigen::VectorXi as an input for write. Eigen::VectorXi is really just a typedef for Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::ColMajor, Eigen::Dynamic, 1> Therefore the line Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix; in write expands to Eigen::Matrix<int, Eigen::Dynamic, 1, Eigen::RowMajor, Eigen::Dynamic, 1> tmp = matrix; which triggers the assertion, since a matrix with MaxColsAtCompileTime==1 and MaxRowsAtCompileTime!=1 must not be RowMajor. Solve your problem The problem now is that even though you can check if your input matrix is a vector, row-major or column-major, you cannot declare Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> if it is no legal to do so at compile-time (and it isn't due to the static assertion). You have the following options to make your code work: 1. if constexpr (C++17) C++17 offers a way for detecting at compile-time if a certain conditional branch will be taken or not. The downside of this approach (beside the requirement for a C++17 compiler) is that you can only test for constant expressions. In the concrete example this looks like this: template <class T, int Rows, int Cols, int Options, int MaxRows, int MaxCols> std::vector<T> write(const Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols>& matrix) { typedef Eigen::Matrix<T, Rows, Cols, Options, MaxRows, MaxCols> MatrixType; std::vector<T> data(static_cast<size_t>(matrix.size())); if constexpr (MatrixType::MaxRowsAtCompileTime == 1 || MatrixType::MaxColsAtCompileTime ==1 || (MatrixType::Options&Eigen::RowMajor) == Eigen::RowMajor) { std::copy(matrix.data(), matrix.data() + matrix.size(), data.begin()); return data; } else { Eigen::Matrix<T, Rows, Cols, Eigen::RowMajor, MaxRows, MaxCols> tmp = matrix; return write(tmp); } } 2. SFINAE You can dispatch the call to write at compile-time using SFINAE by using std::enable_if. The following example uses a slightly modified version of your original code but everything should be clear from context: // matrix is either a vector or in row-major template <typename Derived> std::vector<typename Derived::Scalar> write(const Eigen::MatrixBase<Derived>& matrix, typename std::enable_if<Derived::MaxRowsAtCompileTime == 1 || Derived::MaxColsAtCompileTime == 1 || (Derived::Options & Eigen::RowMajor) == Eigen::RowMajor, Derived>::type* = 0) { std::vector<typename Derived::Scalar> data( static_cast<size_t>(matrix.size())); std::copy(matrix.derived().data(), matrix.derived().data() + matrix.size(), data.begin()); return data; } // matrix is neither a vector nor in row-major template <typename Derived> std::vector<typename Derived::Scalar> write(const Eigen::MatrixBase<Derived>& matrix, typename std::enable_if<Derived::MaxRowsAtCompileTime != 1 && Derived::MaxColsAtCompileTime != 1 && (Derived::Options & Eigen::RowMajor) == 0, Derived>::type* = 0) { Eigen::Matrix<typename Derived::Scalar, Derived::RowsAtCompileTime, Derived::ColsAtCompileTime, Eigen::RowMajor, Derived::MaxRowsAtCompileTime, Derived::MaxColsAtCompileTime> tmp = matrix; return write(tmp); } This works using a C++11 compiler. Other options would be to specialise the template but it will get even more lengthy than the SFINAE approach. Some test cases: Eigen::Matrix<int, 3, 3, Eigen::RowMajor> m; m << 1, 2, 3, 1, 2, 3, 1, 2, 3; std::vector<int> output = write(m); for (const auto& element : output) { std::cout << element << " "; } Output: 1 2 3 1 2 3 1 2 3 Eigen::Matrix<int, 3, 3, Eigen::ColMajor> m; m << 1, 2, 3, 1, 2, 3, 1, 2, 3; std::vector<int> output = write(m); for (const auto& element : output) { std::cout << element << " "; } Output: 1 2 3 1 2 3 1 2 3 Eigen::VectorXi m = Eigen::VectorXi::LinSpaced(10, 0, 9); std::vector<int> output = write(m); for (const auto& element : output) { std::cout << element << " "; } Output: 0 1 2 3 4 5 6 7 8 9 Eigen::RowVectorXi m = Eigen::RowVectorXi::LinSpaced(10, 0, 9); std::vector<int> output = write(m); for (const auto& element : output) { std::cout << element << " "; } Output: 0 1 2 3 4 5 6 7 8 9
A simpler solution is to let Eigen::Ref does all the job for you: Ref<const Matrix<T,Rows,Cols,Cols==1?ColMajor:RowMajor,MaxRows,MaxCols>,0, InnerStride<1> > row_maj(matrix); Then row_maj will be guaranteed to be sequentially stored in row-major order. If matrix is compatible, then no copy occurs. No branch, no SFINAE, etc. Here matrix can be any expression, not only a Matrix<...> but also sub-matrices, Map, another Ref, etc. To handle any expressions, just replace Rows and the likes with XprType::RowsAtCompileTime where XprType is the type of matrix. template <class XprType> std::vector<typename XprType::Scalar> write(const Eigen::MatrixBase<XprType>& matrix) {...}
How to convert an std::vector to a matrix in Eigen?
I am somewhat new to Stack Overflow and C++ so feel free to correct any errors in my code and the formatting of this question. I am trying to make a linear regression calculator using the normal equation which involved the transposing of matrices and multiplication of vectors (and their inverses). The program is supposed to read from a csv file and pass the information from that file into a matrix and calculate the regression line. To make the job easier, I decided to use a library called Eigen for matrix-matrix multiplication. The problem that I have run into is that the Map function can only take in an array as opposed to a std::vector. This is what I have so far: float feature_data[] = { 1, 1, 1, 1, 1, 1, 2, 4.5, 3, 1,4, 5}; float labels[] = { 1, 4, 3, 2, 5, 7 }; //maps the array to a matrix called "feature_data" MatrixXf mFeatures = Map< Matrix<float, 6, 2> >(feature_data); MatrixXf mLabels = Map< Matrix<float, 6, 1> >(labels); //use the toArray function std::vector<float> test_vector = { 2,1,3 }; float* test_array = toArray(test_vector); calcLinReg(mFeatures, mLabels); const int n = 2; int arr[n]; system("pause"); For context, the toArray function is my unsuccessful attempt to make an array from a vector (in all honesty, it works but it returns a pointer which you can't pass into the Map function in Eigen.) calcLinReg does exactly what it sounds like: calculates the linear regression line parameters. Is there anyway I can convert a vector to an array or convert a 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.
Someone in a comment is asking for the case of dynamic numbers of rows and columns. This is possible, as follows: typedef Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic> MyMatrix; size_t nrow = ...; size_t ncol = ...; MyMatrix M = Eigen::Map<MyMatrix>(test_vector.data(), nrow, ncol);
Store pointer to Eigen Vector 'segment' without copy?
I have an Eigen Vector that I would like to refer to a segment at a later time (e.g. pass between functions) instead of modifying immediately. Eigen::Matrix<float, Eigen::Dynamic, 1> vec(10); // initialize vec << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10; I would like to create a pointer to a segment that I can refer to later. The following works but it creates a copy so any changes made to the segment are not reflected in the original vector. const int start = 2; const int end = 8 Eigen::Matrix<float, Eigen::Dynamic, 1> *block = new Eigen::Matrix<float, Eigen::Dynamic, 1>(end - start + 1, 1); *block = vec.segment(start-1,end-1); How can I keep a reference to the segment without copying?
You can use an Eigen::Map to wrap an existing segment of memory without copying. I'm not sure why you're allocating the *block object and not just using block. Using a Map it would look like Eigen::Map<Eigen::VectorXf> block(&vec(start - 1), end - start + 1); You then use the Map as you would a normal VectorXd, sans resizing and stuff. Simpler yet (at least according to #ggael), you can use an Eigen:Ref to refer to part of an Eigen object without inducing a copy. For example: void times2(Eigen::Ref< Eigen::VectorXf> rf) { rf *= 2.f; } int main() { Eigen::Matrix<float, Eigen::Dynamic, 1> vec(10); // initialize vec << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10; const int start = 2; const int end = 8; // This would work as well //Eigen::Map<Eigen::VectorXf> block(&vec(start - 1), end - start + 1); Eigen::Ref<Eigen::VectorXf> block = vec.segment(start, end - start + 1); std::cout << block << "\n\n"; times2(block); std::cout << vec << "\n"; return 0; } P.S. I think you're misusing the segment function. It takes a beginning position an the number of elements, i.e. (start, end-start+1).
Filter points inside of a sphere with Eigen
I have a set of 3D points, and I need to compute which ones are the nearest to a given point p. I am wondering which could be the correct way to do it in Eigen. So far, I have: Matrix<double, Dynamic, 3> points; // The set of 3D points Matrix<double, 1, 3> p; // Populate the "points" matrix ... // Fill a matrix with several copies of "p" in order to match the size of "points" Matrix<double, Dynamic, 3> pp(points.rows(), 3); pp = Matrix<double, Dynamic, 1>::Ones(points.rows, 1) * p; Matrix<double, Dynamic, 1> sq_distances = (points - pp).rowwise.squaredNorm(); Matrix<bool, Dynamic, 1> nearest_points = sq_distances < (dist_threshold * dist_threshold); Can I then have some way of extracting the points in "points" that fullfill the "nearest_points" condition like in Matrix<double, Dynamic, 3> nearest = points(nearest_points); ?
For the nearest I'd suggest: int i; double sqdist = (points.rowwise()-p).rowwise().squaredNorm().minCoeff(&i); nearest = points.row(i); For the ones in a given ball, you currently have to write one loop yourself: ArrayXd sqdists = (points.rowwise()-p).rowwise().squaredNorm(); Matrix<double,Dynamic,3> nearests( (sqdists<sqradius).count(), 3 ); int count = 0; for(int i=0; i<points.rows(); ++i) if(sqdists(i)<sqradius) nearests.row(count++) = points.row(i);