1use std::cmp::{Ordering, PartialOrd};
2use std::iter::IntoIterator;
3use std::ops::Range;
4
5use 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/// ```
19pub fn fitting_range<'a, T: 'a, I: IntoIterator<Item = &'a T>>(iter: I) -> Range<T>
20where
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