| 593 ) { |
593 ) { |
| 594 return cx_array_insert_sorted_impl(target, size, capacity, |
594 return cx_array_insert_sorted_impl(target, size, capacity, |
| 595 cmp_func, sorted_data, elem_size, elem_count, reallocator, false); |
595 cmp_func, sorted_data, elem_size, elem_count, reallocator, false); |
| 596 } |
596 } |
| 597 |
597 |
| 598 size_t cx_array_binary_search_inf( |
598 // implementation that finds ANY index |
| |
599 static size_t cx_array_binary_search_inf_impl( |
| 599 const void *arr, |
600 const void *arr, |
| 600 size_t size, |
601 size_t size, |
| 601 size_t elem_size, |
602 size_t elem_size, |
| 602 const void *elem, |
603 const void *elem, |
| 603 cx_compare_func cmp_func |
604 cx_compare_func cmp_func |
| 638 pivot_index = left_index + (right_index - left_index) / 2; |
639 pivot_index = left_index + (right_index - left_index) / 2; |
| 639 const char *arr_elem = array + pivot_index * elem_size; |
640 const char *arr_elem = array + pivot_index * elem_size; |
| 640 result = cmp_func(elem, arr_elem); |
641 result = cmp_func(elem, arr_elem); |
| 641 if (result == 0) { |
642 if (result == 0) { |
| 642 // found it! |
643 // found it! |
| 643 // check previous elements; |
|
| 644 // when they are equal, report the smallest index |
|
| 645 arr_elem -= elem_size; |
|
| 646 while (pivot_index > 0 && cmp_func(elem, arr_elem) == 0) { |
|
| 647 pivot_index--; |
|
| 648 arr_elem -= elem_size; |
|
| 649 } |
|
| 650 return pivot_index; |
644 return pivot_index; |
| 651 } else if (result < 0) { |
645 } else if (result < 0) { |
| 652 // element is smaller than pivot, continue search left |
646 // element is smaller than pivot, continue search left |
| 653 right_index = pivot_index - 1; |
647 right_index = pivot_index - 1; |
| 654 } else { |
648 } else { |
| 657 } |
651 } |
| 658 } |
652 } |
| 659 |
653 |
| 660 // report the largest upper bound |
654 // report the largest upper bound |
| 661 return result < 0 ? (pivot_index - 1) : pivot_index; |
655 return result < 0 ? (pivot_index - 1) : pivot_index; |
| |
656 } |
| |
657 |
| |
658 size_t cx_array_binary_search_inf( |
| |
659 const void *arr, |
| |
660 size_t size, |
| |
661 size_t elem_size, |
| |
662 const void *elem, |
| |
663 cx_compare_func cmp_func |
| |
664 ) { |
| |
665 size_t index = cx_array_binary_search_inf_impl( |
| |
666 arr, size, elem_size, elem, cmp_func); |
| |
667 // in case of equality, report the largest index |
| |
668 const char *e = ((const char *) arr) + (index + 1) * elem_size; |
| |
669 while (index + 1 < size && cmp_func(e, elem) == 0) { |
| |
670 e += elem_size; |
| |
671 index++; |
| |
672 } |
| |
673 return index; |
| 662 } |
674 } |
| 663 |
675 |
| 664 size_t cx_array_binary_search( |
676 size_t cx_array_binary_search( |
| 665 const void *arr, |
677 const void *arr, |
| 666 size_t size, |
678 size_t size, |
| 684 size_t size, |
696 size_t size, |
| 685 size_t elem_size, |
697 size_t elem_size, |
| 686 const void *elem, |
698 const void *elem, |
| 687 cx_compare_func cmp_func |
699 cx_compare_func cmp_func |
| 688 ) { |
700 ) { |
| 689 size_t inf = cx_array_binary_search_inf( |
701 size_t index = cx_array_binary_search_inf_impl( |
| 690 arr, size, elem_size, elem, cmp_func |
702 arr, size, elem_size, elem, cmp_func |
| 691 ); |
703 ); |
| 692 if (inf == size) { |
704 const char *e = ((const char *) arr) + index * elem_size; |
| 693 // no infimum means, first element is supremum |
705 if (index == size) { |
| |
706 // no infimum means the first element is supremum |
| 694 return 0; |
707 return 0; |
| 695 } else if (cmp_func(((const char *) arr) + inf * elem_size, elem) == 0) { |
708 } else if (cmp_func(e, elem) == 0) { |
| 696 return inf; |
709 // found an equal element, search the smallest index |
| |
710 e -= elem_size; // e now contains the element at index-1 |
| |
711 while (index > 0 && cmp_func(e, elem) == 0) { |
| |
712 e -= elem_size; |
| |
713 index--; |
| |
714 } |
| |
715 return index; |
| 697 } else { |
716 } else { |
| 698 return inf + 1; |
717 // we already have the largest index of the infimum (by design) |
| |
718 // the next element is the supremum (or there is no supremum) |
| |
719 return index + 1; |
| 699 } |
720 } |
| 700 } |
721 } |
| 701 |
722 |
| 702 #ifndef CX_ARRAY_SWAP_SBO_SIZE |
723 #ifndef CX_ARRAY_SWAP_SBO_SIZE |
| 703 #define CX_ARRAY_SWAP_SBO_SIZE 128 |
724 #define CX_ARRAY_SWAP_SBO_SIZE 128 |