Eigen小ネタ

## 参考ページ
- [公式ページ](http://eigen.tuxfamily.org/index.php?title=Main_Page)
- [公式ドキュメント](https://eigen.tuxfamily.org/dox/index.html)
- [Naist-Robotics-lab](https://robotics.naist.jp/edu/text/?Robotics%2FEigen)
- [暗黒通信団](http://ankokudan.org/d/dl/pdf/pdf-eigennote.pdf)
- [qiita-セットアップ紹介](https://qiita.com/vs4sh/items/7e8bc95250db8d88bc41)
- [でらうま倶楽部(各種基本操作)](http://blog.livedoor.jp/tek_nishi/archives/8623876.html)
- [C++で線形代数を1](http://www.singularpoint.org/blog/c/eigen_1/)
- [C++で線形代数を2](http://www.singularpoint.org/blog/c/eigen_2/)
- [C++で線形代数を3](http://www.singularpoint.org/blog/math/eigen-3/)
- [PFNのブログ](https://research.preferred.jp/2010/11/eigen/)
- [金沢先生のまとめ](https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=9&cad=rja&uact=8&ved=2ahUKEwiUj_jn36rfAhWJiLwKHbaBC8gQFjAIegQIAhAC&url=https%3A%2F%2Fwww.morikita.co.jp%2Fbooks%2Fdownload%2F1574&usg=AOvVaw0KsTBA9F_OYAtW-nqoqvSx)

## std::vectorからEigen::VectorXdやEigen::MatrixXdへの型変換
```
std::vector<std::vector<int> > X_std = hogehoge;                                                                                             
std::vector<int> Y_std = fugafuga;                                                                                                            
int X_size = X_vec[0].size();                                                                                                                             
MatD X_mat = MatD::Zero(n_topics_, X_size);                                                                                                                       
for ( int i = 0; i < n_docs_; ++i) {                                                                                                                      
   X_.row(i) += Eigen::Map<VecI>(X_vec[i].data(), X_size).transpose().cast<double> ();                                                                     
  }                                                                                                                                                         
VecD Y_vec = Eigen::Map<VecI>(Y_vec.data(), n_docs_).cast<double> ();
```
- [参考](https://stackoverflow.com/questions/52261389/how-to-convert-an-stdvector-to-a-matrix-in-eigen)

## ブロードキャスト
公式ドキュメントに記載されている通り、標準のブロードキャストは、`+, -,+=, -=`しかない。
掛け算や割り算で、matrixとvectorを要素積したい時には別の書き方をする必要がある。
### matrix-vectorの要素積
```
Eigen::VectorXd vector = hogehoge;
Eigen::MatrixXd mat =fugafuga;
mat = mat * vec.asDiagonal();
```

### matrix-vectorの要素商
https://stackoverflow.com/questions/36849265/eigen-matrix-broadcasting-operation

```
Eigen::VectorXd vector = hogehoge;
Eigen::MatrixXd mat =fugafuga;
mat = mat.rowwise().array() / vec.transpose().array();
```

## ベクトルを規定としてrank1の行列を作るとき(外積?)
```
Eigen::VectorXd vector = hogehoge;
vector * vector.transpose();
```

## reshape
- vector

```
Eigen::Map<VecD> vec_reshape(vec.data(), vec.size() - 1);
```

- matrix

```
mat.conservativeResize(n,m);
```
注意：元のmatが書き換わってしまいます。

## concat
https://stackoverflow.com/questions/21496157/eigen-how-to-concatenate-matrix-along-a-specific-dimension

## gtestでのテストの仕方
https://stackoverflow.com/questions/25094989/compare-eigen-matrices-in-google-test-or-google-mock

## トリビア
- Matrix.row(d)はVector型ではない。`VectorXd v = Matrix.row(d)` は暗黙にキャストしている。
    - transposeするだけ？
- 行方向を取り出す演算(`mat.row(d)`や`mat.rowwise()`)は、行方向ベクトルになるので、演算するときに注意する(transposeを自分または相手に行う。)
- 関数で行列の行や列だけを参照渡しできない。(以下が例)
    - 参照の場合、constである必要があるから。

```
void func(Eigen::VectorXd &v){
  // proc something
};

Eigen::MatrixXd m = Eigen::MatrixXd::Constant(n,m,1.2);
int l = 1;

func(m.row(l).transpose()) //error because &v needs to be const to get m.row(l).transpose()
func(m.col(l)) // I didn't try but it seems the same with the above

```

### エラーについて
- THIS_METHOD_IS_ONLY_FOR_ARRAYS_NOT_MATRICES

arrayのみに実装されており、matrixに実装されていないメソッドや演算子を使うと発生。
割り算などは、arrayのみに実装されているので、要注意。

- Asertion `rows() == rhs.rows() && cols() == rhs.cols()' failed.

確保している行列の大きさよりも大きなインデックスへアクセスしようとしてしまっている。

### 最適化
- http://eigen.tuxfamily.org/index.php?title=FAQ#How_do_I_get_good_performance.3F