@@ -1223,6 +1223,46 @@ pub fn rposition_between<T>(v: &[T], start: uint, end: uint,
1223
1223
None
1224
1224
}
1225
1225
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
+
1226
1266
// FIXME: if issue #586 gets implemented, could have a postcondition
1227
1267
// saying the two result lists have the same length -- or, could
1228
1268
// return a nominal record with a constraint saying that, instead of
@@ -3710,6 +3750,51 @@ mod tests {
3710
3750
assert ! ( rfind_between( v, 4 u, 4 u, f) . is_none( ) ) ;
3711
3751
}
3712
3752
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
+
3713
3798
#[ test]
3714
3799
fn reverse_and_reversed ( ) {
3715
3800
let mut v: ~[ int ] = ~[ 10 , 20 ] ;
0 commit comments