Created
July 28, 2023 04:14
-
-
Save ttsugriy/757030eb2249f17e062159249e7eafa7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/compiler/rustc_data_structures/src/binary_search_util/mod.rs b/compiler/rustc_data_structures/src/binary_search_util/mod.rs | |
| index d40172a2e2f..c6e3354025a 100644 | |
| --- a/compiler/rustc_data_structures/src/binary_search_util/mod.rs | |
| +++ b/compiler/rustc_data_structures/src/binary_search_util/mod.rs | |
| @@ -10,59 +10,22 @@ pub fn binary_search_slice<'d, E, K>(data: &'d [E], key_fn: impl Fn(&E) -> K, ke | |
| where | |
| K: Ord, | |
| { | |
| - let Ok(mid) = data.binary_search_by_key(key, &key_fn) else { | |
| + let size = data.len(); | |
| + let start = data.partition_point(|x| key_fn(x) < *key); | |
| + // at this point start either points at the first entry with equal key | |
| + // or is equal to size in case all elements have smaller keys | |
| + // invariant: start == size || key_fn(&data[start]) >= *key | |
| + if start == size || key_fn(&data[start]) != *key { | |
| return &[]; | |
| }; | |
| - let size = data.len(); | |
| - | |
| - // We get back *some* element with the given key -- so do | |
| - // a galloping search backwards to find the *first* one. | |
| - let mut start = mid; | |
| - 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; | |
| - } | |
| + // invariant: start < size && key_fn(&data[start]) == *key | |
| - // Now search forward to find the *last* one. | |
| - 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; | |
| - } | |
| + // find the first entry with key > `key`. Skip `start` entries since | |
| + // key_fn(&data[start]) == *key | |
| + // invariant: offset == size || key_fn(&data[offset]) >= *key | |
| + let offset = start + 1; | |
| + let end = data[offset..].partition_point(|x| key_fn(x) <= *key) + offset; | |
| + // invariant: end == size || key_fn(&data[end]) > *key | |
| &data[start..end] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment