|
20 | 20 | //! use ordslice::Ext;
|
21 | 21 | //!
|
22 | 22 | //! let b = [1, 3];
|
23 |
| -//! // This is faster than stdlib's binary_search! |
24 |
| -//! assert_eq!(b.fast_binary_search(&2), Err(1)); |
25 |
| -//! assert_eq!(b.fast_binary_search(&3), Ok(1)); |
26 | 23 | //!
|
27 | 24 | //! assert_eq!(b.lower_bound(&1), 0);
|
28 | 25 | //!
|
|
32 | 29 | //! ```
|
33 | 30 | //!
|
34 | 31 | //! [`slice`]: https://doc.rust-lang.org/stable/std/primitive.slice.html
|
35 |
| -use std::cmp::Ordering::{self, Less, Equal, Greater}; |
| 32 | +use std::cmp::Ordering::{self, Less, Greater}; |
36 | 33 |
|
37 | 34 | /// Extends [`slice`] with fast operations on ordered slices.
|
38 | 35 | ///
|
39 | 36 | /// [`slice`]: https://doc.rust-lang.org/stable/std/primitive.slice.html
|
40 | 37 | pub trait Ext {
|
41 | 38 | type Item;
|
42 | 39 |
|
43 |
| - /// Checks if `x` appears in the ordered slice. |
44 |
| - /// |
45 |
| - /// Returns `Ok(i)` where `i` is the index of the matching element, `Err(i)` |
46 |
| - /// otherwise where `i` is the index where the element should be inserted to |
47 |
| - /// preserve the slice's ordering. |
48 |
| - /// |
49 |
| - /// The slice MUST be ordered by the order defined by its elements. |
50 |
| - /// |
51 |
| - /// Note: this is the same as [`binary_search`] but faster. |
52 |
| - /// |
53 |
| - /// | name |std (ns) |fast (ns) |diff (ns) | diff (%) | speedup | |
54 |
| - /// | -----------|---------|----------|----------|----------|---------| |
55 |
| - /// | l1::dups | 31 | 10 | -21 | -67.74% | x 3.10 | |
56 |
| - /// | l1::unique | 35 | 10 | -25 | -71.43% | x 3.50 | |
57 |
| - /// | l2::dups | 54 | 19 | -35 | -64.81% | x 2.84 | |
58 |
| - /// | l2::unique | 58 | 19 | -39 | -67.24% | x 3.05 | |
59 |
| - /// | l3::dups | 136 | 82 | -54 | -39.71% | x 1.66 | |
60 |
| - /// | l3::unique | 139 | 84 | -55 | -39.57% | x 1.65 | |
61 |
| - /// |
62 |
| - /// [`binary_search`]: |
63 |
| - /// https://doc.rust-lang.org/std/primitive.slice.html#method.binary_search |
64 |
| - fn fast_binary_search(&self, x: &Self::Item) -> Result<usize, usize> |
65 |
| - where |
66 |
| - Self::Item: Ord; |
67 |
| - |
68 |
| - /// Check if there is an element `e` in the ordered slice such that `f(e) == |
69 |
| - /// Equal`. |
70 |
| - /// |
71 |
| - /// The slice MUST be ordered by the order defined by the comparator |
72 |
| - /// function. The comparator function should take an element and return |
73 |
| - /// `Ordering` that is consistent with the ordering of the slice. Returns |
74 |
| - /// `Ok(i)` where `i` is the index of the matching element, `Err(i)` |
75 |
| - /// otherwise where `i` is the index where the element should be inserted to |
76 |
| - /// preserve the slice's ordering. |
77 |
| - /// |
78 |
| - /// # Example: |
79 |
| - /// |
80 |
| - /// ``` |
81 |
| - /// # use ordslice::Ext; |
82 |
| - /// let b = [1, 2, 3, 6, 9, 9]; |
83 |
| - /// assert_eq!(b.fast_binary_search(&3), b.fast_binary_search_by(|x| x.cmp(&3))); |
84 |
| - /// ``` |
85 |
| - fn fast_binary_search_by<'a, F>(&'a self, f: F) -> Result<usize, usize> |
86 |
| - where |
87 |
| - F: FnMut(&'a Self::Item) -> Ordering; |
88 |
| - |
89 |
| - /// Check if there is an element `e` in the ordered slice such that `f(e) == |
90 |
| - /// k`. |
91 |
| - /// |
92 |
| - /// The slice MUST be ordered by the order defined by the keys of its |
93 |
| - /// elements. Returns `Ok(i)` where `i` is the index of the matching |
94 |
| - /// element, `Err(i)` otherwise where `i` is the index where the element |
95 |
| - /// should be inserted to preserve the slice's ordering. |
96 |
| - /// |
97 |
| - /// # Example: |
98 |
| - /// |
99 |
| - /// ``` |
100 |
| - /// # use ordslice::Ext; |
101 |
| - /// let b = [1, 2, 3, 6, 9, 9]; |
102 |
| - /// assert_eq!(b.fast_binary_search(&3), b.fast_binary_search_by_key(&6, |x| x * 2)); |
103 |
| - /// ``` |
104 |
| - fn fast_binary_search_by_key<'a, K, F>(&'a self, k: &K, f: F) -> Result<usize, usize> |
105 |
| - where |
106 |
| - F: FnMut(&'a Self::Item) -> K, |
107 |
| - K: Ord; |
108 |
| - |
109 | 40 | /// Returns the index `i` pointing to the first element in the ordered slice
|
110 | 41 | /// that is _not less_ than `x`.
|
111 | 42 | ///
|
@@ -289,44 +220,6 @@ pub trait Ext {
|
289 | 220 | impl<T> Ext for [T] {
|
290 | 221 | type Item = T;
|
291 | 222 |
|
292 |
| - fn fast_binary_search(&self, x: &Self::Item) -> Result<usize, usize> |
293 |
| - where |
294 |
| - T: Ord, |
295 |
| - { |
296 |
| - self.fast_binary_search_by(|y| y.cmp(x)) |
297 |
| - } |
298 |
| - fn fast_binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize> |
299 |
| - where |
300 |
| - F: FnMut(&'a Self::Item) -> Ordering, |
301 |
| - { |
302 |
| - let s = self; |
303 |
| - let mut size = s.len(); |
304 |
| - if size == 0 { |
305 |
| - return Err(0); |
306 |
| - } |
307 |
| - let mut base = 0usize; |
308 |
| - while size > 1 { |
309 |
| - let half = size / 2; |
310 |
| - let mid = base + half; |
311 |
| - let cmp = f(unsafe { s.get_unchecked(mid) }); |
312 |
| - base = if cmp == Greater { base } else { mid }; |
313 |
| - size -= half; |
314 |
| - } |
315 |
| - let cmp = f(unsafe { s.get_unchecked(base) }); |
316 |
| - if cmp == Equal { |
317 |
| - Ok(base) |
318 |
| - } else { |
319 |
| - Err(base + (cmp == Less) as usize) |
320 |
| - } |
321 |
| - } |
322 |
| - fn fast_binary_search_by_key<'a, K, F>(&'a self, k: &K, mut f: F) -> Result<usize, usize> |
323 |
| - where |
324 |
| - F: FnMut(&'a Self::Item) -> K, |
325 |
| - K: Ord, |
326 |
| - { |
327 |
| - self.fast_binary_search_by(|e| f(e).cmp(k)) |
328 |
| - } |
329 |
| - |
330 | 223 | fn lower_bound(&self, x: &Self::Item) -> usize
|
331 | 224 | where
|
332 | 225 | T: Ord,
|
@@ -445,20 +338,6 @@ impl<T> Ext for [T] {
|
445 | 338 | mod tests {
|
446 | 339 | use super::Ext;
|
447 | 340 |
|
448 |
| - #[test] |
449 |
| - fn binary_search() { |
450 |
| - let b: [u32; 0] = []; |
451 |
| - assert_eq!(b.fast_binary_search(&0), Err(0)); |
452 |
| - let b = [1, 3, 3, 5]; |
453 |
| - assert_eq!(b.fast_binary_search(&0), Err(0)); |
454 |
| - assert_eq!(b.fast_binary_search(&1), Ok(0)); |
455 |
| - assert_eq!(b.fast_binary_search(&2), Err(1)); |
456 |
| - assert_eq!(b.fast_binary_search(&3), Ok(2)); |
457 |
| - assert_eq!(b.fast_binary_search(&4), Err(3)); |
458 |
| - assert_eq!(b.fast_binary_search(&5), Ok(3)); |
459 |
| - assert_eq!(b.fast_binary_search(&6), Err(4)); |
460 |
| - } |
461 |
| - |
462 | 341 | #[test]
|
463 | 342 | fn lower_bound() {
|
464 | 343 | let b: [u32; 0] = [];
|
|
0 commit comments