about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-01-22 19:00:15 +0000
committerbors <bors@rust-lang.org>2016-01-22 19:00:15 +0000
commitcded89a3d167a1b736669223ee1ddc1c0744d8d9 (patch)
tree0da916c67451eacf8d7f58c7a34c9a88a2b7dfab
parent8f36038490559a98efcba3521564663b15785d9c (diff)
parent7e5b9d721315611be82cc4a1f9c0e895c90b6348 (diff)
downloadrust-cded89a3d167a1b736669223ee1ddc1c0744d8d9.tar.gz
rust-cded89a3d167a1b736669223ee1ddc1c0744d8d9.zip
Auto merge of #30917 - arthurprs:bs_bounds_check, r=alexcrichton
Avoid bounds checking for binary search. All calculated indexes are safe and the branch is useless.
-rw-r--r--src/libcore/slice.rs23
-rw-r--r--src/libcoretest/slice.rs6
2 files changed, 13 insertions, 16 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 6107564b4ae..40041c748e7 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -294,22 +294,23 @@ impl<T> SliceExt for [T] {
     fn binary_search_by<F>(&self, mut f: F) -> Result<usize, usize> where
         F: FnMut(&T) -> Ordering
     {
-        let mut base : usize = 0;
-        let mut lim : usize = self.len();
+        let mut base = 0usize;
+        let mut s = self;
 
-        while lim != 0 {
-            let ix = base + (lim >> 1);
-            match f(&self[ix]) {
-                Equal => return Ok(ix),
+        loop {
+            let (head, tail) = s.split_at(s.len() >> 1);
+            if tail.is_empty() {
+                return Err(base)
+            }
+            match f(&tail[0]) {
                 Less => {
-                    base = ix + 1;
-                    lim -= 1;
+                    base += head.len() + 1;
+                    s = &tail[1..];
                 }
-                Greater => ()
+                Greater => s = head,
+                Equal => return Ok(base + head.len()),
             }
-            lim >>= 1;
         }
-        Err(base)
     }
 
     #[inline]
diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs
index d60eeb76ccd..f82ab44adad 100644
--- a/src/libcoretest/slice.rs
+++ b/src/libcoretest/slice.rs
@@ -11,24 +11,20 @@
 use core::result::Result::{Ok, Err};
 
 #[test]
-fn binary_search_not_found() {
+fn test_binary_search() {
     let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
-    let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
     let b = [1, 2, 4, 6, 7, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&6)) == Ok(3));
-    let b = [1, 2, 4, 6, 7, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&5)) == Err(3));
     let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(4));
-    let b = [1, 2, 4, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(4));
     let b = [1, 2, 4, 6, 7, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&8)) == Ok(5));
     let b = [1, 2, 4, 5, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&7)) == Err(5));
-    let b = [1, 2, 4, 5, 6, 8, 9];
     assert!(b.binary_search_by(|v| v.cmp(&0)) == Err(0));
     let b = [1, 2, 4, 5, 6, 8];
     assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));