use crate::if_return;
use std::cmp::{Ord, Ordering};
#[inline(always)]
pub fn binary_search<T>(arr: &[T], target: &T) -> Result<usize, usize>
where
T: Ord,
{
binary_search_by(arr, target, T::cmp)
}
pub fn binary_search_by<T1, T2, Cmp>(arr: &[T1], target: &T2, cmp: Cmp) -> Result<usize, usize>
where
Cmp: Fn(&T2, &T1) -> Ordering,
{
if_return! { arr.is_empty() => Err(0) }
let mut left = 0;
let mut right = arr.len() - 1;
let mut mid = left + (right - left) / 2;
while left <= right {
mid = left + (right - left) / 2;
match cmp(target, &arr[mid]) {
Ordering::Equal => return Ok(mid),
Ordering::Greater => left = mid + 1,
Ordering::Less => match mid == 0 {
true => break,
false => right = mid - 1, },
}
}
Err(match cmp(target, &arr[mid]) == Ordering::Greater {
true => mid + 1,
false => mid,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{prelude::tests::__test_search, test_search};
#[test]
fn test_binary_search() {
test_search!(binary_search);
}
}