Optimized segmented_mismatch:

- avoid reference parameters
- avoid extra "bool" information, and extra "mismatch1" parameter
- Simplify implementation to help compiler optimize the code
This commit is contained in:
Ion Gaztañaga
2026-03-20 15:20:29 +01:00
parent f113af51fa
commit bb355d1b6c
@@ -40,87 +40,66 @@ struct mismatch_equal
BOOST_CONTAINER_FORCEINLINE bool operator()(const T& a, const U& b) const { return a == b; }
};
template <class InpIter1, class Sent, class InpIter2, class BinaryPred>
bool mismatch_scan(InpIter1& first1_out, Sent last1, InpIter2& first2_out, BinaryPred pred)
{
InpIter1 first1 = first1_out;
InpIter2 first2 = first2_out;
bool all_match = true;
for (; first1 != last1; ++first1, ++first2) {
if (!pred(*first1, *first2)) {
all_match = false;
break;
}
}
first1_out = first1;
first2_out = first2;
return all_match;
}
template <class SegIter, class InpIter2, class OutIter1, class BinaryPred>
bool segmented_mismatch_ref
(SegIter first1, SegIter last1, InpIter2& first2, OutIter1& mismatch1, BinaryPred pred, segmented_iterator_tag)
template <class SegIter, class InpIter2, class BinaryPred>
std::pair<SegIter, InpIter2> segmented_mismatch_dispatch
(SegIter first1, SegIter last1, InpIter2 first2, BinaryPred pred, segmented_iterator_tag)
{
typedef segmented_iterator_traits<SegIter> traits;
typedef typename traits::local_iterator local_iterator;
typedef typename traits::segment_iterator segment_iterator;
typedef std::pair<SegIter, InpIter2> return_t;
typedef std::pair<local_iterator, InpIter2> local_return_t;
segment_iterator sfirst = traits::segment(first1);
segment_iterator slast = traits::segment(last1);
if(sfirst == slast) {
local_iterator lf = traits::local(first1);
if(!(mismatch_scan)(lf, traits::local(last1), first2, pred)) {
mismatch1 = traits::compose(sfirst, lf);
return false;
}
const local_iterator lf = traits::local(first1);
const local_iterator ll = traits::local(last1);
const local_return_t r = (segmented_mismatch)(lf, ll, first2, pred);
return return_t(traits::compose(sfirst, r.first), r.second);
}
else {
{
local_iterator lf = traits::local(first1);
if(!(mismatch_scan)(lf, traits::end(sfirst), first2, pred)) {
mismatch1 = traits::compose(sfirst, lf);
return false;
}
}
for(++sfirst; sfirst != slast; ++sfirst) {
local_iterator lb = traits::begin(sfirst);
if(!(mismatch_scan)(lb, traits::end(sfirst), first2, pred)) {
mismatch1 = traits::compose(sfirst, lb);
return false;
}
}
{
local_iterator lb = traits::begin(sfirst);
if(!(mismatch_scan)(lb, traits::local(last1), first2, pred)) {
mismatch1 = traits::compose(sfirst, lb);
return false;
}
}
// First segment
{
const local_iterator lf = traits::local(first1);
const local_iterator le = traits::end(sfirst);
const local_return_t r = (segmented_mismatch)(lf, le, first2, pred);
if (r.first != le)
return return_t(traits::compose(sfirst, r.first), r.second);
first2 = r.second;
}
// Middle segments
for(++sfirst; sfirst != slast; ++sfirst) {
const local_iterator lb = traits::begin(sfirst);
const local_iterator le = traits::end(sfirst);
const local_return_t r = (segmented_mismatch)(lb, le, first2, pred);
if (r.first != le)
return return_t(traits::compose(sfirst, r.first), r.second);
first2 = r.second;
}
// Last segment
{
const local_iterator lb = traits::begin(sfirst);
const local_iterator ll = traits::local(last1);
const local_return_t r = (segmented_mismatch)(lb, ll, first2, pred);
return return_t(traits::compose(sfirst, r.first), r.second);
}
return true;
}
template <class InpIter1, class Sent, class InpIter2, class OutIter1, class BinaryPred, class Tag>
typename algo_enable_if_c<
!Tag::value || is_sentinel<Sent, InpIter1>::value, bool>::type
segmented_mismatch_ref(InpIter1 first1, Sent last1, InpIter2& first2_out, OutIter1& mismatch1, BinaryPred pred, Tag)
template <class InpIter1, class Sent, class InpIter2, class BinaryPred, class Tag>
typename algo_enable_if_c
< !Tag::value || is_sentinel<Sent, InpIter1>::value
, std::pair<InpIter1, InpIter2>
>::type
segmented_mismatch_dispatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred, Tag)
{
InpIter2 first2 = first2_out;
bool all_match = true;
for (; first1 != last1; ++first1, ++first2) {
if (!pred(*first1, *first2)) {
mismatch1 = first1;
all_match = false;
break;
}
while (first1 != last1 && pred(*first1, *first2)) {
++first1, ++first2;
}
mismatch1 = first1;
first2_out = first2;
return all_match;
return std::pair<InpIter1, InpIter2>(first1, first2);
}
} // namespace detail_algo
@@ -133,10 +112,8 @@ BOOST_CONTAINER_FORCEINLINE std::pair<InpIter1, InpIter2>
segmented_mismatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred)
{
typedef segmented_iterator_traits<InpIter1> traits;
InpIter1 mismatch1(last1);
detail_algo::segmented_mismatch_ref
(first1, last1, first2, mismatch1, pred, typename traits::is_segmented_iterator());
return std::pair<InpIter1, InpIter2>(mismatch1, first2);
return detail_algo::segmented_mismatch_dispatch
(first1, last1, first2, pred, typename traits::is_segmented_iterator());
}
//! Returns a pair of iterators to the first mismatching elements