From 607edb81737c916d86e575d09356840100c2e431 Mon Sep 17 00:00:00 2001 From: Noa Date: Thu, 5 May 2022 11:18:35 -0500 Subject: [PATCH] Specialize ordering() for Ord types --- src/find_run/tests.rs | 4 ++-- src/gallop.rs | 17 +++------------- src/gallop/tests.rs | 6 +++--- src/insort/tests.rs | 4 ++-- src/lib.rs | 47 +++++++++++++++++++++++++++++++++++++------ src/merge/tests.rs | 4 ++-- src/sort.rs | 5 +---- src/sort/tests.rs | 4 ++-- 8 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/find_run/tests.rs b/src/find_run/tests.rs index ac9656a..955396b 100644 --- a/src/find_run/tests.rs +++ b/src/find_run/tests.rs @@ -1,4 +1,4 @@ -use crate::{comparator, never}; +use crate::{comparator, never, ord_t_comparator}; #[test] fn empty() { @@ -76,5 +76,5 @@ fn find_run(list: &[T]) -> (bool, usize) { /// With comparator. fn get_run(list: &mut [T]) -> usize { - super::get_run(list, &comparator(|a, b| Ok(a > b))).unwrap_or_else(never) + super::get_run(list, &ord_t_comparator()).unwrap_or_else(never) } diff --git a/src/gallop.rs b/src/gallop.rs index 4253d4e..12f2895 100644 --- a/src/gallop.rs +++ b/src/gallop.rs @@ -23,7 +23,7 @@ pub(crate) fn gallop_left>( let (mut base, mut lim) = gallop(key, list, mode, cmp)?; while lim != 0 { let ix = base + (lim / 2); - match ordering(cmp, &list[ix], key)? { + match cmp.ordering(&list[ix], key)? { Ordering::Less => { base = ix + 1; lim -= 1; @@ -53,7 +53,7 @@ pub(crate) fn gallop_right>( let (mut base, mut lim) = gallop(key, list, mode, cmp)?; while lim != 0 { let ix = base + (lim / 2); - match ordering(cmp, &list[ix], key)? { + match cmp.ordering(&list[ix], key)? { Ordering::Less => { base = ix + 1; lim -= 1; @@ -88,7 +88,7 @@ fn gallop>( let mut prev_val = 0; let mut next_val = 1; while next_val < list_len { - match ordering(cmp, &list[next_val], key)? { + match cmp.ordering(&list[next_val], key)? { Ordering::Less => { prev_val = next_val; next_val = ((next_val + 1) * 2) - 1; @@ -124,14 +124,3 @@ fn gallop>( }; Ok(ret) } - -fn ordering>(cmp: &C, a: &T, b: &T) -> Result { - let ord = if cmp.is_gt(a, b)? { - Ordering::Greater - } else if cmp.is_gt(b, a)? { - Ordering::Less - } else { - Ordering::Equal - }; - Ok(ord) -} diff --git a/src/gallop/tests.rs b/src/gallop/tests.rs index a564826..ed3a73c 100644 --- a/src/gallop/tests.rs +++ b/src/gallop/tests.rs @@ -1,5 +1,5 @@ use super::Mode; -use crate::{comparator, never}; +use crate::{never, ord_t_comparator}; macro_rules! test_both { ($v:ident, $($x:expr);*) => {{ @@ -182,9 +182,9 @@ fn gallop_large_end_greater() { } fn gallop_left(key: &T, list: &[T], mode: Mode) -> usize { - super::gallop_left(key, list, mode, &comparator(|a, b| Ok(a > b))).unwrap_or_else(never) + super::gallop_left(key, list, mode, &ord_t_comparator()).unwrap_or_else(never) } fn gallop_right(key: &T, list: &[T], mode: Mode) -> usize { - super::gallop_right(key, list, mode, &comparator(|a, b| Ok(a > b))).unwrap_or_else(never) + super::gallop_right(key, list, mode, &ord_t_comparator()).unwrap_or_else(never) } diff --git a/src/insort/tests.rs b/src/insort/tests.rs index c5108b6..f585133 100644 --- a/src/insort/tests.rs +++ b/src/insort/tests.rs @@ -1,4 +1,4 @@ -use crate::{comparator, never}; +use crate::{comparator, never, ord_t_comparator}; /// Test the insertion sort implementation with an empty list #[test] @@ -80,5 +80,5 @@ fn stable() { /// Insertion sort implementation convenience used for tests. fn sort(list: &mut [T]) { - super::sort(list, &comparator(|a, b| Ok(a > b))).unwrap_or_else(never); + super::sort(list, &ord_t_comparator()).unwrap_or_else(never); } diff --git a/src/lib.rs b/src/lib.rs index f223cb2..c178979 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ mod insort; mod merge; mod sort; -pub use sort::try_sort_by as try_sort_by_gt; +use sort::try_sort_by as try_sort_by_cmp; use std::cmp::Ordering; use std::convert::Infallible; @@ -19,14 +19,19 @@ fn never(x: Infallible) -> T { match x {} } +pub fn try_sort_by_gt Result>( + list: &mut [T], + cmp: C, +) -> Result<(), E> { + try_sort_by_cmp(list, cmp) +} + #[inline] pub fn try_sort_by Result>( list: &mut [T], cmp: C, ) -> Result<(), E> { - try_sort_by_gt(list, move |a, b| { - cmp(a, b).map(|ord| ord == Ordering::Greater) - }) + try_sort_by_cmp(list, ord_comparator(cmp)) } #[inline] @@ -41,13 +46,23 @@ pub fn sort_by Ordering>(list: &mut [T], cmp: C) { } #[inline] -pub fn sort(list: &mut [T]) { - sort_by_gt(list, |a, b| a > b) +pub fn sort(list: &mut [T]) { + sort_by(list, Ord::cmp) } trait Comparator { type Error; fn is_gt(&self, lhs: &T, rhs: &T) -> Result; + fn ordering(&self, lhs: &T, rhs: &T) -> Result { + let ord = if self.is_gt(lhs, rhs)? { + Ordering::Greater + } else if self.is_gt(rhs, lhs)? { + Ordering::Less + } else { + Ordering::Equal + }; + Ok(ord) + } } impl Comparator for F @@ -67,3 +82,23 @@ pub(crate) fn comparator( ) -> impl Comparator { f } +#[cfg(test)] +pub(crate) fn ord_t_comparator() -> impl Comparator { + ord_comparator(|a: &T, b| Ok(a.cmp(b))) +} + +pub(crate) fn ord_comparator Result>( + f: F, +) -> impl Comparator { + struct OrdComparator(F); + impl Result> Comparator for OrdComparator { + type Error = E; + fn is_gt(&self, lhs: &T, rhs: &T) -> Result { + (self.0)(lhs, rhs).map(|ord| ord == Ordering::Greater) + } + fn ordering(&self, lhs: &T, rhs: &T) -> Result { + (self.0)(lhs, rhs) + } + } + OrdComparator(f) +} diff --git a/src/merge/tests.rs b/src/merge/tests.rs index 2295f0a..c6eca46 100644 --- a/src/merge/tests.rs +++ b/src/merge/tests.rs @@ -2,7 +2,7 @@ //! sized temporary slice of the same type. Naturally, it can only merge slices //! that are themselves already sorted. -use crate::{comparator, never}; +use crate::{comparator, never, ord_t_comparator}; /// Test mergeing two empty slices. #[test] @@ -244,5 +244,5 @@ fn hi_gallop_stress() { /// Merge convenience used for tests. fn merge(list: &mut [T], first_len: usize) { - super::merge(list, first_len, &comparator(|a, b| Ok(a > b))).unwrap_or_else(never) + super::merge(list, first_len, &ord_t_comparator()).unwrap_or_else(never) } diff --git a/src/sort.rs b/src/sort.rs index 5c85e0e..3493ad2 100644 --- a/src/sort.rs +++ b/src/sort.rs @@ -141,10 +141,7 @@ impl<'a, T, C: Comparator> SortState<'a, T, C> { } /// Sorts the list using merge sort. -pub fn try_sort_by Result>( - list: &mut [T], - cmp: C, -) -> Result<(), E> { +pub(crate) fn try_sort_by>(list: &mut [T], cmp: C) -> Result<(), C::Error> { if list.len() < MIN_MERGE { insort::sort(list, &cmp) } else { diff --git a/src/sort/tests.rs b/src/sort/tests.rs index 6e73844..a6f385e 100644 --- a/src/sort/tests.rs +++ b/src/sort/tests.rs @@ -1,7 +1,7 @@ //! The top sorting algorithm; that is, the modified merge sort we keep //! talking about. -use crate::{comparator, never}; +use crate::{never, ord_t_comparator}; /// Test the sort implementation with an empty list #[test] @@ -109,7 +109,7 @@ fn stable() { /// Sort implementation convenience used for tests. fn sort(list: &mut [T]) { - super::SortState::new(list, &comparator(|a, b| Ok(a > b))) + super::SortState::new(list, &ord_t_comparator()) .sort() .unwrap_or_else(never) }