1#![cfg_attr(not(feature = "use_std"), no_std)]
11#![cfg_attr(
13 feature = "unstable",
14 feature(
15 specialization,
16 fn_traits,
17 unboxed_closures,
18 stdsimd,
19 align_offset
20 )
21)]
22
23#[allow(unused_imports, unused_macros)]
24#[cfg(not(feature = "use_std"))]
25use core as std;
26
27use std::cmp;
28
29#[cfg(feature = "unstable")]
30use std::{arch, mem, slice};
31
32use cmp::Ordering;
33
34#[cfg(feature = "unstable")]
35mod ord;
36#[cfg(feature = "unstable")]
37pub use self::ord::*;
38
39#[cfg(feature = "unstable")]
40#[macro_use]
41mod macros;
42
43#[cfg(feature = "unstable")]
44mod signed;
45
46#[cfg(feature = "unstable")]
47mod unsigned;
48
49#[cfg(feature = "unstable")]
50mod floats;
51
52pub trait IsSorted: Iterator {
55 #[inline]
67 fn is_sorted(&mut self) -> bool
68 where
69 Self: Sized,
70 Self::Item: PartialOrd,
71 {
72 #[cfg(feature = "unstable")]
73 {
74 self.is_sorted_by(Increasing)
75 }
76 #[cfg(not(feature = "unstable"))]
77 {
78 self.is_sorted_by(<Self::Item as PartialOrd>::partial_cmp)
79 }
80 }
81
82 #[inline]
100 fn is_sorted_by<F>(&mut self, compare: F) -> bool
101 where
102 Self: Sized,
103 F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
104 {
105 is_sorted_by_impl(self, compare)
106 }
107
108 #[inline]
120 fn is_sorted_by_key<F, B>(&mut self, mut key: F) -> bool
121 where
122 Self: Sized,
123 B: PartialOrd,
124 F: FnMut(&Self::Item) -> B,
125 {
126 IsSorted::is_sorted(&mut self.map(|v| key(&v)))
127 }
128
129 #[inline]
139 fn is_sorted_until_by<F>(
140 self, compare: F,
141 ) -> (Option<(Self::Item, Self::Item)>, Self)
142 where
143 Self: Sized,
144 F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
145 {
146 is_sorted_until_by_impl(self, compare)
147 }
148}
149
150impl<I: Iterator> IsSorted for I {}
152
153#[inline]
155fn is_sorted_by_impl<I, F>(iter: &mut I, compare: F) -> bool
156where
157 I: Iterator,
158 F: FnMut(&I::Item, &I::Item) -> Option<Ordering>,
159{
160 <I as IsSortedBy<F>>::is_sorted_by(iter, compare)
161}
162
163trait IsSortedBy<F>: Iterator
166where
167 F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
168{
169 fn is_sorted_by(&mut self, compare: F) -> bool;
170}
171
172impl<I, F> IsSortedBy<F> for I
175where
176 I: Iterator,
177 F: FnMut(&I::Item, &I::Item) -> Option<Ordering>,
178{
179 #[inline]
180 #[cfg(feature = "unstable")]
181 default fn is_sorted_by(&mut self, compare: F) -> bool {
182 is_sorted_by_scalar_impl(self, compare)
183 }
184
185 #[inline]
186 #[cfg(not(feature = "unstable"))]
187 fn is_sorted_by(&mut self, compare: F) -> bool {
188 is_sorted_by_scalar_impl(self, compare)
189 }
190}
191
192#[inline]
196fn is_sorted_by_scalar_impl<I, F>(iter: &mut I, mut compare: F) -> bool
197where
198 I: Iterator,
199 F: FnMut(&I::Item, &I::Item) -> Option<Ordering>,
200{
201 let first = iter.next();
202 if let Some(mut first) = first {
203 return iter.all(|second| {
204 if let Some(ord) = compare(&first, &second) {
205 if ord != Ordering::Greater {
206 first = second;
207 return true;
208 }
209 }
210 false
211 });
212 }
213 true
214}
215
216#[cfg(feature = "unstable")]
220#[inline]
221fn is_sorted_by_scalar_slice_impl<'a, T, F>(
222 iter: &mut slice::Iter<'a, T>, mut compare: F,
223) -> bool
224where
225 T: PartialOrd,
226 F: FnMut(&&'a T, &&'a T) -> Option<Ordering>,
227{
228 let s = iter.as_slice();
229 if s.len() < 2 {
230 return true;
231 }
232 let mut first = unsafe { s.get_unchecked(0) };
233 for i in 1..s.len() {
234 let second = unsafe { s.get_unchecked(i) };
235 if let Some(ord) = compare(&first, &second) {
236 if ord != Ordering::Greater {
237 first = second;
238 continue;
239 }
240 }
241 return false;
242 }
243 true
244}
245
246#[inline]
249fn is_sorted_until_by_impl<I, F>(
250 iter: I, compare: F,
251) -> (Option<(I::Item, I::Item)>, I)
252where
253 I: Iterator,
254 F: FnMut(&I::Item, &I::Item) -> Option<Ordering>,
255{
256 <I as IsSortedUntilBy<F>>::is_sorted_until_by(iter, compare)
257}
258
259trait IsSortedUntilBy<F>: Iterator
262where
263 F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
264{
265 fn is_sorted_until_by(
266 self, compare: F,
267 ) -> (Option<(Self::Item, Self::Item)>, Self);
268}
269
270impl<I, F> IsSortedUntilBy<F> for I
273where
274 I: Iterator,
275 F: FnMut(&I::Item, &I::Item) -> Option<Ordering>,
276{
277 #[inline]
278 #[cfg(feature = "unstable")]
279 default fn is_sorted_until_by(
280 self, compare: F,
281 ) -> (Option<(Self::Item, Self::Item)>, Self) {
282 is_sorted_until_by_scalar_impl(self, compare)
283 }
284
285 #[inline]
286 #[cfg(not(feature = "unstable"))]
287 fn is_sorted_until_by(
288 self, compare: F,
289 ) -> (Option<(Self::Item, Self::Item)>, Self) {
290 is_sorted_until_by_scalar_impl(self, compare)
291 }
292}
293
294#[inline]
296fn is_sorted_until_by_scalar_impl<I, F>(
297 mut iter: I, mut compare: F,
298) -> (Option<(I::Item, I::Item)>, I)
299where
300 I: Iterator,
301 F: FnMut(&I::Item, &I::Item) -> Option<Ordering>,
302{
303 let first = iter.next();
304 if let Some(mut first) = first {
305 loop {
306 let next = iter.next();
307 if let Some(next) = next {
308 if let Some(ord) = compare(&first, &next) {
309 if ord != Ordering::Greater {
310 first = next;
311 continue;
312 }
313 }
314 return (Some((first, next)), iter);
315 }
316 return (None, iter);
317 }
318 }
319 (None, iter)
320}
321
322#[cfg(feature = "unstable")]
326#[inline]
327fn is_sorted_until_by_scalar_slice_impl<'a, T, F>(
328 iter: slice::Iter<'a, T>, mut compare: F,
329) -> (Option<(&'a T, &'a T)>, slice::Iter<'a, T>)
330where
331 T: PartialOrd,
332 F: FnMut(&&'a T, &&'a T) -> Option<Ordering>,
333{
334 let s = iter.as_slice();
335 if s.len() < 2 {
336 return (None, unsafe { s.get_unchecked(s.len()..).iter() });
337 }
338 let mut first = unsafe { s.get_unchecked(0) };
339 for i in 0..s.len() {
340 let second = unsafe { s.get_unchecked(i) };
341 if let Some(ord) = compare(&first, &second) {
342 if ord != Ordering::Greater {
343 first = second;
344 continue;
345 }
346 }
347 return (Some((first, second)), unsafe {
348 s.get_unchecked((i + 1)..).iter()
349 });
350 }
351 return (None, unsafe { s.get_unchecked(s.len()..).iter() });
352}
353
354pub fn is_sorted_until_by<T, F>(slice: &[T], f: F) -> usize
355where
356 for<'r, 's> F: FnMut(&'r &T, &'s &T) -> Option<Ordering>,
357{
358 let (boundary, tail) = IsSorted::is_sorted_until_by(slice.iter(), f);
359 match boundary {
360 Some(_) => {
361 debug_assert!(tail.as_slice().len() < slice.len());
362 slice.len() - tail.as_slice().len() - 1
363 }
364 None => {
365 debug_assert!(tail.as_slice().is_empty());
366 slice.len()
367 }
368 }
369}
370
371#[cfg(feature = "unstable")]
372impl<'a, T, F> IsSortedBy<F> for slice::Iter<'a, T>
373where
374 T: PartialOrd,
375 F: FnMut(&&'a T, &&'a T) -> Option<Ordering>,
376{
377 #[inline]
378 default fn is_sorted_by(&mut self, compare: F) -> bool {
379 is_sorted_by_scalar_slice_impl(self, compare)
380 }
381}
382
383#[cfg(feature = "unstable")]
384impl<'a, T, F> IsSortedUntilBy<F> for slice::Iter<'a, T>
385where
386 T: PartialOrd,
387 F: FnMut(&&'a T, &&'a T) -> Option<Ordering>,
388{
389 #[inline]
390 default fn is_sorted_until_by(
391 self, compare: F,
392 ) -> (Option<(&'a T, &'a T)>, Self) {
393 return is_sorted_until_by_scalar_slice_impl(self, compare);
394 }
395}
396
397macro_rules! is_sorted_by_slice_iter_x86 {
403 ($id:ident, $cmp:path : $([$feature:tt, $function:path]),*) => {
404 #[cfg(feature = "unstable")]
405 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
406 #[cfg(
407 any(
408 feature = "use_std",
410 any($(target_feature = $feature),*)
412 )
413 )]
414 impl<'a> IsSortedBy<$cmp> for slice::Iter<'a, $id> {
415 #[inline]
416 fn is_sorted_by(&mut self, compare: $cmp) -> bool {
417 #[cfg(not(feature = "use_std"))]
422 unsafe {
423 $(
424 #[cfg(target_feature = $feature)]
425 {
426 return $function(self.as_slice()) == self.as_slice().len();
427 }
428 )*
429 }
430
431 #[cfg(feature = "use_std")]
432 {
433 $(
434 if is_x86_feature_detected!($feature) {
435 return unsafe { $function(self.as_slice()) == self.as_slice().len() };
436 }
437 )*;
438 return is_sorted_by_scalar_slice_impl(self, compare);
440 }
441 }
442 }
443
444 #[cfg(feature = "unstable")]
445 #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
446 #[cfg(
447 any(
448 feature = "use_std",
450 any($(target_feature = $feature),*)
452 )
453 )]
454 impl<'a> IsSortedUntilBy<$cmp> for slice::Iter<'a, $id> {
455 #[inline]
456 fn is_sorted_until_by(self, compare: $cmp)
457 -> (Option<(Self::Item,Self::Item)>, Self) {
458 #[cfg(not(feature = "use_std"))]
463 unsafe {
464 $(
465 #[cfg(target_feature = $feature)]
466 {
467 let s = self.as_slice();
472 let i = $function(s);
473 return is_sorted_until_by_scalar_slice_impl(s[i..].iter(), compare);
474 }
475 )*
476 }
477
478 #[cfg(feature = "use_std")]
479 {
480 $(
481 if is_x86_feature_detected!($feature) {
482 let s = self.as_slice();
483 let i = unsafe { $function(s) };
484 return is_sorted_until_by_scalar_slice_impl(s[i..].iter(), compare);
485 }
486 )*;
487 return is_sorted_until_by_scalar_slice_impl(self, compare);
489 }
490 }
491 }
492 }
493}
494
495is_sorted_by_slice_iter_x86!(
496 i64, ord::types::Increasing :
497 ["avx2", ::signed::avx2::is_sorted_lt_i64],
498 ["sse4.2", ::signed::sse42::is_sorted_lt_i64]
499);
500
501is_sorted_by_slice_iter_x86!(
502 i64, ord::types::Decreasing :
503 ["avx2", ::signed::avx2::is_sorted_gt_i64],
504 ["sse4.2", ::signed::sse42::is_sorted_gt_i64]
505);
506
507is_sorted_by_slice_iter_x86!(
508 f64, ord::types::Increasing :
509 ["avx", ::floats::avx::is_sorted_lt_f64],
510 ["sse4.1", ::floats::sse41::is_sorted_lt_f64]
511);
512
513is_sorted_by_slice_iter_x86!(
514 f64, ord::types::Decreasing :
515 ["avx", ::floats::avx::is_sorted_gt_f64],
516 ["sse4.1", ::floats::sse41::is_sorted_gt_f64]
517);
518
519is_sorted_by_slice_iter_x86!(
520 i32, ord::types::Increasing :
521 ["avx2", ::signed::avx2::is_sorted_lt_i32],
522 ["sse4.1", ::signed::sse41::is_sorted_lt_i32]
523);
524
525is_sorted_by_slice_iter_x86!(
526 i32, ord::types::Decreasing :
527 ["avx2", ::signed::avx2::is_sorted_gt_i32],
528 ["sse4.1", ::signed::sse41::is_sorted_gt_i32]
529);
530
531is_sorted_by_slice_iter_x86!(
532 u32, ord::types::Increasing :
533 ["avx2", ::unsigned::avx2::is_sorted_lt_u32],
534 ["sse4.1", ::unsigned::sse41::is_sorted_lt_u32]
535);
536
537is_sorted_by_slice_iter_x86!(
538 u32, ord::types::Decreasing :
539 ["avx2", ::unsigned::avx2::is_sorted_gt_u32],
540 ["sse4.1", ::unsigned::sse41::is_sorted_gt_u32]
541);
542
543is_sorted_by_slice_iter_x86!(
544 f32, ord::types::Increasing :
545 ["avx", ::floats::avx::is_sorted_lt_f32],
546 ["sse4.1", ::floats::sse41::is_sorted_lt_f32]
547);
548
549is_sorted_by_slice_iter_x86!(
550 f32, ord::types::Decreasing :
551 ["avx", ::floats::avx::is_sorted_gt_f32],
552 ["sse4.1", ::floats::sse41::is_sorted_gt_f32]
553);
554
555is_sorted_by_slice_iter_x86!(
556 i16, ord::types::Increasing :
557 ["avx2", ::signed::avx2::is_sorted_lt_i16],
558 ["sse4.1", ::signed::sse41::is_sorted_lt_i16]
559);
560
561is_sorted_by_slice_iter_x86!(
562 i16, ord::types::Decreasing :
563 ["avx2", ::signed::avx2::is_sorted_gt_i16],
564 ["sse4.1", ::signed::sse41::is_sorted_gt_i16]
565);
566
567is_sorted_by_slice_iter_x86!(
568 u16, ord::types::Increasing :
569 ["avx2", ::unsigned::avx2::is_sorted_lt_u16],
570 ["sse4.1", ::unsigned::sse41::is_sorted_lt_u16]
571);
572
573is_sorted_by_slice_iter_x86!(
574 u16, ord::types::Decreasing :
575 ["avx2", ::unsigned::avx2::is_sorted_gt_u16],
576 ["sse4.1", ::unsigned::sse41::is_sorted_gt_u16]
577);
578
579is_sorted_by_slice_iter_x86!(
580 i8, ord::types::Increasing :
581 ["avx2", ::signed::avx2::is_sorted_lt_i8],
582 ["sse4.1", ::signed::sse41::is_sorted_lt_i8]
583);
584
585is_sorted_by_slice_iter_x86!(
586 i8, ord::types::Decreasing :
587 ["avx2", ::signed::avx2::is_sorted_gt_i8],
588 ["sse4.1", ::signed::sse41::is_sorted_gt_i8]
589);
590
591is_sorted_by_slice_iter_x86!(
592 u8, ord::types::Increasing :
593 ["avx2", ::unsigned::avx2::is_sorted_lt_u8],
594 ["sse4.1", ::unsigned::sse41::is_sorted_lt_u8]
595);
596
597is_sorted_by_slice_iter_x86!(
598 u8, ord::types::Decreasing :
599 ["avx2", ::unsigned::avx2::is_sorted_gt_u8],
600 ["sse4.1", ::unsigned::sse41::is_sorted_gt_u8]
601);