Skip to content

Commit 14b7277

Browse files
committed
core: add vec::bsearch.
1 parent 2a86485 commit 14b7277

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

src/libcore/vec.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,46 @@ pub fn rposition_between<T>(v: &[T], start: uint, end: uint,
12231223
None
12241224
}
12251225
1226+
1227+
1228+
/**
1229+
* Binary search a sorted vector with a comparator function.
1230+
*
1231+
* The comparator should implement an order consistent with the sort
1232+
* order of the underlying vector, returning an order code that indicates
1233+
* whether its argument is `Less`, `Equal` or `Greater` the desired target.
1234+
*
1235+
* Returns the index where the comparator returned `Equal`, or `None` if
1236+
* not found.
1237+
*/
1238+
pub pure fn bsearch<T>(v: &[T], f: &fn(&T) -> Ordering) -> Option<uint> {
1239+
let mut base : uint = 0;
1240+
let mut lim : uint = v.len();
1241+
1242+
while lim != 0 {
1243+
let ix = base + (lim >> 1);
1244+
match f(&v[ix]) {
1245+
Equal => return Some(ix),
1246+
Less => {
1247+
base = ix + 1;
1248+
lim -= 1;
1249+
}
1250+
Greater => ()
1251+
}
1252+
lim >>= 1;
1253+
}
1254+
return None;
1255+
}
1256+
1257+
/**
1258+
* Binary search a sorted vector for a given element.
1259+
*
1260+
* Returns the index of the element or None if not found.
1261+
*/
1262+
pub pure fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> {
1263+
bsearch(v, |p| p.cmp(x))
1264+
}
1265+
12261266
// FIXME: if issue #586 gets implemented, could have a postcondition
12271267
// saying the two result lists have the same length -- or, could
12281268
// return a nominal record with a constraint saying that, instead of
@@ -3710,6 +3750,51 @@ mod tests {
37103750
assert!(rfind_between(v, 4u, 4u, f).is_none());
37113751
}
37123752

3753+
#[test]
3754+
fn test_bsearch_elem() {
3755+
fail_unless!(bsearch_elem([1,2,3,4,5], &5) == Some(4));
3756+
fail_unless!(bsearch_elem([1,2,3,4,5], &4) == Some(3));
3757+
fail_unless!(bsearch_elem([1,2,3,4,5], &3) == Some(2));
3758+
fail_unless!(bsearch_elem([1,2,3,4,5], &2) == Some(1));
3759+
fail_unless!(bsearch_elem([1,2,3,4,5], &1) == Some(0));
3760+
3761+
fail_unless!(bsearch_elem([2,4,6,8,10], &1) == None);
3762+
fail_unless!(bsearch_elem([2,4,6,8,10], &5) == None);
3763+
fail_unless!(bsearch_elem([2,4,6,8,10], &4) == Some(1));
3764+
fail_unless!(bsearch_elem([2,4,6,8,10], &10) == Some(4));
3765+
3766+
fail_unless!(bsearch_elem([2,4,6,8], &1) == None);
3767+
fail_unless!(bsearch_elem([2,4,6,8], &5) == None);
3768+
fail_unless!(bsearch_elem([2,4,6,8], &4) == Some(1));
3769+
fail_unless!(bsearch_elem([2,4,6,8], &8) == Some(3));
3770+
3771+
fail_unless!(bsearch_elem([2,4,6], &1) == None);
3772+
fail_unless!(bsearch_elem([2,4,6], &5) == None);
3773+
fail_unless!(bsearch_elem([2,4,6], &4) == Some(1));
3774+
fail_unless!(bsearch_elem([2,4,6], &6) == Some(2));
3775+
3776+
fail_unless!(bsearch_elem([2,4], &1) == None);
3777+
fail_unless!(bsearch_elem([2,4], &5) == None);
3778+
fail_unless!(bsearch_elem([2,4], &2) == Some(0));
3779+
fail_unless!(bsearch_elem([2,4], &4) == Some(1));
3780+
3781+
fail_unless!(bsearch_elem([2], &1) == None);
3782+
fail_unless!(bsearch_elem([2], &5) == None);
3783+
fail_unless!(bsearch_elem([2], &2) == Some(0));
3784+
3785+
fail_unless!(bsearch_elem([], &1) == None);
3786+
fail_unless!(bsearch_elem([], &5) == None);
3787+
3788+
fail_unless!(bsearch_elem([1,1,1,1,1], &1) != None);
3789+
fail_unless!(bsearch_elem([1,1,1,1,2], &1) != None);
3790+
fail_unless!(bsearch_elem([1,1,1,2,2], &1) != None);
3791+
fail_unless!(bsearch_elem([1,1,2,2,2], &1) != None);
3792+
fail_unless!(bsearch_elem([1,2,2,2,2], &1) == Some(0));
3793+
3794+
fail_unless!(bsearch_elem([1,2,3,4,5], &6) == None);
3795+
fail_unless!(bsearch_elem([1,2,3,4,5], &0) == None);
3796+
}
3797+
37133798
#[test]
37143799
fn reverse_and_reversed() {
37153800
let mut v: ~[int] = ~[10, 20];

0 commit comments

Comments
 (0)