std::valarrayの使い方

#std::valarrayの使い方
C++で可変長配列を扱う時によく使うのがstd::vectorだが、intやdoubleなどの数値に限っては数値配列専用のstd::valarrayがある。便利なメンバ関数や演算子が定義されていて、シンプルに書くことが出来る。
また、速度についてもstd::vectorよりも優位という話もある。[(参考: .Regenschauer 雑記帳)](http://sigure430.hatenablog.com/entry/2014/12/13/162149)

以下でstd::valarrayの使い方をstd::vectorと比較しながら示す．
実行環境: Visual C++ 14 (Visual studio 2015)

##インクルード
ヘッダーをインクルードするだけで良い．

```cpp
#include <vector>//std::vector
#include <valarray>//std::valarray
```


##初期化

###初期化リストで初期化
`std::vector`, `std::valarray`ともに初期化リストで初期できる．

```cpp
//std::vector
std::vector<double> vector = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
//std::valarray
std::valarray<double> varray = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
```
###要素数と同一の初期値して初期化
要素数と初期値で初期化が可能だが，`std::valarray`だけ順序が逆なので注意．

```cpp
//std::vector
std::vector<double> vector(10, 0.0);
//std::valarray
std::valarray<double> varray(0.0, 10);//初期値，要素数の順．
```

##繰り返し処理
###範囲for文
`std::vector`, `std::valarray`ともに範囲for文(Range-based for loop)を使うことができる．

```cpp
//std::vector
for (auto& v : vector)
{
  //処理...
	std::cout << v << std::endl;
}

//std::valarray
for (auto& v : varray)
{
  //処理...
	std::cout << v << std::endl;
}
```

###for_each,std::transformの使用
`std::valarray`でも，`std::for_each`, `std::transform`を使うことができる．
ただし，`std::valarray`では`begin()`と`end()`がメンバ関数ではないので，`std::begin()`, `std::end()`を使う．

```cpp
std::for_each(vector.begin(), vector.end(), [](auto x) {std::cout << x << std::endl; });
std::for_each(std::begin(varray), std::end(varray), [](auto x) {std::cout << x << std::endl; });//std::begin(), std::end()を使う．

```

また，std::valarrayにはapply()というメンバ関数が用意されている．

```cpp
//std::vector
std::transform(vector.begin(), vector.end(),vector.begin(), [](double v) {return v+1; });
//std::valarray
varray = varray.apply([](double v) {return v+1; });
```

##配列同士の四則演算
例として，2つの配列の足し算を行う．
`std::vector`では，`std::transfrom`で行う．[(参考: 学生時代に頑張ったことが何もない)](http://d.hatena.ne.jp/muupan/20140619/1403183849)
一方`std::valarray`では，演算子が定義されているので+で書くことが出来る．

```cpp
//std::vector
std::vector<double> vector1 = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
std::vector<double> vector2 = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 };
std::vector<double> vector3(vector1.size(),0.0);
std::transform(vector1.begin(), vector1.end(), vector2.begin(), vector3.begin(), std::plus<double>());

//std::valarray
std::valarray<double> varray1 = { 0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0 };
std::valarray<double> varray2 = { 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0 };
std::valarray<double> varray3 = varray1 + varray2;
```

##最大，最小，合計，平均，分散
###最大，最小，合計
`std::vector`では`std::max_element`, `std::min_element`, `std::accumulate`を使って求めるが，
`std::valarray`ではこれらがメンバ関数として用意されている．
 
```cpp
//std::vector
auto max = *std::max_element(vector.begin(), vector.end());//9
auto min = *std::min_element(vector.begin(), vector.end());//0
auto sum = std::accumulate(vector.begin(), vector.end(), 0.0);//45

//std::valarray
auto max = varray.max();//9
auto min = varray.min();//0
auto sum = varray.sum();//45
  
```

###平均，分散
要素の和と内積を使って平均と分散を求める．
`std::vector`では，`std::accumulate`や`std::inner_product`を使う．[(参考: My Life as a Mock Quant)](http://d.hatena.ne.jp/teramonagi/20120627/1340805908)
`std::varray`の方がメンバ関数や演算子でシンプルに書くことができる．

```cpp
//std::vector
auto mean = std::accumulate(vector.begin(), vector.end(), 0.0) / vector.size();//4.5
auto var = (std::inner_product(vector.begin(), vector.end(), vector.begin(), 0.0) - mean * mean * vector.size() )/vector.size();//8.25

//std::valarray
auto mean = varray.sum() / varray.size();//4.5
auto var = ((varray*varray).sum() - mean*mean*varray.size()) / varray.size();//8.25
```