API Showcase

From Eigen
Revision as of 14:12, 4 December 2008 by Bjacob (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Here are some examples of Eigen's fine API.

Performing row on a matrix

Suppose that you have a matrix m, a number alpha, and integers i and j, and you want to add alpha times the j-th row into the i-th row. You can do:

m.row(i) += alpha * m.row(j);

Here row() returns a "block inside a matrix" expression that can be used as a lvalue. This is only made possible in C++ by the technique of expression templates, used pervasively throughout Eigen. The great thing about the above code, is that it compiles to completely optimized assembly -- despite the abstraction! The arrays are traversed only once, no temporary is introduced. If the rows' size is fixed at compile time, Eigen will consider unrolling the loop if it is small enough. If vectorization is enabled, it will be successfully used.

Thus, as the user of Eigen, in most cases you can simply copy pseudocode from books and let Eigen handle the details.

The next great thing about Eigen's expressions, as opposed to fixed-function libraries such as BLAS, is that arbitrary expressions can be used. For example, if you also another number beta and another integer k, you can do:

m.row(i) += alpha * m.row(j) + beta * m.row(k);

Eigen will still optimize this completely, as above.

Operating on blocks inside a matrix or vector

Let m be a matrix. All the following operations are allowed by Eigen, with the self-explanatory effect. Here again, Eigen does its best to optimize everything for you, like traversing the arrays only once.

m.block(firstRow, firstCol, rows, cols).setZero();
m.corner(Eigen::TopLeft, rows, cols) = some_other_matrix;
m.block<2,2>(firstRow, firstCol).setIdentity(); // optimized variant when the # of rows, cols are known at compile-time

There are also vector-specific operations. Let v be a vector.

v.segment(first, size) = some_other_vector;
v.segment<3>(position1) = v.segment<3>(position2); // optimized variant when the size is known at compile-time
v.start(n).setConstant(12); // writes 12 in the n first coefficients of v
m.diagonal().end(n) *= lambda; // multiplies by lambda the n last diagonal coefficients of a matrix m

Computing sums

m.sum(); // returns the sum of all coefficients in m
m.block(firstRow, firstCol, rows, cols).sum();
m.rowwise().sum(); // returns a vector of the sums in each row


Like other libraries, Eigen has a comma-initializer allowing to construct a matrix like this:

Matrix3f m;
m << 1, 2, 3,
     4, 5, 6,
     7, 8, 9;

Unlike other libraries, Eigen's comma-initializer can be combined at will with expressions, which makes it very powerful. Here is a matrix being constructed by blocks:

Matrix4f m;
m << Matrix2f::Identity(),             Matrix2f::Zero(),
     (Matrix2f()<<1,2,3,4).finished(), Matrix2f::Identity();
/* The matrix m is now:
   1 0 0 0
   0 1 0 0
   1 2 1 0
   3 4 0 1

You can even use a comma-initializer to fill directly an expression. Here is how you would write 1,2,3 in the first row of a matrix:

Matrix3f m;
m.row(0) << 1,2,3;