1pub use crate::bisect_right as bisect;
2pub use crate::insort_right as insort;
3
4use std::cmp::Ordering;
5use std::ops::{Bound::*, RangeBounds};
6
7pub fn insort_right_slice<T, I>(a: &mut Vec<T>, x: T, within: I)
17where
18 I: RangeBounds<usize>,
19 T: Ord,
20{
21 insort_right_slice_by(a, x, within, T::cmp);
22}
23
24pub fn insort_right<T>(a: &mut Vec<T>, x: T)
27where
28 T: Ord,
29{
30 insort_right_by(a, x, T::cmp);
31}
32
33pub fn insort_right_by<T, F>(a: &mut Vec<T>, x: T, f: F)
41where
42 T: Ord,
43 F: FnMut(&T, &T) -> Ordering,
44{
45 insort_right_slice_by(a, x, .., f);
46}
47
48pub fn insort_right_slice_by<T, I, F>(a: &mut Vec<T>, x: T, within: I, mut f: F)
60where
61 I: RangeBounds<usize>,
62 F: FnMut(&T, &T) -> Ordering,
63{
64 let lo = bisect_right_slice_by(a, within, |p| f(&x, p));
65 a.insert(lo, x);
66}
67
68pub fn bisect_right_slice<T, I>(a: &[T], x: &T, within: I) -> usize
80where
81 I: RangeBounds<usize>,
82 T: Ord,
83{
84 bisect_right_slice_by(a, within, |p| x.cmp(p))
85}
86
87pub fn bisect_right<T>(a: &[T], x: &T) -> usize
94where
95 T: Ord,
96{
97 bisect_right_slice(a, x, ..)
98}
99
100pub fn bisect_right_by<T, F>(a: &[T], f: F) -> usize
112where
113 F: FnMut(&T) -> Ordering,
114{
115 bisect_right_slice_by(a, .., f)
116}
117
118pub fn bisect_right_slice_by<T, I, F>(a: &[T], within: I, mut f: F) -> usize
134where
135 I: RangeBounds<usize>,
136 F: FnMut(&T) -> Ordering,
137{
138 let (mut lo, mut hi) = bounds_to_indices(a, within);
139 while lo < hi {
140 let mid = (lo + hi) / 2;
141 if f(&a[mid]) == Ordering::Less {
142 hi = mid;
143 } else {
144 lo = mid + 1;
145 }
146 }
147 lo
148}
149
150pub fn insort_left_slice<T, I>(a: &mut Vec<T>, x: T, within: I)
158where
159 I: RangeBounds<usize>,
160 T: Ord,
161{
162 insort_left_slice_by(a, x, within, T::cmp);
163}
164
165pub fn insort_left<T>(a: &mut Vec<T>, x: T)
169where
170 T: Ord,
171{
172 insort_left_by(a, x, T::cmp);
173}
174
175pub fn insort_left_by<T, F>(a: &mut Vec<T>, x: T, f: F)
183where
184 T: Ord,
185 F: FnMut(&T, &T) -> Ordering,
186{
187 insort_left_slice_by(a, x, .., f);
188}
189
190pub fn insort_left_slice_by<T, I, F>(a: &mut Vec<T>, x: T, within: I, mut f: F)
202where
203 I: RangeBounds<usize>,
204 F: FnMut(&T, &T) -> Ordering,
205{
206 let lo = bisect_right_slice_by(a, within, |p| f(&x, p));
207 a.insert(lo, x);
208}
209
210pub fn bisect_left_slice<T, I>(a: &[T], x: &T, within: I) -> usize
222where
223 I: RangeBounds<usize>,
224 T: Ord,
225{
226 bisect_left_slice_by(a, within, |p| p.cmp(x))
227}
228
229pub fn bisect_left<T>(a: &[T], x: &T) -> usize
236where
237 T: Ord,
238{
239 bisect_left_slice(a, x, ..)
240}
241
242pub fn bisect_left_by<T, F>(a: &[T], f: F) -> usize
254where
255 F: FnMut(&T) -> Ordering,
256{
257 bisect_left_slice_by(a, .., f)
258}
259
260pub fn bisect_left_slice_by<T, I, F>(a: &[T], within: I, mut f: F) -> usize
275where
276 I: RangeBounds<usize>,
277 F: FnMut(&T) -> Ordering,
278{
279 let (mut lo, mut hi) = bounds_to_indices(a, within);
280 while lo < hi {
281 let mid = (lo + hi) / 2;
282 let cmp = f(&a[mid]);
283 if cmp == Ordering::Less {
284 lo = mid + 1;
285 } else {
286 hi = mid;
287 }
288 }
289 lo
290}
291
292fn bounds_to_indices<T, I>(a: &[T], within: I) -> (usize, usize)
298where
299 I: RangeBounds<usize>,
300{
301 let lo = match within.start_bound() {
303 Unbounded => 0,
304 Included(i) => *i,
305 Excluded(i) => i + 1,
306 };
307
308 let hi = match within.end_bound() {
309 Unbounded => a.len(),
310 Included(i) => i + 1,
311 Excluded(i) => *i,
312 };
313
314 if hi > a.len() {
315 panic!("index out of bounds")
316 }
317
318 (lo, hi)
319}
320
321#[cfg(test)]
322mod tests {
323
324 use super::*;
325 use proptest::prelude::*;
326 use std::collections::HashSet;
327 use std::iter::FromIterator;
328
329 #[derive(Clone, Debug)]
330 struct BisectTest<T: 'static>
331 where
332 T: Ord,
333 {
334 name: &'static str,
335 a: &'static [T],
336 x: T,
337 expected_index: usize,
338 }
339
340 #[derive(Debug, Clone)]
341 enum TestDirection {
342 Left,
343 Right,
344 }
345
346 type TestCollection<T: Ord + Clone> = &'static [BisectTest<T>];
347
348 macro_rules! t {
349 ($name:ident, $a:expr, $x:expr, $expected_index:expr) => {
350 BisectTest {
351 name: stringify!($name),
352 a: $a,
353 x: $x,
354 expected_index: $expected_index,
355 }
356 };
357 }
358
359 const RIGHT_INT_CASES: TestCollection<i32> = &[
360 t!(ints_right_0, &[], 1, 0),
361 t!(ints_right_1, &[1], 0, 0),
362 t!(ints_right_2, &[1], 1, 1),
363 t!(ints_right_3, &[1], 2, 1),
364 t!(ints_right_4, &[1, 1], 0, 0),
365 t!(ints_right_5, &[1, 1], 1, 2),
366 t!(ints_right_6, &[1, 1], 2, 2),
367 t!(ints_right_7, &[1, 1, 1], 0, 0),
368 t!(ints_right_8, &[1, 1, 1], 1, 3),
369 t!(ints_right_9, &[1, 1, 1], 2, 3),
370 t!(ints_right_10, &[1, 1, 1, 1], 0, 0),
371 t!(ints_right_11, &[1, 1, 1, 1], 1, 4),
372 t!(ints_right_12, &[1, 1, 1, 1], 2, 4),
373 t!(ints_right_13, &[1, 2], 0, 0),
374 t!(ints_right_14, &[1, 2], 1, 1),
375 t!(ints_right_15, &[1, 2], 2, 2),
376 t!(ints_right_16, &[1, 2], 3, 2),
377 t!(ints_right_17, &[1, 1, 2, 2], 0, 0),
378 t!(ints_right_18, &[1, 1, 2, 2], 1, 2),
379 t!(ints_right_19, &[1, 1, 2, 2], 2, 4),
380 t!(ints_right_20, &[1, 1, 2, 2], 3, 4),
381 t!(ints_right_21, &[1, 2, 3], 0, 0),
382 t!(ints_right_22, &[1, 2, 3], 1, 1),
383 t!(ints_right_23, &[1, 2, 3], 2, 2),
384 t!(ints_right_24, &[1, 2, 3], 3, 3),
385 t!(ints_right_25, &[1, 2, 3], 4, 3),
386 t!(ints_right_26, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0),
387 t!(ints_right_27, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 1),
388 t!(ints_right_28, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 3),
389 t!(ints_right_29, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 6),
390 t!(ints_right_30, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 10),
391 t!(ints_right_31, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10),
392 ];
393
394 const LEFT_INT_CASES: TestCollection<i32> = &[
395 t!(ints_left_0, &[], 1, 0),
396 t!(ints_left_1, &[1], 0, 0),
397 t!(ints_left_2, &[1], 1, 0),
398 t!(ints_left_3, &[1], 2, 1),
399 t!(ints_left_4, &[1, 1], 0, 0),
400 t!(ints_left_5, &[1, 1], 1, 0),
401 t!(ints_left_6, &[1, 1], 2, 2),
402 t!(ints_left_7, &[1, 1, 1], 0, 0),
403 t!(ints_left_8, &[1, 1, 1], 1, 0),
404 t!(ints_left_9, &[1, 1, 1], 2, 3),
405 t!(ints_left_10, &[1, 1, 1, 1], 0, 0),
406 t!(ints_left_11, &[1, 1, 1, 1], 1, 0),
407 t!(ints_left_12, &[1, 1, 1, 1], 2, 4),
408 t!(ints_left_13, &[1, 2], 0, 0),
409 t!(ints_left_14, &[1, 2], 1, 0),
410 t!(ints_left_15, &[1, 2], 2, 1),
411 t!(ints_left_16, &[1, 2], 3, 2),
412 t!(ints_left_17, &[1, 1, 2, 2], 0, 0),
413 t!(ints_left_18, &[1, 1, 2, 2], 1, 0),
414 t!(ints_left_19, &[1, 1, 2, 2], 2, 2),
415 t!(ints_left_20, &[1, 1, 2, 2], 3, 4),
416 t!(ints_left_21, &[1, 2, 3], 0, 0),
417 t!(ints_left_22, &[1, 2, 3], 1, 0),
418 t!(ints_left_23, &[1, 2, 3], 2, 1),
419 t!(ints_left_24, &[1, 2, 3], 3, 2),
420 t!(ints_left_25, &[1, 2, 3], 4, 3),
421 t!(ints_left_26, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 0, 0),
422 t!(ints_left_27, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 1, 0),
423 t!(ints_left_28, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 2, 1),
424 t!(ints_left_29, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 3, 3),
425 t!(ints_left_30, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 4, 6),
426 t!(ints_left_31, &[1, 2, 2, 3, 3, 3, 4, 4, 4, 4], 5, 10),
427 ];
428
429 #[test]
430 fn bisect_right_precomputed() {
431 run_bisect_tests(TestDirection::Right, RIGHT_INT_CASES);
432 }
433
434 #[test]
435 fn bisect_left_precomputed() {
436 run_bisect_tests(TestDirection::Left, LEFT_INT_CASES);
437 }
438
439 #[test]
440 fn bisect_right_slice_precomputed() {
441 run_bisect_slice_tests(TestDirection::Right, RIGHT_INT_CASES);
442 }
443
444 #[test]
445 fn bisect_left_slice_precomputed() {
446 run_bisect_slice_tests(TestDirection::Left, LEFT_INT_CASES);
447 }
448
449 #[test]
450 #[should_panic]
451 fn right_slice_index_out_of_bounds() {
452 let a: Vec<u32> = (0..10).collect();
453 bisect_right_slice(&a, &10, 5..15);
455 }
456
457 #[test]
458 #[should_panic]
459 fn left_slice_index_out_of_bounds() {
460 let a: Vec<u32> = (0..10).collect();
461 bisect_left_slice(&a, &10, 5..15);
463 }
464
465 #[test]
466 #[should_panic]
467 fn right_slice_index_out_of_bounds_when_not_searched() {
468 let a: Vec<u32> = (0..10).collect();
469 bisect_right_slice(&a, &5, ..15);
471 }
472
473 #[test]
474 #[should_panic]
475 fn left_slice_index_out_of_bounds_when_not_searched() {
476 let a: Vec<u32> = (0..10).collect();
477 bisect_left_slice(&a, &5, ..15);
479 }
480
481 fn run_bisect_tests<T: Clone + Ord>(direction: TestDirection, test_cases: TestCollection<T>) {
482 let bisect_func = match direction {
483 TestDirection::Left => bisect_left,
484 TestDirection::Right => bisect_right,
485 };
486
487 for test_case in test_cases {
488 let data = test_case.a.to_vec();
489 assert_eq!(test_case.expected_index, bisect_func(&data, &test_case.x));
490 }
491 }
492
493 fn run_bisect_slice_tests<T: Clone + Ord>(
494 direction: TestDirection,
495 test_cases: TestCollection<T>,
496 ) {
497 let bisect_func = match direction {
498 TestDirection::Left => bisect_left_slice,
499 TestDirection::Right => bisect_right_slice,
500 };
501
502 for test_case in test_cases {
503 let data = test_case.a.to_vec();
504 for lo in 0..4 {
505 for hi in 3..8 {
506 let hi = std::cmp::min(data.len(), hi);
507 let ip = bisect_func(&data, &test_case.x, lo..hi);
508
509 match direction {
510 TestDirection::Left => {
511 if ip < hi {
512 assert!(test_case.x <= data[ip]);
513 }
514
515 if ip > lo {
516 assert!(data[ip - 1] < test_case.x)
517 }
518 }
519 TestDirection::Right => {
520 if ip < hi {
521 assert!(test_case.x < data[ip]);
522 }
523
524 if ip > lo {
525 assert!(data[ip - 1] <= test_case.x)
526 }
527 }
528 }
529
530 assert_eq!(
531 ip,
532 std::cmp::max(lo, std::cmp::min(hi, test_case.expected_index))
533 );
534 }
535 }
536 }
537 }
538
539 #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
540 struct Person {
541 name: String,
542 age: u32,
543 }
544
545 fn arb_person() -> impl Strategy<Value = Person> {
546 ("[a-z]*", 1..100_u32).prop_map(|(name, age)| Person { name, age })
547 }
548
549 fn check_index_right_invariant<T, F>(a: &[T], target: &T, index: usize, mut f: F)
550 where
551 F: FnMut(&T, &T) -> Ordering,
552 {
553 assert!(a[..index].iter().all(|x| match f(x, &target) {
555 Ordering::Less | Ordering::Equal => true,
556 _ => false,
557 }));
558 assert!(a[index..]
559 .iter()
560 .all(|x| f(x, &target) == Ordering::Greater));
561 }
562
563 fn check_index_left_invariant<T, F>(a: &[T], target: &T, index: usize, mut f: F)
564 where
565 F: FnMut(&T, &T) -> Ordering,
566 {
567 assert!(a[..index].iter().all(|x| f(x, &target) == Ordering::Less));
569 assert!(a[index..].iter().all(|x| match f(x, &target) {
570 Ordering::Greater | Ordering::Equal => true,
571 _ => false,
572 }));
573 }
574
575 proptest! {
576
577 #[test]
578 fn test_bisect_left_index_invariant(
579 mut nums in prop::collection::vec(any::<u32>(), 0..500),
580 num in any::<u32>()
581 ) {
582 nums.sort();
583
584 let i = bisect_left(&nums, &num);
585
586 check_index_left_invariant(&nums, &num, i, u32::cmp);
587 }
588
589 #[test]
590 fn test_bisect_left_by_index_invariant(
591 mut people in prop::collection::vec(arb_person(), 0..500),
592 new_person in arb_person()
593 ) {
594 let f = |a: &Person, b: &Person| a.age.cmp(&b.age);
596
597 people.sort_by(f);
598
599 let i = bisect_left_by(&people, |p| f(p, &new_person));
600
601 check_index_left_invariant(&people, &new_person, i, f);
602
603 let f = |a: &Person, b: &Person| a.name.cmp(&b.name);
605
606 people.sort_by(f);
607
608 let i = bisect_left_by(&people, |p| f(p, &new_person));
609
610 check_index_left_invariant(&people, &new_person, i, f);
611 }
612
613 #[test]
614 fn test_bisect_right_index_invariant(
615 mut nums in prop::collection::vec(any::<u32>(), 0..500),
616 num in any::<u32>()
617 ) {
618 nums.sort();
619
620 let i = bisect_right(&nums, &num);
621
622 check_index_right_invariant(&nums, &num, i, u32::cmp)
623 }
624
625 #[test]
626 fn test_bisect_right_by_index_invariant(
627 mut people in prop::collection::vec(arb_person(), 0..500),
628 new_person in arb_person()
629 ) {
630 let f = |a: &Person, b: &Person| a.age.cmp(&b.age);
632
633 people.sort_by(f);
634
635 let i = bisect_right_by(&people, |p| f(&new_person, p));
636
637 check_index_right_invariant(&people, &new_person, i, f);
638
639
640 let f = |a: &Person, b: &Person| a.name.cmp(&b.name);
642
643 people.sort_by(f);
644
645 let i = bisect_right_by(&people, |p| f(&new_person, p));
646
647 check_index_right_invariant(&people, &new_person, i, f);
648 }
649
650 #[test]
651 fn test_insort_vs_vec_sort(
652 digits in prop::collection::vec(0..10, 0..500)
653 ) {
654 let left_digits = HashSet::<i32>::from_iter(vec![0, 2, 4, 6, 8]);
655 let mut insorted = vec![];
656
657 for digit in digits {
658 let f = if left_digits.contains(&digit) {
659 insort_left
660 } else {
661 insort_right
662 };
663
664 f(&mut insorted, digit);
665 }
666
667 let vec_sorted = {
668 let mut v = insorted.clone();
669 v.sort();
670 v
671 };
672
673 assert_eq!(vec_sorted, insorted);
674 }
675 }
676}