Rustでf32やf64の配列の最大値を得る方法

# TL;DR
```rust:参照のイテレータの場合
// iter: Iterator<&f64>
let max = iter.fold(0.0/0.0, |m, v| v.max(m));
```

```rust:値のイテレータの場合
// iter: Iterator<f64>
let max = iter.fold(0.0/0.0, f64::max);
// または
let max = iter.fold(0.0/0.0, |m, v| v.max(m));
```

`NaN` かもしれない値を `Option<NaNでない小数>` のようにして弾くには:

```rust:f64をOptionに変換
// `val: f64`: NaNかもしれない値
let opt_f64 = Some(val).into_iter().find(|v| !v.is_nan());
// opt_f64: Option<f64>
```

# 最大値と浮動小数点数
Rustでは `f32` や `f64` は `PartialOrd` を実装してはいるが、 `Ord` を実装していない。
`NAN <= NAN` でなく、かつ `NAN > NAN` でもないためだ。
そんなわけで、 `Iterator<f32>::max()` なんかは使えないのである。

```rust
let vec = vec![1.0, 2.0, -3.0, ::std::f64::NAN, 1.4142, 3.1416, -0.1];
let max = vec.iter().max(); // <- エラー
// "error: the trait `core::cmp::Ord` is not implemented for the type `f64` [E0277]"
```

かといって、これだけの処理のためにforループとif文を書くのもばかばかしい。

そして、いろいろ試行錯誤した結果、辿り着いた方法が以下のものである。

```rust:iter()の場合
let vec = vec![1.0, 2.0, -3.0, ::std::f64::NAN, 1.4142, 3.1416, -0.1];

// NaN以外の要素がある場合
let max = vec.iter().fold(0.0/0.0, |m, v| v.max(m));
println!("max: {}", max); // => 3.1416

// NaNしかない場合
println!("max: {}",
         Some(::std::f64::NAN).iter().fold(0.0/0.0, |m, v| v.max(m)));
// => NaN
```

```rust:into_iter()の場合
let vec = vec![1.0, 2.0, -3.0, ::std::f64::NAN, 1.4142, 3.1416, -0.1];

// NaN以外の要素がある場合
let max = vec.into_iter().fold(0.0/0.0, f64::max); // <- f64::maxを使う
println!("max: {}", max); // => 3.1416
```

## 解説
### [`f64::max`](https://doc.rust-lang.org/std/primitive.f64.html#method.max)
`S -> T -> S` として渡した関数 `|m, v| v.max(m)` や [`f64::max`](https://doc.rust-lang.org/std/primitive.f64.html#method.max) は、「もし引数のどちらかがNaNであれば、そっちじゃない方を返す」という関数なので、返る値は結局こうなる。

- 両方 `NaN` → `NaN`
- 一方だけ `NaN` → `NaN` じゃない方
- 両方 `NaN` ではない → 大きな方

`|m, v| v.max(m)` とクロージャを使うのは理由があって、 `vec.iter()` は `Iterator<&f64>` とかを返すので、そのまま `f64::max` に渡すと、「 `f64::max(_, &f64)` なんてねえぞ💢」とコンパイラに怒られるためである。
仕方がないので引数として受け取ってやることになる。
ついでに、 `v` は `&f64` であるが、メソッドを探す時点で勝手にデリファレンスされて `f64::max` が探されるので、 `|m, &v|` と書く必要はない。一文字節約だ。

それから、 `|m, v| m.max(v)` と逆にすると、これまたうまくいかない。
`NAN` として使っている `0.0/0.0` の型が判然としない(`f32` とも `f64` ともとれる)ため、「 ``error: no method named `max` found for type `_` in the current scope`` 」とお叱りを受ける。

型が曖昧だとメソッド `max()` を呼べないということは、以下の場合もエラーになる。

```rust
let max = vec![0.0, 1.0].iter().fold(0.0/0.0, |m, v| v.max(m)); // ← エラー
```

こういう場合、 `v` 側か `m` 側で、どこかで型をはっきりさせてやる必要がある。

```rust
let max1 = vec![0.0, 1.0].iter().fold(0.0/0.0, |m, v: &f64| v.max(m)); // ← おｋ
let max2 = vec![0.0, 1.0].iter().fold(0.0/0.0f64, |m, &v| m.max(v)); // ← おｋ
let max3 = vec![0.0f64, 1.0].iter().fold(0.0/0.0, |m, v| v.max(m)); // ← おｋ
```

`v` を受け取る時点で型を明示したのが `max1` 、 `m` の型を明示したのが `max2` 、`v` をイテレータ作成前に明示したのが `max3` である。
`max2` の例では、 `v` の型が曖昧なため `m.max(v)` のように `m` のメソッドを呼ぶことと、メソッド呼び出しの引数は勝手にデリファレンスされないため、 `&v` のように受け取ることで参照を剥がすこと、この2点に注意だ。

### [`Iterator::fold()`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.fold)
reduceと呼ばれることも多い、例のアレだ。
型は `Iterator<T> -> S -> (S -> T -> S) -> S` みたいな感じだが、この用例では `S`, `T` ともに `f64` である。

あとは、 `fold()` を、**状態として今までの最大値**、**入力として次の値**、**出力として更新された最大値**のようにして使うことで、イテレータで列挙した要素の最大値が得られる。

# 最小値
書くまでもないが、 `max()` の代わりに `min()` を使えばよい。

# `NaN` の代わりに `Option<f64>` が欲しい
ここで `if else` なんかを使ってしまうと、一気に文字数が膨れ上がる。
「基本 `Some` にしておいて、 `NAN` だけ `None` にする」という方針でいくと、比較的短く済む。

```rust
let max = Some(vec.iter().fold(0.0/0.0, |m, v| v.max(m)))
    .filter(|v| !v.is_nan());
```

手前味噌だが、[Rustでイテレータを積極的に使っていくメモ (逐次更新)](http://qiita.com/l1048576/items/ccef72649883af343f84)の[事例2](http://qiita.com/l1048576/items/ccef72649883af343f84#%E4%BA%8B%E4%BE%8B2-optiont-%E3%81%AE%E4%B8%AD%E8%BA%AB%E3%81%8C%E6%9D%A1%E4%BB%B6%E3%82%92%E6%BA%80%E3%81%9F%E3%81%97%E3%81%A6%E3%81%84%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%82%89-none-%E3%81%AB%E3%81%99%E3%82%8B)である。


# その他
ナン(`NaN`)をナン(`None`)に変換するの、ちょっとおもしろい。
……と思ったが、英語圏では3文字のacronymは一音節で読まず個々の文字を読むと聞いたことがあるので、NaNは「ナン」とは発音しないのかもしれない。
残念。


以上。