From 57adb459209923837721fc3f03aa7b93469c7b19 Mon Sep 17 00:00:00 2001 From: Nagata Kana Date: Tue, 12 Nov 2024 20:14:24 +0900 Subject: [PATCH] add value versions of binary searches --- libs/riff/src/binary_search.rs | 67 ++++++++++++++++++++++++------ libs/riff/src/bitmask_iterators.rs | 12 ++++-- 2 files changed, 63 insertions(+), 16 deletions(-) diff --git a/libs/riff/src/binary_search.rs b/libs/riff/src/binary_search.rs index 8518882b..f885ce55 100644 --- a/libs/riff/src/binary_search.rs +++ b/libs/riff/src/binary_search.rs @@ -6,6 +6,7 @@ use std::cmp::Ordering::Less; /// `{lower,upper}_bound`, etc pub trait BinarySearch { fn partition_point bool>(&self, pred: F) -> usize; + fn partition_point_value bool>(&self, pred: F) -> Option<&T>; fn lower_bound_by Ordering>(&self, mut f: F) -> usize { self.partition_point(|x| f(x) < Equal) } @@ -30,6 +31,30 @@ pub trait BinarySearch { { self.upper_bound_by(|p| p.cmp(x)) } + fn lower_bound_value_by Ordering>(&self, mut f: F) -> Option<&T> { + self.partition_point_value(|x| f(x) < Equal) + } + fn upper_bound_value_by Ordering>(&self, mut f: F) -> Option<&T> { + self.partition_point_value(|x| f(x) <= Equal) + } + fn lower_bound_value_by_key B>(&self, b: &B, mut f: F) -> Option<&T> { + self.lower_bound_value_by(|x| f(x).cmp(b)) + } + fn upper_bound_value_by_key B>(&self, b: &B, mut f: F) -> Option<&T> { + self.upper_bound_value_by(|x| f(x).cmp(b)) + } + fn lower_bound_value(&self, x: &T) -> Option<&T> + where + T: Ord, + { + self.lower_bound_value_by(|p| p.cmp(x)) + } + fn upper_bound_value(&self, x: &T) -> Option<&T> + where + T: Ord, + { + self.upper_bound_value_by(|p| p.cmp(x)) + } } impl BinarySearch for [T] { @@ -37,6 +62,10 @@ impl BinarySearch for [T] { self.binary_search_by(|x| if pred(x) { Less } else { Greater }) .unwrap_err() } + + fn partition_point_value bool>(&self, pred: F) -> Option<&T> { + self.get(self.partition_point(pred)) + } } #[cfg(test)] @@ -44,17 +73,31 @@ mod tests { use super::*; #[test] - fn test_vec_binary_search() { - let vec = vec![10, 12]; - assert_eq!(vec.lower_bound(&9), 0); - assert_eq!(vec.lower_bound(&10), 0); - assert_eq!(vec.lower_bound(&11), 1); - assert_eq!(vec.lower_bound(&12), 1); - assert_eq!(vec.lower_bound(&13), 2); - assert_eq!(vec.upper_bound(&9), 0); - assert_eq!(vec.upper_bound(&10), 1); - assert_eq!(vec.upper_bound(&11), 1); - assert_eq!(vec.upper_bound(&12), 2); - assert_eq!(vec.upper_bound(&13), 2); + fn test_array_binary_search() { + let array = [10, 12]; + + assert_eq!(array.lower_bound(&9), 0); + assert_eq!(array.lower_bound(&10), 0); + assert_eq!(array.lower_bound(&11), 1); + assert_eq!(array.lower_bound(&12), 1); + assert_eq!(array.lower_bound(&13), 2); + + assert_eq!(array.upper_bound(&9), 0); + assert_eq!(array.upper_bound(&10), 1); + assert_eq!(array.upper_bound(&11), 1); + assert_eq!(array.upper_bound(&12), 2); + assert_eq!(array.upper_bound(&13), 2); + + assert_eq!(array.lower_bound_value(&9), Some(&10)); + assert_eq!(array.lower_bound_value(&10), Some(&10)); + assert_eq!(array.lower_bound_value(&11), Some(&12)); + assert_eq!(array.lower_bound_value(&12), Some(&12)); + assert_eq!(array.lower_bound_value(&13), None); + + assert_eq!(array.upper_bound_value(&9), Some(&10)); + assert_eq!(array.upper_bound_value(&10), Some(&12)); + assert_eq!(array.upper_bound_value(&11), Some(&12)); + assert_eq!(array.upper_bound_value(&12), None); + assert_eq!(array.upper_bound_value(&13), None); } } diff --git a/libs/riff/src/bitmask_iterators.rs b/libs/riff/src/bitmask_iterators.rs index 35476380..a6c08fde 100644 --- a/libs/riff/src/bitmask_iterators.rs +++ b/libs/riff/src/bitmask_iterators.rs @@ -6,9 +6,11 @@ use super::numeric_traits::Unsigned; /// /// Basic usage: /// ``` -/// use bitutils::combinations; +/// use riff::bitmask_combinations; /// -/// assert_eq!(combinations::(3, 2).collect::>(), vec![3, 5, 6]); +/// assert_eq!(bitmask_combinations::(3, 2).collect::>(), vec![ +/// 3, 5, 6 +/// ]); /// ``` pub fn bitmask_combinations(n: u32, k: u32) -> BitmaskCombinations { assert!(k < T::bit_length() && k < T::bit_length()); @@ -48,9 +50,11 @@ impl Iterator for BitmaskCombinations { /// /// Basic usage: /// ``` -/// use bitutils::subsets; +/// use riff::bitmask_subsets; /// -/// assert_eq!(subsets(10u32).collect::>(), vec![0, 2, 8, 10]); +/// assert_eq!(bitmask_subsets(10u32).collect::>(), vec![ +/// 0, 2, 8, 10 +/// ]); /// ``` pub fn bitmask_subsets(bs: T) -> BitmaskSubsets { BitmaskSubsets {