Eigenメモ

1.インストール
ヘッダの入ったディレクトリをg++の標準検索パスに入れるだけ

$ wget http://bitbucket.org/eigen/eigen/get/3.2.5.tar.gz ./tmp
$ cd tmp
$ tar xvzf 3.2.5.tar.gz
$ sudo cp -r eigen-*/Eigen /usr/local/include/

2.使い方のメモ
チュートリアルEigen: Main Pageのよく使う例だけメモ.

#include <iostream>
#include <vector>
#include <Eigen/Dense>

using namespace Eigen;
using namespace std;
int main()
{
  // constructor
  Matrix2d m1;      // 2x2 uninitialized matrix
  MatrixXd m2(2,2); // 2x2 uninitialized matrix
  Vector3d v1,v2;

  // coefficent accessor
  m1(0,0) = 1;   // m1 = 1 0
  m1(0,1) = 0;   //      0 1
  m1(1,0) = 0;   //      
  m1(1,1) = 1;   //
  v1(0)=1, v1(1)=2, v1(2);

  // comma initialization
  m2 << 1,0,
        0,1;
  v2 << 2,1,0;

  // resize --CAUTION-- resize initialize matrix !!
  cout << "m2" << endl << m2 << endl;
  m2.resize(3,3);
  cout << "m2 row size=" << m2.rows() << endl;
  cout << "m2 col size=" << m2.cols() << endl;
  m2(0,2)=0, m2(1,2)=0, m2(2,0)=0, m2(2,1)=0, m2(2,2)=1;
  
  // Frequently used expression/operator
  m1.transpose();
  m1.sum();
  m1.prod();
  m1.mean();
  m1.minCoeff();
  m1.maxCoeff();
  m1.trace();
  v1.dot(v2);      // dot product
  v1.cross(v2);    // cross product
  
  // partially access
  m2.block(0,0,2,2); // block of size(p,q) starting at(i,j)
  m2.row(0);         // ith row
  m2.col(0);         // jth column
  
  // Array operator
  ArrayXXd a = m1.array();
  (a > 0).all();
  (a > 0).any();

  // array -> Eigen::Matrix
  // Map<Matrix <type, rowSize, colSize>> (*array_pointer)
  int arr[8];
  for (int i=0; i<8; ++i) arr[i] = i;
  cout << "Column-major:\n" << Map<Matrix<int, 2, 4> >(arr) << endl;
  cout << "Row-major:\n" << Map<Matrix<int, 2, 4,RowMajor> >(arr) << endl;
  MatrixXi m3 = Map<Matrix<int, 2, 4> >(arr);
  m3(0,0) = 10;
  cout << "arr[0]=" << arr[0] << endl;
  cout << "m3(0,0)=" << m3(0,0) << endl;

  // vector -> Eigen::Matrix
  vector<int> v(8);
  for (int i=0; i<8; ++i) v[i] = i;
  cout << "Column-major:\n" << Map<Matrix<int, 2, 4> >(v.data()) << endl;

  return 0;
}

3.覚えておくこと

  • Matrix3dはMatrixをtypedefしているだけ.Vector3dも同様にMatrixをtypedefしている.
  • 実行時にサイズを動的に変える場合にはDynamicで宣言する,またはXを指定.Matrix(double, Dynamic, Dynamic),またはMatrixXd.

*Matrix3dのdはdoubleのd.dynamicのdじゃない.*

  • Fixedサイズを使うと高速化が図られる可能性があるが,実際はサイズが32以上だと差は殆ど無い.よって,サイズが32程度の固定サイズを除いて,いつもDyanamicを使う.
  • 計算はコンパイル時点で最適化される.例えば行列の掛け算などは掛け算の順序で計算量が異なる.または,ベクトルの計算をいちいち全て独立にやるのではなく,一つのループで回す.

 (これはどうやって実現しているの?C++Lispみたいなマクロか遅延評価の仕組みってあったかな?)

  • 最小値,最大値や平均も基本演算で定義されている.当然Vectorにも適用できるので意外と便利.Arrayに変換すれば要素ごとの演算子がもっと豊富で,any, allなどは便利.
  • resizeすると中身がリセットされるっぽい
  • vectorや配列から変換するときはMapを使う.ここでMapに渡すのはデータコンテナの先頭アドレス.よってvectorの場合はdata()を渡す.チュートリアルを見るとアドレス自体をコピーしている(メモリ領域自体)ように見えるけど,Map後の行列の値を変更しても元のデータは変更されないみたいだから,値コピーなのかな?