Skip to content

Commit

Permalink
Galloping search for binary_search_util
Browse files Browse the repository at this point in the history
  • Loading branch information
llogiq committed Jan 12, 2020
1 parent ebbb2bf commit 0e1cd59
Showing 1 changed file with 40 additions and 20 deletions.
60 changes: 40 additions & 20 deletions src/librustc_data_structures/binary_search_util/mod.rs
Expand Up @@ -14,35 +14,55 @@ where
Ok(mid) => mid,
Err(_) => return &[],
};
let size = data.len();

// We get back *some* element with the given key -- so
// search backwards to find the *first* one.
//
// (It'd be more efficient to use a "galloping" search
// here, but it's not really worth it for small-ish
// amounts of data.)
// We get back *some* element with the given key -- so do
// a galloping search backwards to find the *first* one.
let mut start = mid;
while start > 0 {
if key_fn(&data[start - 1]) == *key {
start -= 1;
} else {
let mut previous = mid;
let mut step = 1;
loop {
start = start.saturating_sub(step);
if start == 0 || key_fn(&data[start]) != *key {
break;
}
previous = start;
step *= 2;
}
step = previous - start;
while step > 1 {
let half = step / 2;
let mid = start + half;
if key_fn(&data[mid]) != *key {
start = mid;
}
step -= half;
}
// adjust by one if we have overshot
if start < size && key_fn(&data[start]) != *key {
start += 1;
}

// Now search forward to find the *last* one.
//
// (It'd be more efficient to use a "galloping" search
// here, but it's not really worth it for small-ish
// amounts of data.)
let mut end = mid + 1;
let max = data.len();
while end < max {
if key_fn(&data[end]) == *key {
end += 1;
} else {
let mut end = mid;
let mut previous = mid;
let mut step = 1;
loop {
end = end.saturating_add(step).min(size);
if end == size || key_fn(&data[end]) != *key {
break;
}
previous = end;
step *= 2;
}
step = end - previous;
while step > 1 {
let half = step / 2;
let mid = end - half;
if key_fn(&data[mid]) != *key {
end = mid;
}
step -= half;
}

&data[start..end]
Expand Down

0 comments on commit 0e1cd59

Please sign in to comment.