1use crate::float16::pf16;
2
3pub trait MinMax: Sized {
13 fn nan_min_lt(&self, other: &Self) -> bool;
17 fn nan_max_lt(&self, other: &Self) -> bool;
18
19 #[inline(always)]
20 fn nan_min_gt(&self, other: &Self) -> bool {
21 other.nan_min_lt(self)
22 }
23
24 #[inline(always)]
25 fn nan_max_gt(&self, other: &Self) -> bool {
26 other.nan_max_lt(self)
27 }
28
29 #[inline(always)]
31 fn min_propagate_nan(self, other: Self) -> Self {
32 if self.nan_min_lt(&other) { self } else { other }
33 }
34
35 #[inline(always)]
36 fn max_propagate_nan(self, other: Self) -> Self {
37 if self.nan_max_lt(&other) { other } else { self }
38 }
39
40 #[inline(always)]
41 fn min_ignore_nan(self, other: Self) -> Self {
42 if self.nan_max_lt(&other) { self } else { other }
43 }
44
45 #[inline(always)]
46 fn max_ignore_nan(self, other: Self) -> Self {
47 if self.nan_min_lt(&other) { other } else { self }
48 }
49}
50
51macro_rules! impl_trivial_min_max {
52 ($T: ty) => {
53 impl MinMax for $T {
54 #[inline(always)]
55 fn nan_min_lt(&self, other: &Self) -> bool {
56 self < other
57 }
58
59 #[inline(always)]
60 fn nan_max_lt(&self, other: &Self) -> bool {
61 self < other
62 }
63 }
64 };
65}
66
67impl_trivial_min_max!(bool);
70impl_trivial_min_max!(u8);
71impl_trivial_min_max!(u16);
72impl_trivial_min_max!(u32);
73impl_trivial_min_max!(u64);
74impl_trivial_min_max!(u128);
75impl_trivial_min_max!(usize);
76impl_trivial_min_max!(i8);
77impl_trivial_min_max!(i16);
78impl_trivial_min_max!(i32);
79impl_trivial_min_max!(i64);
80impl_trivial_min_max!(i128);
81impl_trivial_min_max!(isize);
82impl_trivial_min_max!(char);
83impl_trivial_min_max!(&str);
84impl_trivial_min_max!(&[u8]);
85impl_trivial_min_max!(String);
86
87macro_rules! impl_float_min_max {
88 ($T: ty) => {
89 impl MinMax for $T {
90 #[inline(always)]
91 fn nan_min_lt(&self, other: &Self) -> bool {
92 !(other.is_nan() | (self >= other))
93 }
94
95 #[inline(always)]
96 fn nan_max_lt(&self, other: &Self) -> bool {
97 !(self.is_nan() | (self >= other))
98 }
99
100 #[inline(always)]
101 fn min_ignore_nan(self, other: Self) -> Self {
102 <$T>::min(self, other)
103 }
104
105 #[inline(always)]
106 fn max_ignore_nan(self, other: Self) -> Self {
107 <$T>::max(self, other)
108 }
109
110 #[inline(always)]
111 fn min_propagate_nan(self, other: Self) -> Self {
112 if (self < other) | self.is_nan() {
113 self
114 } else {
115 other
116 }
117 }
118
119 #[inline(always)]
120 fn max_propagate_nan(self, other: Self) -> Self {
121 if (self > other) | self.is_nan() {
122 self
123 } else {
124 other
125 }
126 }
127 }
128 };
129}
130
131impl_float_min_max!(pf16);
132impl_float_min_max!(f32);
133impl_float_min_max!(f64);
134
135pub trait MinMaxPolicy {
136 fn is_better<T: MinMax>(a: &T, b: &T) -> bool;
138 fn best<T: MinMax>(a: T, b: T) -> T;
139}
140
141#[derive(Copy, Clone, Debug)]
142pub struct MinIgnoreNan;
143impl MinMaxPolicy for MinIgnoreNan {
144 fn is_better<T: MinMax>(a: &T, b: &T) -> bool {
145 T::nan_max_lt(a, b)
146 }
147
148 fn best<T: MinMax>(a: T, b: T) -> T {
149 T::min_ignore_nan(a, b)
150 }
151}
152
153#[derive(Copy, Clone, Debug)]
154pub struct MinPropagateNan;
155impl MinMaxPolicy for MinPropagateNan {
156 fn is_better<T: MinMax>(a: &T, b: &T) -> bool {
157 T::nan_min_lt(a, b)
158 }
159
160 fn best<T: MinMax>(a: T, b: T) -> T {
161 T::min_propagate_nan(a, b)
162 }
163}
164
165#[derive(Copy, Clone, Debug)]
166pub struct MaxIgnoreNan;
167impl MinMaxPolicy for MaxIgnoreNan {
168 fn is_better<T: MinMax>(a: &T, b: &T) -> bool {
169 T::nan_min_lt(b, a)
170 }
171
172 fn best<T: MinMax>(a: T, b: T) -> T {
173 T::max_ignore_nan(a, b)
174 }
175}
176
177#[derive(Copy, Clone, Debug)]
178pub struct MaxPropagateNan;
179impl MinMaxPolicy for MaxPropagateNan {
180 fn is_better<T: MinMax>(a: &T, b: &T) -> bool {
181 T::nan_max_lt(b, a)
182 }
183
184 fn best<T: MinMax>(a: T, b: T) -> T {
185 T::max_propagate_nan(a, b)
186 }
187}