1#![deny(missing_docs)]
4
5use num_traits::{Num, NumCast};
6use std::cmp;
7use std::fmt::Debug;
8use std::ops::{Range, RangeInclusive};
9
10pub fn clamp<N>(value: N, range: RangeInclusive<N>) -> N
30where
31 N: PartialOrd,
32{
33 let (low, high) = range.into_inner();
34 assert!(low <= high);
35 if value < low {
36 low
37 } else if value > high {
38 high
39 } else {
40 value
41 }
42}
43
44pub fn map_range<N, M>(
62 value: N,
63 Range {
64 start: in_low,
65 end: in_high,
66 }: Range<N>,
67 Range {
68 start: out_low,
69 end: out_high,
70 }: Range<M>,
71) -> M
72where
73 N: Num + NumCast + Copy + PartialOrd + Debug,
74 M: Num + NumCast + Copy + PartialOrd + Debug,
75{
76 assert!(in_low < in_high, "{:?} < {:?}", in_low, in_high);
77 assert!(out_low < out_high, "{:?} < {:?}", out_low, out_high);
78 assert!(value >= in_low, "{:?} >= {:?}", value, in_low);
79 assert!(value <= in_high, "{:?} <= {:?}", value, in_high);
80
81 let value: M = NumCast::from(value).unwrap();
82 let in_low: M = NumCast::from(in_low).unwrap();
83 let in_high: M = NumCast::from(in_high).unwrap();
84
85 let dividend = out_high - out_low;
86 let divisor = in_high - in_low;
87 assert!(!divisor.is_zero());
88
89 let slope = dividend / divisor;
90 out_low + (slope * (value - in_low))
91}
92
93#[derive(Copy, Clone, Debug, Default, PartialOrd, PartialEq, Hash)]
95pub struct NoMorePartial<T>(pub T);
96
97impl<T: PartialOrd> cmp::Ord for NoMorePartial<T> {
98 #[inline]
99 fn cmp(&self, other: &Self) -> cmp::Ordering {
100 self.partial_cmp(other).unwrap()
101 }
102}
103
104impl<T: PartialEq> cmp::Eq for NoMorePartial<T> {}