use std::cmp;
#[cfg(test)]
extern crate rand;
#[cfg(test)]
use self::rand::distributions::{Distribution, Uniform};
pub fn upper_bound<T>(arr: &[T], v: &T) -> usize
where
T: cmp::Ord,
{
let mut l = 0;
let mut r = arr.len();
while l < r {
let m = (l + r) / 2;
let vm = &arr[m];
match vm.cmp(v) {
cmp::Ordering::Less => {
l = m + 1;
}
cmp::Ordering::Greater => {
r = m;
}
cmp::Ordering::Equal => {
l = m + 1;
}
}
}
assert_eq!(l, r);
l
}
#[test]
fn test_upper_bound() {
let distr = Uniform::from(0..20);
let mut rng = rand::thread_rng();
let mut arr = (0..1000)
.map(|_| distr.sample(&mut rng))
.collect::<Vec<_>>();
arr.sort();
let val = distr.sample(&mut rng);
let idx = upper_bound(&arr[..], &val);
let mut check = 0;
for (i, v) in arr.iter().enumerate() {
check = i;
if *v > val {
break;
}
}
assert_eq!(check, idx);
}
#[test]
fn test_upper_bound_end() {
let distr = Uniform::from(0..20);
let mut rng = rand::thread_rng();
let mut arr = (0..1000)
.map(|_| distr.sample(&mut rng))
.collect::<Vec<_>>();
arr.sort();
let val = 99;
let idx = upper_bound(&arr[..], &val);
assert_eq!(arr.len(), idx);
}