1#![doc(html_root_url = "https://docs.rs/fixed_heap")]
3#![crate_name = "fixed_heap"]
4#![warn(
5 missing_debug_implementations,
6 trivial_casts,
7 trivial_numeric_casts,
8 unused_lifetimes,
9 unused_import_braces,
10 clippy::shadow_unrelated
11)]
12#![deny(missing_docs, unsafe_op_in_unsafe_fn)]
13#![cfg_attr(all(feature = "unstable"), feature(slice_swap_unchecked))]
14#![cfg_attr(not(test), no_std)]
15
16use core::{
17 fmt::{Debug, Formatter, Result},
18 iter::FusedIterator,
19 mem::{self, ManuallyDrop, MaybeUninit},
20 slice::{Iter, IterMut},
21};
22
23pub struct FixedHeap<T, const N: usize> {
25 high: usize,
26 data: [MaybeUninit<T>; N],
27}
28
29impl<T, const N: usize> FixedHeap<T, N> {
30 pub fn new() -> Self {
42 Self {
43 high: 0,
44 data: [const { MaybeUninit::uninit() }; N],
45 }
46 }
47
48 pub fn copy_from_slice(&mut self, slice: &[T])
62 where
63 T: Copy,
64 {
65 assert!(slice.len() <= N);
66 self.high = slice.len();
67 self.as_slice_mut().copy_from_slice(slice);
68 }
69
70 #[inline(always)]
87 pub fn peek(&self) -> Option<&T> {
88 self.peek_at(0)
89 }
90
91 #[inline(always)]
109 pub fn peek_at(&self, index: usize) -> Option<&T> {
110 if index < self.high {
113 Some(unsafe { self.data.get_unchecked(index).assume_init_ref() })
114 } else {
115 None
116 }
117 }
118
119 pub fn add_last(&mut self, value: T) -> Option<T> {
142 if self.high == N {
143 Some(value)
145 } else {
146 unsafe {
150 *self.data.get_unchecked_mut(self.high) = MaybeUninit::new(value);
151 }
152 self.high += 1;
153 None
154 }
155 }
156
157 pub fn swap_remove(&mut self, index: usize) -> Option<T> {
185 if index < self.high {
186 self.high -= 1;
187
188 let removed_node = unsafe { self.data.get_unchecked(index).assume_init_read() };
192 unsafe {
194 *self.data.get_unchecked_mut(index) =
195 MaybeUninit::new(self.data.get_unchecked(self.high).assume_init_read());
196 }
197
198 Some(removed_node)
199 } else {
200 None
201 }
202 }
203
204 pub fn push<S, F>(&mut self, value: T, comparer: &F, state: &S) -> Option<T>
250 where
251 F: Fn(&T, &T, &S) -> bool,
252 {
253 let mut result = None;
254 let mut node_index = self.high;
255 if let Some(value) = self.add_last(value) {
256 if N == 0 {
258 return Some(value);
260 } else if self.high == N {
261 let mut smallest_index = N >> 1;
265 for index in N >> 1..N {
266 let node = unsafe { self.data.get_unchecked(index).assume_init_ref() };
267 let smallest =
268 unsafe { self.data.get_unchecked(smallest_index).assume_init_ref() };
269 if comparer(smallest, node, state) {
270 smallest_index = index;
271 }
272 }
273 let smallest = unsafe { self.data.get_unchecked(smallest_index).assume_init_ref() };
274 if comparer(&value, smallest, state) {
275 let replaced = mem::replace(
276 unsafe { self.data.get_unchecked_mut(smallest_index) },
277 MaybeUninit::new(value),
278 );
279 node_index = smallest_index;
280 result = Some(unsafe { replaced.assume_init() });
281 } else {
282 return Some(value);
283 }
284 }
285 }
286
287 while node_index != 0 {
288 let parent_index = (node_index - 1) >> 1;
289 let node = unsafe { self.data.get_unchecked(node_index).assume_init_ref() };
292 let parent = unsafe { self.data.get_unchecked(parent_index).assume_init_ref() };
293 if !comparer(node, parent, state) {
294 break;
295 }
296
297 #[cfg(feature = "unstable")]
298 unsafe {
299 self.data.swap_unchecked(node_index, parent_index);
300 }
301 #[cfg(not(feature = "unstable"))]
302 self.data.swap(node_index, parent_index);
303
304 node_index = parent_index;
305 }
306
307 result
308 }
309
310 pub fn pop<S, F>(&mut self, comparer: &F, state: &S) -> Option<T>
354 where
355 F: Fn(&T, &T, &S) -> bool,
356 {
357 self.pop_at(0, comparer, state)
358 }
359
360 pub fn pop_at<S, F>(&mut self, index: usize, comparer: &F, state: &S) -> Option<T>
407 where
408 F: Fn(&T, &T, &S) -> bool,
409 {
410 if let Some(removed_node) = self.swap_remove(index) {
411 if index >= self.high {
414 return Some(removed_node);
415 }
416 let mut node_index: usize = index;
417 loop {
418 let lchild_index = (node_index << 1) + 1;
419 let rchild_index = (node_index << 1) + 2;
420 let node = unsafe { self.data.get_unchecked(node_index).assume_init_ref() };
423 let swap = if rchild_index < self.high {
425 let lchild = unsafe { self.data.get_unchecked(lchild_index).assume_init_ref() };
426 let rchild = unsafe { self.data.get_unchecked(rchild_index).assume_init_ref() };
427 match comparer(lchild, rchild, state) {
428 true => (comparer(lchild, node, state), lchild_index),
429 false => (comparer(rchild, node, state), rchild_index),
430 }
431 } else if lchild_index < self.high {
432 let lchild = unsafe { self.data.get_unchecked(lchild_index).assume_init_ref() };
433 (comparer(lchild, node, state), lchild_index)
434 } else {
435 (false, 0)
436 };
437 if let (true, compared_index) = swap {
439 #[cfg(feature = "unstable")]
440 unsafe {
441 self.data.swap_unchecked(node_index, compared_index);
442 }
443 #[cfg(not(feature = "unstable"))]
444 self.data.swap(node_index, compared_index);
445
446 node_index = compared_index;
447 } else {
448 break;
449 }
450 }
451
452 if node_index == index {
455 while node_index != 0 {
456 let parent_index = (node_index - 1) >> 1;
457 let node = unsafe { self.data.get_unchecked(node_index).assume_init_ref() };
458 let parent = unsafe { self.data.get_unchecked(parent_index).assume_init_ref() };
459 if !comparer(node, parent, state) {
460 break;
461 }
462
463 #[cfg(feature = "unstable")]
464 unsafe {
465 self.data.swap_unchecked(node_index, parent_index);
466 }
467 #[cfg(not(feature = "unstable"))]
468 self.data.swap(node_index, parent_index);
469
470 node_index = parent_index;
471 }
472 }
473
474 Some(removed_node)
475 } else {
476 None
477 }
478 }
479
480 #[inline(always)]
482 pub fn as_slice(&self) -> &[T] {
483 unsafe { core::slice::from_raw_parts(self.data.as_ptr() as *const T, self.high) }
484 }
485
486 #[inline(always)]
489 pub fn as_slice_mut(&mut self) -> &mut [T] {
490 unsafe { core::slice::from_raw_parts_mut(self.data.as_mut_ptr() as *mut T, self.high) }
491 }
492
493 #[inline(always)]
496 pub fn iter(&self) -> Iter<'_, T> {
497 self.as_slice().iter()
498 }
499
500 #[inline(always)]
504 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
505 self.as_slice_mut().iter_mut()
506 }
507
508 #[inline(always)]
520 pub fn len(&self) -> usize {
521 self.high
522 }
523
524 #[inline(always)]
537 pub fn is_empty(&self) -> bool {
538 self.high == 0
539 }
540
541 #[inline(always)]
554 pub fn is_full(&self) -> bool {
555 self.high == N
556 }
557}
558
559unsafe impl<T: Sync, const N: usize> Sync for FixedHeap<T, N> {}
560unsafe impl<T: Send, const N: usize> Send for FixedHeap<T, N> {}
561
562impl<T, const N: usize> Drop for FixedHeap<T, N> {
563 #[inline(always)]
564 fn drop(&mut self) {
565 for i in 0..self.high {
566 unsafe { self.data.get_unchecked_mut(i).assume_init_drop() };
567 }
568 }
569}
570
571impl<T, const N: usize> Debug for FixedHeap<T, N>
572where
573 T: Debug,
574{
575 fn fmt(&self, f: &mut Formatter) -> Result {
576 f.debug_struct("FixedHeap")
577 .field("high", &self.high)
578 .field("data", &self.as_slice())
579 .finish()
580 }
581}
582
583impl<T, const N: usize> Default for FixedHeap<T, N> {
584 fn default() -> Self {
585 Self::new()
586 }
587}
588
589impl<'a, T: 'a, const N: usize> IntoIterator for &'a FixedHeap<T, N> {
590 type Item = &'a T;
591 type IntoIter = Iter<'a, T>;
592
593 fn into_iter(self) -> Self::IntoIter {
594 self.iter()
595 }
596}
597
598impl<'a, T: 'a, const N: usize> IntoIterator for &'a mut FixedHeap<T, N> {
599 type Item = &'a mut T;
600 type IntoIter = IterMut<'a, T>;
601
602 fn into_iter(self) -> Self::IntoIter {
603 self.iter_mut()
604 }
605}
606
607impl<T, const N: usize> IntoIterator for FixedHeap<T, N> {
608 type Item = T;
609 type IntoIter = IntoIter<T, N>;
610
611 fn into_iter(self) -> Self::IntoIter {
612 IntoIter {
613 next: 0,
614 heap: ManuallyDrop::new(self),
615 }
616 }
617}
618
619#[derive(Debug)]
621pub struct IntoIter<T, const N: usize> {
622 next: usize,
623 heap: ManuallyDrop<FixedHeap<T, N>>,
624}
625
626impl<T, const N: usize> Iterator for IntoIter<T, N> {
627 type Item = T;
628
629 fn next(&mut self) -> Option<T> {
630 if self.next < self.heap.high {
631 let index = self.next;
632 self.next += 1;
633 Some(unsafe { self.heap.data.get_unchecked(index).assume_init_read() })
637 } else {
638 None
639 }
640 }
641
642 fn size_hint(&self) -> (usize, Option<usize>) {
643 let size = self.heap.high - self.next;
644 (size, Some(size))
645 }
646}
647
648impl<T, const N: usize> Drop for IntoIter<T, N> {
649 #[inline(always)]
650 fn drop(&mut self) {
651 for i in self.next..self.heap.high {
652 unsafe { self.heap.data[i].assume_init_drop() };
655 }
656 }
657}
658
659impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {}
660impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
661
662#[cfg(test)]
663mod test {
664 use crate::*;
665 use core::cell::RefCell;
666 use rand::{Rng, rngs::ThreadRng};
667
668 #[test]
669 fn test_default() {
670 let heap: FixedHeap<i32, 4> = FixedHeap::default();
671 assert_eq!(&[0; 0], heap.as_slice());
672 }
673
674 #[test]
675 fn test_copy_from_slice() {
676 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
677 heap.copy_from_slice(&[0, 3]);
678 assert_eq!(&[0, 3], heap.as_slice());
679 heap.copy_from_slice(&[]);
680 assert_eq!(&[0; 0], heap.as_slice());
681 heap.copy_from_slice(&[1, 3, 6, 2]);
682 assert_eq!(&[1, 3, 6, 2], heap.as_slice());
683 }
684
685 #[test]
686 fn test_push_peek_pop() {
687 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
688 let comparer = |a: &i32, b: &i32, _: &()| a > b;
689 assert_eq!(None, heap.peek());
690 assert_eq!(heap.push(1, &comparer, &()), None);
691 assert_eq!(Some(&1), heap.peek());
692 assert_eq!(heap.push(3, &comparer, &()), None);
693 assert_eq!(Some(&3), heap.peek());
694 assert_eq!(heap.push(2, &comparer, &()), None);
695 assert_eq!(Some(&3), heap.peek());
696
697 assert_eq!(Some(3), heap.pop(&comparer, &()));
698 assert_eq!(Some(&2), heap.peek());
699 assert_eq!(Some(2), heap.pop(&comparer, &()));
700 assert_eq!(Some(&1), heap.peek());
701 assert_eq!(Some(1), heap.pop(&comparer, &()));
702 assert_eq!(None, heap.peek());
703 assert_eq!(None, heap.pop(&comparer, &()));
704 }
705
706 #[test]
707 fn test_add_last_swap_remove() {
708 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
709 assert_eq!(heap.add_last(1), None);
710 assert_eq!(heap.add_last(2), None);
711 assert_eq!(heap.add_last(4), None);
712 assert_eq!(heap.add_last(3), None);
713 assert_eq!(heap.add_last(5), Some(5));
714
715 assert_eq!(Some(1), heap.swap_remove(0));
716 assert_eq!(Some(3), heap.swap_remove(0));
717 assert_eq!(Some(4), heap.swap_remove(0));
718 assert_eq!(Some(2), heap.swap_remove(0));
719 assert_eq!(None, heap.swap_remove(0));
720 }
721
722 #[test]
723 fn test_push_full() {
724 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
725 let comparer = |a: &i32, b: &i32, _: &()| a > b;
726 assert_eq!(heap.push(1, &comparer, &()), None);
727 assert_eq!(heap.push(2, &comparer, &()), None);
728 assert_eq!(heap.push(4, &comparer, &()), None);
729 assert_eq!(heap.push(3, &comparer, &()), None);
730 assert_eq!(heap.push(5, &comparer, &()), Some(1));
731
732 assert_eq!(Some(5), heap.pop(&comparer, &()));
733 assert_eq!(Some(4), heap.pop(&comparer, &()));
734 assert_eq!(Some(3), heap.pop(&comparer, &()));
735 assert_eq!(Some(2), heap.pop(&comparer, &()));
736 assert_eq!(None, heap.pop(&comparer, &()));
737 }
738
739 #[test]
740 fn test_push_pop_equal() {
741 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
742 let comparer = |a: &i32, b: &i32, _: &()| a > b;
743 assert_eq!(heap.push(7, &comparer, &()), None);
744 assert_eq!(heap.push(7, &comparer, &()), None);
745 assert_eq!(heap.push(7, &comparer, &()), None);
746
747 assert_eq!(Some(7), heap.pop(&comparer, &()));
748 assert_eq!(Some(7), heap.pop(&comparer, &()));
749 assert_eq!(Some(7), heap.pop(&comparer, &()));
750 assert_eq!(None, heap.pop(&comparer, &()));
751 }
752
753 #[test]
754 fn test_keys() {
755 let mut heap: FixedHeap<usize, 4> = FixedHeap::new();
756 fn comparer(a: &usize, b: &usize, state: &[i32; 4]) -> bool {
757 state[*a] > state[*b]
758 }
759 let state = [1, 3, 1, 2];
760 assert_eq!(heap.push(0, &comparer, &state), None);
761 assert_eq!(heap.push(1, &comparer, &state), None);
762 assert_eq!(heap.push(3, &comparer, &state), None);
763
764 assert_eq!(Some(1), heap.pop(&comparer, &state));
765 assert_eq!(Some(3), heap.pop(&comparer, &state));
766 assert_eq!(Some(0), heap.pop(&comparer, &state));
767 assert_eq!(None, heap.pop(&comparer, &state));
768 }
769
770 #[test]
771 fn test_as_slice() {
772 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
773 let comparer = |a: &i32, b: &i32, _: &()| a > b;
774 assert_eq!(heap.push(7, &comparer, &()), None);
775 assert_eq!(heap.push(9, &comparer, &()), None);
776 assert_eq!(heap.push(2, &comparer, &()), None);
777 assert_eq!(heap.push(5, &comparer, &()), None);
778 assert_eq!(heap.push(8, &comparer, &()), None);
779 assert_eq!(heap.push(8, &comparer, &()), None);
780 assert_eq!(heap.push(3, &comparer, &()), None);
781
782 let slice = heap.as_slice();
783 assert_eq!(7, slice.len());
784 assert_eq!(9, slice[0]);
785 assert_eq!(8, slice[1]);
786 assert_eq!(8, slice[2]);
787 assert_eq!(5, slice[3]);
788 assert_eq!(7, slice[4]);
789 assert_eq!(2, slice[5]);
790 assert_eq!(3, slice[6]);
791 }
792
793 #[test]
794 fn test_debug() {
795 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
796 let comparer = |a: &i32, b: &i32, _: &()| a > b;
797 assert_eq!(heap.push(7, &comparer, &()), None);
798 assert_eq!(heap.push(9, &comparer, &()), None);
799 assert_eq!(heap.push(2, &comparer, &()), None);
800 assert_eq!(heap.push(5, &comparer, &()), None);
801 assert_eq!(heap.push(8, &comparer, &()), None);
802 assert_eq!(heap.push(8, &comparer, &()), None);
803 assert_eq!(heap.push(3, &comparer, &()), None);
804 assert_eq!(
805 format!("{:?}", heap.into_iter()),
806 "IntoIter { next: 0, heap: ManuallyDrop { value: FixedHeap { high: 7, data: [9, 8, 8, 5, 7, 2, 3] } } }"
807 );
808 }
809
810 #[test]
811 fn test_iter() {
812 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
813 assert_eq!(None, heap.iter().next());
814 heap.copy_from_slice(&[2, 3, 6]);
815 let mut iter = heap.iter();
816 assert_eq!(Some(&2), iter.next());
817 assert_eq!(Some(&3), iter.next());
818 assert_eq!(Some(&6), iter.next());
819 assert_eq!(None, iter.next());
820 }
821
822 #[test]
823 fn test_iter_mut() {
824 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
825 assert_eq!(None, heap.iter_mut().next());
826 heap.copy_from_slice(&[2, 3, 6]);
827 let mut iter = heap.iter_mut();
828 *iter.next().unwrap() = 5;
829 *iter.next().unwrap() = 4;
830 *iter.next().unwrap() = 2;
831 assert_eq!(&[5, 4, 2], heap.as_slice());
832 }
833
834 #[test]
835 fn test_into_iter() {
836 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
837 heap.copy_from_slice(&[2, 3, 6]);
838 let mut iter = heap.into_iter();
839 assert_eq!((3, Some(3)), iter.size_hint());
840 assert_eq!(Some(2), iter.next());
841 assert_eq!(Some(3), iter.next());
842 assert_eq!(Some(6), iter.next());
843 assert_eq!(None, iter.next());
844 }
845
846 #[test]
847 fn test_into_iter_ref() {
848 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
849 assert_eq!(None, (&heap).into_iter().next());
850 heap.copy_from_slice(&[2, 3, 6]);
851 let mut iter = (&heap).into_iter();
852 assert_eq!(Some(&2), iter.next());
853 assert_eq!(Some(&3), iter.next());
854 assert_eq!(Some(&6), iter.next());
855 assert_eq!(None, iter.next());
856 }
857
858 #[test]
859 fn test_into_iter_mut() {
860 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
861 assert_eq!(None, (&mut heap).into_iter().next());
862 heap.copy_from_slice(&[2, 3, 6]);
863 let mut iter = (&mut heap).into_iter();
864 *iter.next().unwrap() = 5;
865 *iter.next().unwrap() = 4;
866 *iter.next().unwrap() = 2;
867 assert_eq!(&[5, 4, 2], heap.as_slice());
868 }
869
870 #[test]
871 fn test_len() {
872 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
873 assert_eq!(0, heap.len());
874 heap.copy_from_slice(&[2, 3, 6]);
875 assert_eq!(3, heap.len());
876 }
877
878 #[test]
879 fn test_is_empty() {
880 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
881 assert!(heap.is_empty());
882 heap.copy_from_slice(&[2, 3, 6]);
883 assert!(!heap.is_empty());
884 }
885
886 #[test]
887 fn test_is_full() {
888 let mut heap: FixedHeap<i32, 4> = FixedHeap::new();
889 assert!(!heap.is_full());
890 heap.copy_from_slice(&[2, 3, 6]);
891 assert!(!heap.is_full());
892 heap.copy_from_slice(&[4, 1, 5, 3]);
893 assert!(heap.is_full());
894 }
895
896 #[test]
897 fn test_drop() {
898 let drops = RefCell::new(0usize);
899 {
900 let comparer = |_: &_, _: &_, _: &()| false;
901 let mut list: FixedHeap<DropCounted, 16> = FixedHeap::new();
902 for _ in 0..11 {
903 list.push(DropCounted(&drops), &comparer, &());
904 }
905 assert_eq!(*drops.borrow(), 0);
906
907 for _ in 0..4 {
909 list.pop(&comparer, &());
910 }
911 assert_eq!(*drops.borrow(), 4);
912
913 let mut iter = list.into_iter();
915 assert_eq!(*drops.borrow(), 4);
916
917 iter.next();
919 assert_eq!(*drops.borrow(), 5);
920
921 }
923 assert_eq!(*drops.borrow(), 11);
924 }
925
926 struct DropCounted<'a>(&'a RefCell<usize>);
927
928 impl<'a> Drop for DropCounted<'a> {
929 fn drop(&mut self) {
930 *self.0.borrow_mut() += 1;
931 }
932 }
933
934 #[test]
935 fn test_pop_at_sift_up() {
936 let mut heap: FixedHeap<i32, 16> = FixedHeap::new();
938 let comparer = |a: &i32, b: &i32, _: &()| a > b;
939 for &v in &[50, 10, 30, 5, 8, 25, 28] {
940 heap.push(v, &comparer, &());
941 }
942 assert_eq!(heap.pop_at(3, &comparer, &()), Some(5));
943 assert_eq!(heap.pop(&comparer, &()), Some(50));
944 assert_eq!(heap.pop(&comparer, &()), Some(30));
945 assert_eq!(heap.pop(&comparer, &()), Some(28));
946 assert_eq!(heap.pop(&comparer, &()), Some(25));
947 assert_eq!(heap.pop(&comparer, &()), Some(10));
948 assert_eq!(heap.pop(&comparer, &()), Some(8));
949 assert_eq!(heap.pop(&comparer, &()), None);
950 }
951
952 #[test]
953 fn test_fuzz_gt_partial() {
954 let gt = |a: &i8, b: &i8, _: &()| a > b;
955 fuzz::<_, 8, 7>(10, >);
956 fuzz::<_, 9, 7>(10, >);
957 fuzz::<_, 10, 7>(10, >);
958 fuzz::<_, 11, 7>(10, >);
959 fuzz::<_, 12, 7>(10, >);
960 fuzz::<_, 13, 7>(10, >);
961 fuzz::<_, 14, 7>(10, >);
962 fuzz::<_, 15, 7>(10, >);
963 fuzz::<_, 16, 7>(10, >);
964 }
965
966 #[test]
967 fn test_fuzz_gt_full() {
968 let gt = |a: &i8, b: &i8, _: &()| a > b;
969 fuzz::<_, 0, 4>(10, >);
970 fuzz::<_, 1, 4>(10, >);
971 fuzz::<_, 2, 4>(10, >);
972 fuzz::<_, 3, 4>(10, >);
973 fuzz::<_, 8, 16>(10, >);
974 fuzz::<_, 9, 16>(10, >);
975 fuzz::<_, 10, 16>(10, >);
976 fuzz::<_, 11, 16>(10, >);
977 fuzz::<_, 12, 16>(10, >);
978 fuzz::<_, 13, 16>(10, >);
979 fuzz::<_, 14, 16>(10, >);
980 fuzz::<_, 15, 16>(10, >);
981 }
982
983 #[test]
984 fn test_fuzz_ge_partial() {
985 let ge = |a: &i8, b: &i8, _: &()| a >= b;
986 fuzz::<_, 8, 7>(10, &ge);
987 fuzz::<_, 9, 7>(10, &ge);
988 fuzz::<_, 10, 7>(10, &ge);
989 fuzz::<_, 11, 7>(10, &ge);
990 fuzz::<_, 12, 7>(10, &ge);
991 fuzz::<_, 13, 7>(10, &ge);
992 fuzz::<_, 14, 7>(10, &ge);
993 fuzz::<_, 15, 7>(10, &ge);
994 fuzz::<_, 16, 7>(10, &ge);
995 }
996
997 #[test]
998 fn test_fuzz_ge_full() {
999 let ge = |a: &i8, b: &i8, _: &()| a >= b;
1000 fuzz::<_, 0, 4>(10, &ge);
1001 fuzz::<_, 1, 4>(10, &ge);
1002 fuzz::<_, 2, 4>(10, &ge);
1003 fuzz::<_, 3, 4>(10, &ge);
1004 fuzz::<_, 8, 16>(10, &ge);
1005 fuzz::<_, 9, 16>(10, &ge);
1006 fuzz::<_, 10, 16>(10, &ge);
1007 fuzz::<_, 11, 16>(10, &ge);
1008 fuzz::<_, 12, 16>(10, &ge);
1009 fuzz::<_, 13, 16>(10, &ge);
1010 fuzz::<_, 14, 16>(10, &ge);
1011 fuzz::<_, 15, 16>(10, &ge);
1012 }
1013
1014 fn fuzz<F, const N: usize, const M: usize>(iters: usize, comparer: &F)
1015 where
1016 F: Fn(&i8, &i8, &()) -> bool,
1017 {
1018 for _ in 0..iters {
1019 let mut heap: FixedHeap<i8, N> = FixedHeap::new();
1020 let mut array = [0i8; M];
1021 rand::rng().fill(&mut array[..]);
1022 for element in array {
1023 heap.push(element, comparer, &());
1024 }
1025 array.sort_by(|a, b| b.cmp(a));
1026 for &element in array.iter().take(N) {
1027 assert_eq!(Some(element), heap.pop(comparer, &()));
1028 }
1029 assert_eq!(None, heap.pop(comparer, &()));
1030 }
1031 }
1032
1033 #[test]
1034 fn test_fuzz_true() {
1035 let comparer = |_: &usize, _: &usize, _: &()| true;
1036 fuzz_state::<_, _, 0, 4>(&comparer, &());
1037 fuzz_state::<_, _, 1, 4>(&comparer, &());
1038 fuzz_state::<_, _, 2, 4>(&comparer, &());
1039 fuzz_state::<_, _, 3, 4>(&comparer, &());
1040 fuzz_state::<_, _, 8, 16>(&comparer, &());
1041 fuzz_state::<_, _, 9, 16>(&comparer, &());
1042 fuzz_state::<_, _, 10, 16>(&comparer, &());
1043 fuzz_state::<_, _, 11, 16>(&comparer, &());
1044 fuzz_state::<_, _, 12, 16>(&comparer, &());
1045 fuzz_state::<_, _, 13, 16>(&comparer, &());
1046 fuzz_state::<_, _, 14, 16>(&comparer, &());
1047 fuzz_state::<_, _, 15, 16>(&comparer, &());
1048 fuzz_state::<_, _, 16, 16>(&comparer, &());
1049 fuzz_state::<_, _, 17, 16>(&comparer, &());
1050 }
1051
1052 #[test]
1053 fn test_fuzz_false() {
1054 let comparer = |_: &usize, _: &usize, _: &()| false;
1055 fuzz_state::<_, _, 0, 4>(&comparer, &());
1056 fuzz_state::<_, _, 1, 4>(&comparer, &());
1057 fuzz_state::<_, _, 2, 4>(&comparer, &());
1058 fuzz_state::<_, _, 3, 4>(&comparer, &());
1059 fuzz_state::<_, _, 8, 16>(&comparer, &());
1060 fuzz_state::<_, _, 9, 16>(&comparer, &());
1061 fuzz_state::<_, _, 10, 16>(&comparer, &());
1062 fuzz_state::<_, _, 11, 16>(&comparer, &());
1063 fuzz_state::<_, _, 12, 16>(&comparer, &());
1064 fuzz_state::<_, _, 13, 16>(&comparer, &());
1065 fuzz_state::<_, _, 14, 16>(&comparer, &());
1066 fuzz_state::<_, _, 15, 16>(&comparer, &());
1067 fuzz_state::<_, _, 16, 16>(&comparer, &());
1068 fuzz_state::<_, _, 17, 16>(&comparer, &());
1069 }
1070
1071 #[test]
1072 fn test_fuzz() {
1073 let rng = RefCell::new(rand::rng());
1074 fn comparer(_: &usize, _: &usize, rng: &RefCell<ThreadRng>) -> bool {
1075 rng.borrow_mut().random()
1076 }
1077 fuzz_state::<_, _, 0, 4>(&comparer, &rng);
1078 fuzz_state::<_, _, 1, 4>(&comparer, &rng);
1079 fuzz_state::<_, _, 2, 4>(&comparer, &rng);
1080 fuzz_state::<_, _, 3, 4>(&comparer, &rng);
1081 fuzz_state::<_, _, 8, 16>(&comparer, &rng);
1082 fuzz_state::<_, _, 9, 16>(&comparer, &rng);
1083 fuzz_state::<_, _, 10, 16>(&comparer, &rng);
1084 fuzz_state::<_, _, 11, 16>(&comparer, &rng);
1085 fuzz_state::<_, _, 12, 16>(&comparer, &rng);
1086 fuzz_state::<_, _, 13, 16>(&comparer, &rng);
1087 fuzz_state::<_, _, 14, 16>(&comparer, &rng);
1088 fuzz_state::<_, _, 15, 16>(&comparer, &rng);
1089 fuzz_state::<_, _, 16, 16>(&comparer, &rng);
1090 fuzz_state::<_, _, 17, 16>(&comparer, &rng);
1091 }
1092
1093 fn fuzz_state<S, F, const N: usize, const M: usize>(
1094 comparer: &F,
1095 state: &S,
1096 ) -> [Option<usize>; M]
1097 where
1098 F: Fn(&usize, &usize, &S) -> bool,
1099 {
1100 let mut heap: FixedHeap<usize, N> = FixedHeap::new();
1101 for i in 0..M {
1102 heap.push(i, comparer, state);
1103 }
1104 let mut result = [None; M];
1105 for item in result.iter_mut() {
1106 *item = heap.pop(comparer, state);
1107 }
1108 if N < M {
1109 for &item in result.iter().skip(N) {
1110 assert_eq!(None, item);
1111 }
1112 } else {
1113 assert_eq!(None, heap.pop(comparer, state));
1114 }
1115 result
1116 }
1117}