1 | use std::cmp::{Ordering, PartialOrd}; |
2 | use std::iter::IntoIterator; |
3 | use std::ops::Range; |
4 | |
5 | use num_traits::{One, Zero}; |
6 | |
7 | /// Build a range that fits the data |
8 | /// |
9 | /// - `iter`: the iterator over the data |
10 | /// - **returns** The resulting range |
11 | /// |
12 | /// ```rust |
13 | /// use plotters::data::fitting_range; |
14 | /// |
15 | /// let data = [4, 14, -2, 2, 5]; |
16 | /// let range = fitting_range(&data); |
17 | /// assert_eq!(range, std::ops::Range { start: -2, end: 14 }); |
18 | /// ``` |
19 | pub fn fitting_range<'a, T: 'a, I: IntoIterator<Item = &'a T>>(iter: I) -> Range<T> |
20 | where |
21 | T: Zero + One + PartialOrd + Clone, |
22 | { |
23 | let (mut lb: Option, mut ub: Option) = (None, None); |
24 | |
25 | for value: &T in iter.into_iter() { |
26 | if let Some(Ordering::Greater) = lb |
27 | .as_ref() |
28 | .map_or(default:Some(Ordering::Greater), |lbv: &T| lbv.partial_cmp(value)) |
29 | { |
30 | lb = Some(value.clone()); |
31 | } |
32 | |
33 | if let Some(Ordering::Less) = ub |
34 | .as_ref() |
35 | .map_or(default:Some(Ordering::Less), |ubv: &T| ubv.partial_cmp(value)) |
36 | { |
37 | ub = Some(value.clone()); |
38 | } |
39 | } |
40 | |
41 | lb.unwrap_or_else(Zero::zero)..ub.unwrap_or_else(One::one) |
42 | } |
43 | |