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