try_partialord/sort/
mod.rs1use crate::{ord_as_cmp, InvalidOrderError, OrderResult};
2use core::cmp::Ordering;
3#[cfg(feature = "std")]
4mod std_mergesort;
5mod std_quicksort;
6
7pub trait TrySort<T> {
9 #[cfg(feature = "std")]
10 #[inline]
11 fn try_sort(&mut self) -> OrderResult<()>
13 where
14 T: PartialOrd<T>,
15 {
16 self.try_sort_by(ord_as_cmp)
17 }
18 #[cfg(feature = "std")]
19 fn try_sort_by<F>(&mut self, compare: F) -> OrderResult<()>
21 where
22 F: FnMut(&T, &T) -> Option<bool>;
23 #[cfg(feature = "std")]
24 #[inline]
25 fn try_sort_by_key<K, F>(&mut self, f: F) -> OrderResult<()>
27 where
28 F: FnMut(&T) -> Option<K>,
29 K: PartialOrd<K>,
30 {
31 let mut f2 = f;
32 self.try_sort_by(|a, b| f2(a).partial_cmp(&f2(b)).map(|a| a == Ordering::Less))
33 }
34 #[cfg(feature = "std")]
35 fn try_sort_by_cached_key<K, F>(&mut self, f: F) -> OrderResult<()>
37 where
38 F: FnMut(&T) -> Option<K>,
39 K: PartialOrd<K>;
40
41 #[inline]
42 fn try_sort_unstable(&mut self) -> OrderResult<()>
44 where
45 T: PartialOrd<T>,
46 {
47 self.try_sort_unstable_by(ord_as_cmp)
48 }
49 fn try_sort_unstable_by<F>(&mut self, compare: F) -> OrderResult<()>
51 where
52 F: FnMut(&T, &T) -> Option<bool>;
53 #[inline]
54 fn try_sort_unstable_by_key<K, F>(&mut self, f: F) -> OrderResult<()>
56 where
57 F: FnMut(&T) -> Option<K>,
58 K: PartialOrd<K>,
59 {
60 let mut f2 = f;
61 self.try_sort_unstable_by(|a, b| f2(a).partial_cmp(&f2(b)).map(|a| a == Ordering::Less))
62 }
63
64 #[inline]
65 fn try_is_sorted(&self) -> OrderResult<bool>
67 where
68 T: PartialOrd<T>,
69 {
70 self.try_is_sorted_by(ord_as_cmp)
71 }
72 fn try_is_sorted_by<F>(&self, compare: F) -> OrderResult<bool>
74 where
75 F: FnMut(&T, &T) -> Option<bool>;
76 #[inline]
77 fn try_is_sorted_by_key<K, F>(&mut self, f: F) -> OrderResult<bool>
79 where
80 F: FnMut(&T) -> Option<K>,
81 K: PartialOrd<K>,
82 {
83 let mut f2 = f;
84 self.try_is_sorted_by(|a, b| f2(a).partial_cmp(&f2(b)).map(|a| a == Ordering::Less))
85 }
86}
87
88impl<T> TrySort<T> for [T] {
89 #[inline]
90 #[cfg(feature = "std")]
91 fn try_sort_by<F>(&mut self, compare: F) -> OrderResult<()>
92 where
93 F: FnMut(&T, &T) -> Option<bool>,
94 {
95 std_mergesort::merge_sort(self, compare).ok_or(InvalidOrderError)
96 }
97
98 #[inline]
99 fn try_sort_unstable_by<F>(&mut self, compare: F) -> OrderResult<()>
100 where
101 F: FnMut(&T, &T) -> Option<bool>,
102 {
103 std_quicksort::quicksort(self, compare).ok_or(InvalidOrderError)
104 }
105
106 #[inline]
107 fn try_is_sorted_by<F>(&self, compare: F) -> OrderResult<bool>
108 where
109 F: FnMut(&T, &T) -> Option<bool>,
110 {
111 try_is_sorted_by_slice(self, compare)
112 }
113
114 #[cfg(feature = "std")]
115 #[inline]
116 fn try_sort_by_cached_key<K, F>(&mut self, f: F) -> OrderResult<()>
117 where
118 F: FnMut(&T) -> Option<K>,
119 K: PartialOrd<K>,
120 {
121 macro_rules! sort_by_key {
123 ($t:ty, $slice:ident, $f:ident) => {{
124 let mut indices: Vec<_> = $slice
125 .iter()
126 .map($f)
127 .enumerate()
128 .map(|(i, k)| (k, i as $t))
129 .collect();
130 indices.try_sort_unstable()?;
134 for i in 0..$slice.len() {
135 let mut index = indices[i].1;
136 while (index as usize) < i {
137 index = indices[index as usize].1;
138 }
139 indices[i].1 = index;
140 $slice.swap(i, index as usize);
141 }
142 Ok(())
143 }};
144 }
145
146 let sz_u8 = core::mem::size_of::<(K, u8)>();
147 let sz_u16 = core::mem::size_of::<(K, u16)>();
148 let sz_u32 = core::mem::size_of::<(K, u32)>();
149 let sz_usize = core::mem::size_of::<(K, usize)>();
150
151 let len = self.len();
152 if len < 2 {
153 return Ok(());
154 }
155 if sz_u8 < sz_u16 && len <= (u8::MAX as usize) {
156 return sort_by_key!(u8, self, f);
157 }
158 if sz_u16 < sz_u32 && len <= (u16::MAX as usize) {
159 return sort_by_key!(u16, self, f);
160 }
161 if sz_u32 < sz_usize && len <= (u32::MAX as usize) {
162 return sort_by_key!(u32, self, f);
163 }
164 sort_by_key!(usize, self, f)
165 }
166}
167
168pub fn try_is_sorted_by_slice<T, F>(slice: &[T], compare: F) -> OrderResult<bool>
170where
171 F: FnMut(&T, &T) -> Option<bool>,
172{
173 let mut cmp = compare;
174 if slice.len() > 1 {
175 unsafe {
176 let mut prev = slice.get_unchecked(0);
177 for i in 1..slice.len() {
178 let next = slice.get_unchecked(i);
179 if let Some(x) = cmp(&prev, &next) {
180 if !x {
181 return Ok(false);
182 }
183 prev = next;
184 } else {
185 return Err(InvalidOrderError);
186 }
187 }
188 }
189 }
190 Ok(true)
191}
192
193pub fn try_is_sorted_by<T, I, F>(mut iter: I, compare: F) -> OrderResult<bool>
195where
196 F: FnMut(&T, &T) -> Option<bool>,
197 I: Iterator<Item = T>,
198{
199 let mut cmp = compare;
200 if let Some(mut prev) = iter.next() {
201 for next in iter {
202 if let Some(x) = cmp(&prev, &next) {
203 if !x {
204 return Ok(false);
205 }
206 prev = next;
207 } else {
208 return Err(InvalidOrderError);
209 }
210 }
211 }
212 Ok(true)
213}
214
215#[cfg(test)]
216#[cfg(feature = "std")]
217mod tests {
218 use crate::sort::*;
219 use rand::distributions::Standard;
220 use rand::prelude::*;
221 use std::vec::Vec;
222
223 #[test]
224 fn try_sort_ok() {
225 let rng = thread_rng();
226 let mut v: Vec<f32> = Standard.sample_iter(rng).take(100).collect();
227 let res = v.try_sort();
228 assert!(res.is_ok());
229 assert!(v.try_is_sorted().unwrap_or(false))
230 }
231
232 #[test]
233 fn try_sort_error() {
234 let rng = thread_rng();
235 let mut v: Vec<f32> = Standard.sample_iter(rng).take(100).collect();
236 v.push(f32::NAN);
237 let res = v.try_sort();
238 assert!(res.is_err());
239 assert!(!v.try_is_sorted().is_err())
240 }
241}