1#![warn(missing_docs)]
3
4use batbox_range::*;
5
6pub use std::cmp::{max, min};
7
8pub trait MinMax: Sized {
10 type T;
12
13 fn min_max(self) -> (Self::T, Self::T);
15
16 fn min(self) -> Self::T {
18 self.min_max().0
19 }
20
21 fn max(self) -> Self::T {
23 self.min_max().1
24 }
25}
26
27impl<T: Ord> MinMax for (T, T) {
28 type T = T;
29 fn min_max(self) -> (T, T) {
30 let (a, b) = self;
31 if a.cmp(&b) == std::cmp::Ordering::Less {
32 (a, b)
33 } else {
34 (b, a)
35 }
36 }
37}
38
39pub fn min_max<T: Ord>(a: T, b: T) -> (T, T) {
41 (a, b).min_max()
42}
43
44pub trait PartialMinMax: Sized {
46 type T;
48
49 fn partial_min_max(self) -> (Self::T, Self::T);
51
52 fn partial_min(self) -> Self::T {
54 self.partial_min_max().0
55 }
56
57 fn partial_max(self) -> Self::T {
59 self.partial_min_max().1
60 }
61}
62
63impl<T: PartialOrd> PartialMinMax for (T, T) {
64 type T = T;
65 fn partial_min_max(self) -> (T, T) {
66 let (a, b) = self;
67 if a.partial_cmp(&b) == Some(std::cmp::Ordering::Less) {
68 (a, b)
69 } else {
70 (b, a)
71 }
72 }
73}
74
75pub fn partial_min<T: PartialOrd>(a: T, b: T) -> T {
77 (a, b).partial_min()
78}
79
80pub fn partial_max<T: PartialOrd>(a: T, b: T) -> T {
82 (a, b).partial_max()
83}
84
85pub fn partial_min_max<T: PartialOrd>(a: T, b: T) -> (T, T) {
87 (a, b).partial_min_max()
88}
89
90pub trait Clamp: Sized + PartialOrd {
92 fn clamp_range(mut self, range: impl FixedRangeBounds<Self>) -> Self
101 where
102 Self: Clone,
103 {
104 match range.start_bound() {
105 FixedBound::Included(start) => self = partial_max(self, start.clone()),
106 FixedBound::Unbounded => (),
107 }
108 match range.end_bound() {
109 FixedBound::Included(end) => self = partial_min(self, end.clone()),
110 FixedBound::Unbounded => (),
111 }
112 self
113 }
114
115 fn clamp_abs(self, max: Self) -> Self
117 where
118 Self: std::ops::Neg<Output = Self> + Copy,
119 {
120 self.clamp_range(-max..=max)
121 }
122
123 fn clamp_max(self, max: Self) -> Self {
127 partial_min(self, max)
128 }
129
130 fn clamp_min(self, min: Self) -> Self {
134 partial_max(self, min)
135 }
136}
137
138impl<T: PartialOrd> Clamp for T {}