This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Applying user functions to columns/rows

Tags: None
(comma "," separated)
pandishar
Registered Member
Posts
10
Karma
0
As I understand it, we typically want to allow library functions to handle iterating over matrices/vectors. So, we rely on block operators, unaryExpr, colwise, and so on whenever possible. It's cleaner code, easier to write and maintain correctly, and faster. However, I can't find an analogue for the case when I need to apply a user function to rows or columns. So, my code looks like this:

Code: Select all
MatrixXd A;  //set size and fill
MatrixXd B; //set size

for(int i=0; i<A.cols(); ++i)
{
B.col(i) = userFn(A.col(i)); //this function maps VectorXd to VectorXd
}


We'll have to assume that I can't rewrite userFn as an entirely native Eigen matrix function. I'm hoping it could look like this:

Code: Select all
B = A.colwise(userFn);


Does such a construct exist in Eigen? Especially combined with lambdas in C++11, it seems like this would be a powerful and natural way of expressing some operations. Thanks!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
That does not exist yet, but sounds like a good idea. However please not that if your functions can be written using Eigen's API, then it's better to use Eigen directly instead of creating your own functor because then Eigen can take care of vectorization. Do you have some examples of custom functors you apply using unaryExpr or would like to apply column-wise?
pandishar
Registered Member
Posts
10
Karma
0
Once place I used this recently is if the columns are inputs to an external model. I was running a complex ocean simulation that's actually a complex standalone application. Then, say, we might take an svd. In some sense this isn't a great use of a matrix, as the first part isn't doing liner algebra. But eventually you have to form a matrix, which I think you'd do by looping at some stage.

More generally, I think this ties into how you want to support iteration over matrices. Writing fully vectorizable code is great, but sometimes tricky. I'm sure I'm not the only one who periodically uses for loops over rows, columns, or elements; either because I can't vectorize it or don't think it's simpler not to. (with the possibility of vectorizing if it turns out to be a performance bottleneck). I don't love the current syntax for iterating, because it's boilerplate and possible to confuse row and column indices/bounds. I saw some discussions of iterators for compatibility with the stl algorithms and such, which provides superior syntax in some cases (especially combined with range for in c++11 or boost), but obviously they haven't become standard.
Hauke
Registered Member
Posts
109
Karma
3
OS
I am not sure whether you are looking for something like this, but with modern compilers you can build this with a few lines of code on top of Eigen

Code: Select all
#include <Eigen/Eigen>

#include <iostream>

using namespace Eigen;

namespace Eigen
{
  template <typename Derived, typename Function>
  void for_each_col(DenseBase<Derived>& D, Function f)
  {
    for (Eigen::DenseIndex i = 0; i < D.cols(); ++i)
      f(D.col(i));
  }
}

int main(int argc, char** argv)
{
  const double x = -5000;
  ArrayXd v = ArrayXd::Constant(4, x);

  // if we don't take care, columns are copied
  for_each_col(v, [](VectorXd v)
  {
    std::cout << v.transpose() << std::endl;
  });

  // but the syntax even allows you to modify the columns
  for_each_col(v, [](ArrayXd::ColXpr& v)
  {
    v += 1;
  });

  std::cout << v.transpose() << std::endl;
}


HTH,
Hauke
pandishar
Registered Member
Posts
10
Karma
0
Thanks a lot - I didn't think of doing it that way. Not perfect, but a nice option to have.


Bookmarks



Who is online

Registered users: Baidu [Spider], Bing [Bot], Google [Bot], Yahoo [Bot]