mirror of
https://github.com/boostorg/container.git
synced 2026-07-05 09:20:48 +02:00
Implement dual segmentation to copy_if, copy_n and mismatch.
This commit is contained in:
@@ -159,6 +159,98 @@ void test_copy_if_seg2()
|
||||
BOOST_TEST_EQ(out[3], 8);
|
||||
}
|
||||
|
||||
void test_copy_if_segmented_output()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv.add_segment_range(a1, a1 + 3);
|
||||
sv.add_segment_range(a2, a2 + 2);
|
||||
sv.add_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg_vector<int> out;
|
||||
out.add_segment(3, 0);
|
||||
out.add_segment(2, 0);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_if(sv.begin(), sv.end(), out.begin(), is_even());
|
||||
|
||||
std::size_t count = 0;
|
||||
iter_t it = out.begin();
|
||||
for(; it != result; ++it)
|
||||
++count;
|
||||
BOOST_TEST_EQ(count, 4u);
|
||||
|
||||
it = out.begin();
|
||||
BOOST_TEST_EQ(*it, 2); ++it;
|
||||
BOOST_TEST_EQ(*it, 4); ++it;
|
||||
BOOST_TEST_EQ(*it, 6); ++it;
|
||||
BOOST_TEST_EQ(*it, 8);
|
||||
}
|
||||
|
||||
void test_copy_if_seg2_to_seg2()
|
||||
{
|
||||
test_detail::seg2_vector<int> sv2;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv2.add_flat_segment_range(a1, a1 + 3);
|
||||
sv2.add_flat_segment_range(a2, a2 + 2);
|
||||
sv2.add_flat_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg2_vector<int> out;
|
||||
{
|
||||
test_detail::seg_vector<int> s1; s1.add_segment(3, 0);
|
||||
test_detail::seg_vector<int> s2; s2.add_segment(2, 0);
|
||||
out.add_segment(s1);
|
||||
out.add_segment(s2);
|
||||
}
|
||||
|
||||
typedef test_detail::seg2_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_if(sv2.begin(), sv2.end(), out.begin(), is_even());
|
||||
|
||||
std::size_t count = 0;
|
||||
iter_t it = out.begin();
|
||||
for(; it != result; ++it)
|
||||
++count;
|
||||
BOOST_TEST_EQ(count, 4u);
|
||||
|
||||
it = out.begin();
|
||||
BOOST_TEST_EQ(*it, 2); ++it;
|
||||
BOOST_TEST_EQ(*it, 4); ++it;
|
||||
BOOST_TEST_EQ(*it, 6); ++it;
|
||||
BOOST_TEST_EQ(*it, 8);
|
||||
}
|
||||
|
||||
void test_copy_if_seg_to_seg_misaligned()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3, 4, 5};
|
||||
int a2[] = {6, 7, 8};
|
||||
sv.add_segment_range(a1, a1 + 5);
|
||||
sv.add_segment_range(a2, a2 + 3);
|
||||
|
||||
test_detail::seg_vector<int> out;
|
||||
out.add_segment(2, 0);
|
||||
out.add_segment(3, 0);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_if(sv.begin(), sv.end(), out.begin(), is_even());
|
||||
|
||||
std::size_t count = 0;
|
||||
iter_t it = out.begin();
|
||||
for(; it != result; ++it)
|
||||
++count;
|
||||
BOOST_TEST_EQ(count, 4u);
|
||||
|
||||
it = out.begin();
|
||||
BOOST_TEST_EQ(*it, 2); ++it;
|
||||
BOOST_TEST_EQ(*it, 4); ++it;
|
||||
BOOST_TEST_EQ(*it, 6); ++it;
|
||||
BOOST_TEST_EQ(*it, 8);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_copy_if_full_range();
|
||||
@@ -169,5 +261,8 @@ int main()
|
||||
test_copy_if_sentinel_segmented();
|
||||
test_copy_if_sentinel_non_segmented();
|
||||
test_copy_if_seg2();
|
||||
test_copy_if_segmented_output();
|
||||
test_copy_if_seg2_to_seg2();
|
||||
test_copy_if_seg_to_seg_misaligned();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -112,6 +112,107 @@ void test_copy_n_seg2()
|
||||
BOOST_TEST_EQ(out[static_cast<std::size_t>(i)], i + 1);
|
||||
}
|
||||
|
||||
void test_copy_n_segmented_output()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv.add_segment_range(a1, a1 + 3);
|
||||
sv.add_segment_range(a2, a2 + 2);
|
||||
sv.add_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg_vector<int> out;
|
||||
out.add_segment(4, 0);
|
||||
out.add_segment(3, 0);
|
||||
out.add_segment(2, 0);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_n(sv.begin(), 9, out.begin());
|
||||
|
||||
BOOST_TEST(result == out.end());
|
||||
iter_t it = out.begin();
|
||||
for(int i = 0; i < 9; ++i, ++it)
|
||||
BOOST_TEST_EQ(*it, i + 1);
|
||||
}
|
||||
|
||||
void test_copy_n_seg2_to_seg2()
|
||||
{
|
||||
test_detail::seg2_vector<int> sv2;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv2.add_flat_segment_range(a1, a1 + 3);
|
||||
sv2.add_flat_segment_range(a2, a2 + 2);
|
||||
sv2.add_flat_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg2_vector<int> out;
|
||||
{
|
||||
test_detail::seg_vector<int> s1; s1.add_segment(5, 0);
|
||||
test_detail::seg_vector<int> s2; s2.add_segment(4, 0);
|
||||
out.add_segment(s1);
|
||||
out.add_segment(s2);
|
||||
}
|
||||
|
||||
typedef test_detail::seg2_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_n(sv2.begin(), 9, out.begin());
|
||||
|
||||
BOOST_TEST(result == out.end());
|
||||
iter_t it = out.begin();
|
||||
for(int i = 0; i < 9; ++i, ++it)
|
||||
BOOST_TEST_EQ(*it, i + 1);
|
||||
}
|
||||
|
||||
void test_copy_n_seg_to_seg_misaligned()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3, 4, 5};
|
||||
int a2[] = {6, 7, 8};
|
||||
sv.add_segment_range(a1, a1 + 5);
|
||||
sv.add_segment_range(a2, a2 + 3);
|
||||
|
||||
test_detail::seg_vector<int> out;
|
||||
out.add_segment(2, 0);
|
||||
out.add_segment(3, 0);
|
||||
out.add_segment(3, 0);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_n(sv.begin(), 8, out.begin());
|
||||
|
||||
BOOST_TEST(result == out.end());
|
||||
iter_t it = out.begin();
|
||||
for(int i = 0; i < 8; ++i, ++it)
|
||||
BOOST_TEST_EQ(*it, i + 1);
|
||||
}
|
||||
|
||||
void test_copy_n_partial_segmented_output()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv.add_segment_range(a1, a1 + 3);
|
||||
sv.add_segment_range(a2, a2 + 2);
|
||||
sv.add_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg_vector<int> out;
|
||||
out.add_segment(3, 0);
|
||||
out.add_segment(3, 0);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
iter_t result = segmented_copy_n(sv.begin(), 5, out.begin());
|
||||
|
||||
std::size_t count = 0;
|
||||
iter_t it = out.begin();
|
||||
for(; it != result; ++it)
|
||||
++count;
|
||||
BOOST_TEST_EQ(count, 5u);
|
||||
|
||||
it = out.begin();
|
||||
for(int i = 0; i < 5; ++i, ++it)
|
||||
BOOST_TEST_EQ(*it, i + 1);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_copy_n_full();
|
||||
@@ -120,5 +221,9 @@ int main()
|
||||
test_copy_n_single_segment();
|
||||
test_copy_n_non_segmented();
|
||||
test_copy_n_seg2();
|
||||
test_copy_n_segmented_output();
|
||||
test_copy_n_seg2_to_seg2();
|
||||
test_copy_n_seg_to_seg_misaligned();
|
||||
test_copy_n_partial_segmented_output();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -232,6 +232,132 @@ void test_mismatch_every_position_seg2()
|
||||
BOOST_TEST(r.first == sv2.end());
|
||||
}
|
||||
|
||||
void test_mismatch_seg_to_seg()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv.add_segment_range(a1, a1 + 3);
|
||||
sv.add_segment_range(a2, a2 + 2);
|
||||
sv.add_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg_vector<int> sv2;
|
||||
int b1[] = {1, 2, 3, 4};
|
||||
int b2[] = {5, 6, 7, 8};
|
||||
int b3[] = {9};
|
||||
sv2.add_segment_range(b1, b1 + 4);
|
||||
sv2.add_segment_range(b2, b2 + 4);
|
||||
sv2.add_segment_range(b3, b3 + 1);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
std::pair<iter_t, iter_t> r = segmented_mismatch(sv.begin(), sv.end(), sv2.begin());
|
||||
BOOST_TEST(r.first == sv.end());
|
||||
}
|
||||
|
||||
void test_mismatch_seg_to_seg_mismatch()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv.add_segment_range(a1, a1 + 3);
|
||||
sv.add_segment_range(a2, a2 + 2);
|
||||
sv.add_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg_vector<int> sv2;
|
||||
int b1[] = {1, 2, 3, 4};
|
||||
int b2[] = {5, 6, 99, 8};
|
||||
int b3[] = {9};
|
||||
sv2.add_segment_range(b1, b1 + 4);
|
||||
sv2.add_segment_range(b2, b2 + 4);
|
||||
sv2.add_segment_range(b3, b3 + 1);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
std::pair<iter_t, iter_t> r = segmented_mismatch(sv.begin(), sv.end(), sv2.begin());
|
||||
BOOST_TEST(r.first != sv.end());
|
||||
BOOST_TEST_EQ(*r.first, 7);
|
||||
BOOST_TEST_EQ(*r.second, 99);
|
||||
}
|
||||
|
||||
void test_mismatch_seg2_to_seg2()
|
||||
{
|
||||
test_detail::seg2_vector<int> sv;
|
||||
int a1[] = {1, 2, 3};
|
||||
int a2[] = {4, 5};
|
||||
int a3[] = {6, 7, 8, 9};
|
||||
sv.add_flat_segment_range(a1, a1 + 3);
|
||||
sv.add_flat_segment_range(a2, a2 + 2);
|
||||
sv.add_flat_segment_range(a3, a3 + 4);
|
||||
|
||||
test_detail::seg2_vector<int> sv2;
|
||||
int b1[] = {1, 2, 3, 4, 5};
|
||||
int b2[] = {6, 7, 8, 9};
|
||||
sv2.add_flat_segment_range(b1, b1 + 5);
|
||||
sv2.add_flat_segment_range(b2, b2 + 4);
|
||||
|
||||
typedef test_detail::seg2_vector<int>::iterator iter_t;
|
||||
std::pair<iter_t, iter_t> r = segmented_mismatch(sv.begin(), sv.end(), sv2.begin());
|
||||
BOOST_TEST(r.first == sv.end());
|
||||
}
|
||||
|
||||
void test_mismatch_seg_to_seg_misaligned()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {1, 2, 3, 4, 5};
|
||||
int a2[] = {6, 7, 8};
|
||||
sv.add_segment_range(a1, a1 + 5);
|
||||
sv.add_segment_range(a2, a2 + 3);
|
||||
|
||||
test_detail::seg_vector<int> sv2;
|
||||
int b1[] = {1, 2};
|
||||
int b2[] = {3, 4, 5};
|
||||
int b3[] = {6, 7, 8};
|
||||
sv2.add_segment_range(b1, b1 + 2);
|
||||
sv2.add_segment_range(b2, b2 + 3);
|
||||
sv2.add_segment_range(b3, b3 + 3);
|
||||
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
std::pair<iter_t, iter_t> r = segmented_mismatch(sv.begin(), sv.end(), sv2.begin());
|
||||
BOOST_TEST(r.first == sv.end());
|
||||
}
|
||||
|
||||
void test_mismatch_seg_to_seg_every_position()
|
||||
{
|
||||
test_detail::seg_vector<int> sv;
|
||||
int a1[] = {10, 20, 30};
|
||||
int a2[] = {40, 50};
|
||||
int a3[] = {60, 70, 80, 90};
|
||||
sv.add_segment_range(a1, a1 + 3);
|
||||
sv.add_segment_range(a2, a2 + 2);
|
||||
sv.add_segment_range(a3, a3 + 4);
|
||||
|
||||
int vals[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};
|
||||
const int N = 9;
|
||||
typedef test_detail::seg_vector<int>::iterator iter_t;
|
||||
|
||||
for(int pos = 0; pos < N; ++pos) {
|
||||
test_detail::seg_vector<int> sv2;
|
||||
int ref[9];
|
||||
for(int j = 0; j < N; ++j) ref[j] = vals[j];
|
||||
ref[pos] = -1;
|
||||
int r1[] = {ref[0], ref[1], ref[2], ref[3]};
|
||||
int r2[] = {ref[4], ref[5], ref[6], ref[7]};
|
||||
int r3[] = {ref[8]};
|
||||
sv2.add_segment_range(r1, r1 + 4);
|
||||
sv2.add_segment_range(r2, r2 + 4);
|
||||
sv2.add_segment_range(r3, r3 + 1);
|
||||
|
||||
iter_t expected = sv.begin();
|
||||
for(int j = 0; j < pos; ++j) ++expected;
|
||||
|
||||
std::pair<iter_t, iter_t> r = segmented_mismatch(sv.begin(), sv.end(), sv2.begin());
|
||||
BOOST_TEST(r.first == expected);
|
||||
BOOST_TEST_EQ(*r.first, vals[pos]);
|
||||
BOOST_TEST_EQ(*r.second, -1);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_mismatch_matching();
|
||||
@@ -245,5 +371,10 @@ int main()
|
||||
test_mismatch_seg2();
|
||||
test_mismatch_every_position();
|
||||
test_mismatch_every_position_seg2();
|
||||
test_mismatch_seg_to_seg();
|
||||
test_mismatch_seg_to_seg_mismatch();
|
||||
test_mismatch_seg2_to_seg2();
|
||||
test_mismatch_seg_to_seg_misaligned();
|
||||
test_mismatch_seg_to_seg_every_position();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -31,88 +31,211 @@ OutIter segmented_copy_if(InIter first, Sent last, OutIter result, Pred pred);
|
||||
|
||||
namespace detail_algo {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bounded destination helper: copies matching elements from source into
|
||||
// [dst_first, dst_last), stopping when source is exhausted or destination
|
||||
// is full. Advances first_out (by reference) so the caller knows how far
|
||||
// we got. Recursively walks destination segments when dst is segmented.
|
||||
//
|
||||
// When dst_last is unreachable_sentinel_t the destination-full check
|
||||
// is optimised away, giving the same code as an unbounded loop.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RAIter, class OutIter, class Pred>
|
||||
OutIter segmented_copy_if_dispatch
|
||||
(RAIter first, RAIter last, OutIter result, Pred pred, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
template <class RASrcIter, class DstIter, class DstSent, class Pred>
|
||||
DstIter segmented_copy_if_dst_bounded
|
||||
(RASrcIter& first_out, RASrcIter last, DstIter dst_first, DstSent dst_last, Pred pred,
|
||||
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<RAIter>::difference_type difference_type;
|
||||
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
|
||||
RASrcIter first = first_out;
|
||||
|
||||
difference_type n = last - first;
|
||||
|
||||
while(n >= difference_type(4)) {
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { *result = *first; ++result; }
|
||||
break;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
if(pred(*first)) { *result = *first; ++result; } ++first;
|
||||
if(pred(*first)) { *result = *first; ++result; }
|
||||
break;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
if(pred(*first)) { *result = *first; ++result; }
|
||||
break;
|
||||
if(pred(*first)) { if(dst_first == dst_last) goto out_path; *dst_first = *first; ++dst_first; } ++first;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
out_path:
|
||||
first_out = first;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class InIter, class Sent, class OutIter, class Pred, class Tag, class Cat>
|
||||
typename algo_enable_if_c<
|
||||
!Tag::value || is_sentinel<Sent, InIter>::value, OutIter>::type
|
||||
segmented_copy_if_dispatch
|
||||
(InIter first, Sent last, OutIter result, Pred pred, Tag, Cat)
|
||||
template <class SrcIter, class Sent, class DstIter, class DstSent, class Pred, class DstTag, class SrcCat>
|
||||
typename algo_enable_if_c<!DstTag::value, DstIter>::type
|
||||
segmented_copy_if_dst_bounded
|
||||
(SrcIter& first_out, Sent last, DstIter dst_first, DstSent dst_last, Pred pred, DstTag, SrcCat)
|
||||
{
|
||||
for(; first != last; ++first)
|
||||
SrcIter first = first_out;
|
||||
|
||||
for(; first != last; ++first) {
|
||||
if(pred(*first)) {
|
||||
*result = *first;
|
||||
++result;
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
*dst_first = *first;
|
||||
++dst_first;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
out_path:
|
||||
first_out = first;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
template <class SrcIter, class Sent, class SegDstIter, class Pred, class SrcCat>
|
||||
SegDstIter segmented_copy_if_dst_bounded
|
||||
(SrcIter& first, Sent last, SegDstIter dst_first, SegDstIter dst_last, Pred pred,
|
||||
segmented_iterator_tag, SrcCat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
dst_segment_iterator sfirst = dst_traits::segment(dst_first);
|
||||
const dst_segment_iterator slast = dst_traits::segment(dst_last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
dst_local_iterator r = (segmented_copy_if_dst_bounded)
|
||||
(first, last, dst_traits::local(dst_first), dst_traits::local(dst_last), pred, dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, r);
|
||||
}
|
||||
else {
|
||||
dst_local_iterator dst_local = (segmented_copy_if_dst_bounded)
|
||||
(first, last, dst_traits::local(dst_first), dst_traits::end(sfirst), pred, dst_is_local_seg_t(), SrcCat());
|
||||
if(first == last)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst) {
|
||||
dst_local = (segmented_copy_if_dst_bounded)
|
||||
(first, last, dst_traits::begin(sfirst), dst_traits::end(sfirst), pred, dst_is_local_seg_t(), SrcCat());
|
||||
if(first == last)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
|
||||
dst_local = (segmented_copy_if_dst_bounded)
|
||||
(first, last, dst_traits::begin(slast), dst_traits::local(dst_last), pred, dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Destination dispatch: routes to bounded helper.
|
||||
// Non-segmented destination: single unbounded call (unreachable_sentinel_t).
|
||||
// Segmented destination: loop over destination segments, bounded per segment.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Sent, class DstIter, class Pred, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE DstIter segmented_copy_if_dst_dispatch
|
||||
(SrcIter first, Sent last, DstIter result, Pred pred,
|
||||
const non_segmented_iterator_tag &, Cat)
|
||||
{
|
||||
return (segmented_copy_if_dst_bounded)
|
||||
(first, last, result, unreachable_sentinel_t(), pred, non_segmented_iterator_tag(), Cat());
|
||||
}
|
||||
|
||||
template <class SrcIter, class Sent, class SegDstIter, class Pred, class Cat>
|
||||
SegDstIter segmented_copy_if_dst_dispatch
|
||||
(SrcIter first, Sent last, SegDstIter result, Pred pred,
|
||||
const segmented_iterator_tag &, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
if(first == last)
|
||||
return result;
|
||||
|
||||
dst_segment_iterator dst_seg = dst_traits::segment(result);
|
||||
dst_local_iterator dst_local = dst_traits::local(result);
|
||||
|
||||
while(first != last) {
|
||||
dst_local_iterator dst_end = dst_traits::end(dst_seg);
|
||||
dst_local = (segmented_copy_if_dst_bounded)
|
||||
(first, last, dst_local, dst_end, pred, dst_is_local_seg_t(), Cat());
|
||||
if(first != last) {
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
}
|
||||
return dst_traits::compose(dst_seg, dst_local);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Source dispatch: walks the source (read pointer) segments
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Sent, class OutIter, class Pred, class Tag, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename algo_enable_if_c<
|
||||
!Tag::value || is_sentinel<Sent, SrcIter>::value, OutIter>::type
|
||||
segmented_copy_if_dispatch(SrcIter first, Sent last, OutIter result, Pred pred, Tag, Cat)
|
||||
{
|
||||
#if !defined(BOOST_CONTAINER_DISABLE_SEGMENTED_OUTPUT)
|
||||
typedef segmented_iterator_traits<OutIter> dst_traits;
|
||||
return (segmented_copy_if_dst_dispatch)
|
||||
(first, last, result, pred, typename dst_traits::is_segmented_iterator(), Cat());
|
||||
#else
|
||||
return (segmented_copy_if_dst_dispatch)
|
||||
(first, last, result, pred, non_segmented_iterator_tag(), Cat());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class SegIter, class OutIter, class Pred, class Cat>
|
||||
OutIter segmented_copy_if_dispatch
|
||||
(SegIter first, SegIter last, OutIter result, Pred pred, segmented_iterator_tag, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegIter> traits;
|
||||
typedef typename traits::local_iterator local_iterator;
|
||||
typedef typename traits::segment_iterator segment_iterator;
|
||||
typedef typename segmented_iterator_traits<local_iterator>::is_segmented_iterator is_local_seg_t;
|
||||
typedef typename iterator_traits<local_iterator>::iterator_category local_cat_t;
|
||||
typedef segmented_iterator_traits<SegIter> src_traits;
|
||||
typedef typename src_traits::local_iterator src_local_iterator;
|
||||
typedef typename src_traits::segment_iterator src_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<src_local_iterator>::is_segmented_iterator src_is_local_seg_t;
|
||||
typedef typename iterator_traits<src_local_iterator>::iterator_category src_local_cat_t;
|
||||
|
||||
segment_iterator sfirst = traits::segment(first);
|
||||
segment_iterator slast = traits::segment(last);
|
||||
src_segment_iterator sfirst = src_traits::segment(first);
|
||||
const src_segment_iterator slast = src_traits::segment(last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
return (segmented_copy_if_dispatch)(traits::local(first), traits::local(last), result, pred, is_local_seg_t(), local_cat_t());
|
||||
return (segmented_copy_if_dispatch)
|
||||
(src_traits::local(first), src_traits::local(last), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
}
|
||||
else {
|
||||
result = (segmented_copy_if_dispatch)(traits::local(first), traits::end(sfirst), result, pred, is_local_seg_t(), local_cat_t());
|
||||
result = (segmented_copy_if_dispatch)
|
||||
(src_traits::local(first), src_traits::end(sfirst), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst)
|
||||
result = (segmented_copy_if_dispatch)(traits::begin(sfirst), traits::end(sfirst), result, pred, is_local_seg_t(), local_cat_t());
|
||||
result = (segmented_copy_if_dispatch)
|
||||
(src_traits::begin(sfirst), src_traits::end(sfirst), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
|
||||
return (segmented_copy_if_dispatch)(traits::begin(sfirst), traits::local(last), result, pred, is_local_seg_t(), local_cat_t());
|
||||
return (segmented_copy_if_dispatch)
|
||||
(src_traits::begin(slast), src_traits::local(last), result, pred, src_is_local_seg_t(), src_local_cat_t());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
//! Copies elements satisfying \c pred from [first, last) to the range
|
||||
//! beginning at \c result. Segmentation is exploited on the input range.
|
||||
//! beginning at \c result. Segmentation is exploited on both input and
|
||||
//! output ranges.
|
||||
template <class InIter, class Sent, class OutIter, class Pred>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
OutIter segmented_copy_if(InIter first, Sent last, OutIter result, Pred pred)
|
||||
|
||||
@@ -32,6 +32,156 @@ OutIter segmented_copy_n(InIter first, Size count, OutIter result);
|
||||
|
||||
namespace detail_algo {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bounded destination helper: copies from source count elements into
|
||||
// [dst_first, dst_last), stopping when count reaches zero or destination
|
||||
// is full. Advances first_out and count (by reference) so the caller
|
||||
// knows how far we got.
|
||||
// Recursively walks destination segments when dst is segmented.
|
||||
//
|
||||
// When dst_last is unreachable_sentinel_t the destination-full check
|
||||
// is optimised away, giving the same code as an unbounded loop.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RASrcIter, class Size, class DstIter, class DstSent>
|
||||
DstIter segmented_copy_n_dst_bounded
|
||||
(RASrcIter& first_out, Size& count, DstIter dst_first, DstSent dst_last,
|
||||
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
{
|
||||
RASrcIter first = first_out;
|
||||
|
||||
while(count >= Size(4)) {
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
}
|
||||
|
||||
switch(count) {
|
||||
case 3:
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
if(dst_first == dst_last) goto out_path; *dst_first = *first; ++first; ++dst_first; --count;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out_path:
|
||||
first_out = first;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class SrcIter, class Size, class DstIter, class DstSent, class DstTag, class SrcCat>
|
||||
typename algo_enable_if_c<!DstTag::value, DstIter>::type
|
||||
segmented_copy_n_dst_bounded
|
||||
(SrcIter& first_out, Size& count, DstIter dst_first, DstSent dst_last, DstTag, SrcCat)
|
||||
{
|
||||
SrcIter first = first_out;
|
||||
|
||||
for(; count > 0; ++first, --count) {
|
||||
if(dst_first == dst_last)
|
||||
goto out_path;
|
||||
*dst_first = *first;
|
||||
++dst_first;
|
||||
}
|
||||
out_path:
|
||||
first_out = first;
|
||||
return dst_first;
|
||||
}
|
||||
|
||||
template <class SrcIter, class Size, class SegDstIter, class SrcCat>
|
||||
SegDstIter segmented_copy_n_dst_bounded
|
||||
(SrcIter& first, Size& count, SegDstIter dst_first, SegDstIter dst_last,
|
||||
segmented_iterator_tag, SrcCat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
dst_segment_iterator sfirst = dst_traits::segment(dst_first);
|
||||
const dst_segment_iterator slast = dst_traits::segment(dst_last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
dst_local_iterator r = (segmented_copy_n_dst_bounded)
|
||||
(first, count, dst_traits::local(dst_first), dst_traits::local(dst_last), dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, r);
|
||||
}
|
||||
else {
|
||||
dst_local_iterator dst_local = (segmented_copy_n_dst_bounded)
|
||||
(first, count, dst_traits::local(dst_first), dst_traits::end(sfirst), dst_is_local_seg_t(), SrcCat());
|
||||
if(count == 0)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst) {
|
||||
dst_local = (segmented_copy_n_dst_bounded)
|
||||
(first, count, dst_traits::begin(sfirst), dst_traits::end(sfirst), dst_is_local_seg_t(), SrcCat());
|
||||
if(count == 0)
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
|
||||
dst_local = (segmented_copy_n_dst_bounded)
|
||||
(first, count, dst_traits::begin(slast), dst_traits::local(dst_last), dst_is_local_seg_t(), SrcCat());
|
||||
return dst_traits::compose(sfirst, dst_local);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Destination dispatch: routes to bounded helper.
|
||||
// Non-segmented destination: single unbounded call (unreachable_sentinel_t).
|
||||
// Segmented destination: loop over destination segments, bounded per segment.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Size, class DstIter, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE DstIter segmented_copy_n_dst_dispatch
|
||||
(SrcIter first, Size& count, DstIter result,
|
||||
const non_segmented_iterator_tag &, Cat)
|
||||
{
|
||||
return (segmented_copy_n_dst_bounded)
|
||||
(first, count, result, unreachable_sentinel_t(), non_segmented_iterator_tag(), Cat());
|
||||
}
|
||||
|
||||
template <class SrcIter, class Size, class SegDstIter, class Cat>
|
||||
SegDstIter segmented_copy_n_dst_dispatch
|
||||
(SrcIter first, Size& count, SegDstIter result,
|
||||
const segmented_iterator_tag &, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegDstIter> dst_traits;
|
||||
typedef typename dst_traits::local_iterator dst_local_iterator;
|
||||
typedef typename dst_traits::segment_iterator dst_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<dst_local_iterator>::is_segmented_iterator dst_is_local_seg_t;
|
||||
|
||||
if(count <= 0)
|
||||
return result;
|
||||
|
||||
dst_segment_iterator dst_seg = dst_traits::segment(result);
|
||||
dst_local_iterator dst_local = dst_traits::local(result);
|
||||
|
||||
while(count > 0) {
|
||||
dst_local_iterator dst_end = dst_traits::end(dst_seg);
|
||||
dst_local = (segmented_copy_n_dst_bounded)
|
||||
(first, count, dst_local, dst_end, dst_is_local_seg_t(), Cat());
|
||||
if(count > 0) {
|
||||
++dst_seg;
|
||||
dst_local = dst_traits::begin(dst_seg);
|
||||
}
|
||||
}
|
||||
return dst_traits::compose(dst_seg, dst_local);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// copy_n_scan: scans through source segments, clipping to both segment
|
||||
// boundaries and count, then delegates to the destination dispatch layer.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class InIter, class Size, class OutIter>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
OutIter copy_n_scan_non_segmented
|
||||
@@ -95,6 +245,10 @@ OutIter copy_n_scan(SegIt first, SegIt last, Size& count, OutIter result, segmen
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Source dispatch: walks the source (read pointer) segments
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SegIter, class Size, class OutIter, class Cat>
|
||||
OutIter segmented_copy_n_dispatch
|
||||
(SegIter first, Size count, OutIter result, segmented_iterator_tag, Cat)
|
||||
@@ -123,34 +277,17 @@ OutIter segmented_copy_n_dispatch
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RAIter, class Size, class OutIter>
|
||||
OutIter segmented_copy_n_dispatch
|
||||
BOOST_CONTAINER_FORCEINLINE OutIter segmented_copy_n_dispatch
|
||||
(RAIter first, Size count, OutIter result, non_segmented_iterator_tag, const std::random_access_iterator_tag &)
|
||||
{
|
||||
while(count >= Size(4)) {
|
||||
*result = *first; ++first; ++result;
|
||||
*result = *first; ++first; ++result;
|
||||
*result = *first; ++first; ++result;
|
||||
*result = *first; ++first; ++result;
|
||||
count -= Size(4);
|
||||
}
|
||||
|
||||
switch(count) {
|
||||
case 3:
|
||||
*result = *first; ++first; ++result;
|
||||
*result = *first; ++first; ++result;
|
||||
*result = *first; ++first; ++result;
|
||||
break;
|
||||
case 2:
|
||||
*result = *first; ++first; ++result;
|
||||
*result = *first; ++first; ++result;
|
||||
break;
|
||||
case 1:
|
||||
*result = *first; ++first; ++result;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
#if !defined(BOOST_CONTAINER_DISABLE_SEGMENTED_OUTPUT)
|
||||
typedef segmented_iterator_traits<OutIter> dst_traits;
|
||||
return (segmented_copy_n_dst_dispatch)
|
||||
(first, count, result, typename dst_traits::is_segmented_iterator(), std::random_access_iterator_tag());
|
||||
#else
|
||||
return (segmented_copy_n_dst_dispatch)
|
||||
(first, count, result, non_segmented_iterator_tag(), std::random_access_iterator_tag());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
@@ -159,15 +296,21 @@ template <class InIter, class Size, class OutIter, class Cat>
|
||||
OutIter segmented_copy_n_dispatch
|
||||
(InIter first, Size count, OutIter result, non_segmented_iterator_tag, Cat)
|
||||
{
|
||||
for(; count > 0; ++first, ++result, --count)
|
||||
*result = *first;
|
||||
return result;
|
||||
#if !defined(BOOST_CONTAINER_DISABLE_SEGMENTED_OUTPUT)
|
||||
typedef segmented_iterator_traits<OutIter> dst_traits;
|
||||
return (segmented_copy_n_dst_dispatch)
|
||||
(first, count, result, typename dst_traits::is_segmented_iterator(), Cat());
|
||||
#else
|
||||
return (segmented_copy_n_dst_dispatch)
|
||||
(first, count, result, non_segmented_iterator_tag(), Cat());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace detail_algo
|
||||
|
||||
//! Copies \c count elements from the range beginning at \c first to
|
||||
//! the range beginning at \c result. Exploits segmentation on input.
|
||||
//! the range beginning at \c result. Exploits segmentation on both
|
||||
//! input and output.
|
||||
template <class InIter, class Size, class OutIter>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
OutIter segmented_copy_n(InIter first, Size count, OutIter result)
|
||||
|
||||
@@ -41,86 +41,228 @@ struct mismatch_equal
|
||||
BOOST_CONTAINER_FORCEINLINE bool operator()(const T& a, const U& b) const { return a == b; }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Bounded iter2 helper: compares source [first1, last1) against
|
||||
// [iter2_first, iter2_last), stopping when source, iter2, or a mismatch
|
||||
// is encountered.
|
||||
// Advances first1_out (by reference) so the caller knows how far we got.
|
||||
// Advances iter2_first (by reference) for the same reason.
|
||||
// Recursively walks iter2 segments when iter2 is segmented.
|
||||
//
|
||||
// Returns true if no mismatch was found in the bounded region
|
||||
// (i.e. stopped because first1==last1 or first2==iter2_last).
|
||||
// Returns false if a mismatch was found.
|
||||
//
|
||||
// When iter2_last is unreachable_sentinel_t the segment-boundary check
|
||||
// is optimised away, giving the same code as an unbounded loop.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
|
||||
|
||||
template <class RAIter1, class RAIter2, class BinaryPred>
|
||||
std::pair<RAIter1, RAIter2> segmented_mismatch_dispatch
|
||||
(RAIter1 first1, RAIter1 last1, RAIter2 first2, BinaryPred pred, const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
template <class RASrcIter, class Iter2, class Iter2Sent, class BinaryPred>
|
||||
bool segmented_mismatch_iter2_bounded
|
||||
(RASrcIter &first1_out, RASrcIter last1, Iter2 &iter2_first, Iter2Sent iter2_last, BinaryPred pred,
|
||||
const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
|
||||
{
|
||||
typedef typename iterator_traits<RAIter1>::difference_type difference_type;
|
||||
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
|
||||
RASrcIter first1 = first1_out;
|
||||
Iter2 first2 = iter2_first;
|
||||
|
||||
difference_type n = last1 - first1;
|
||||
|
||||
while(n >= difference_type(4)) {
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
n -= 4;
|
||||
}
|
||||
|
||||
switch(n) {
|
||||
case 3:
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
break;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 2:
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
break;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
BOOST_FALLTHROUGH;
|
||||
case 1:
|
||||
if(!pred(*first1, *first2))
|
||||
goto final_result;
|
||||
++first1; ++first2;
|
||||
break;
|
||||
if(first2 == iter2_last) goto out_path; if(!pred(*first1, *first2)) goto mismatch_path; ++first1; ++first2;
|
||||
BOOST_FALLTHROUGH;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
final_result:
|
||||
return std::pair<RAIter1, RAIter2>(first1, first2);
|
||||
out_path:
|
||||
first1_out = first1;
|
||||
iter2_first = first2;
|
||||
return true;
|
||||
|
||||
mismatch_path:
|
||||
first1_out = first1;
|
||||
iter2_first = first2;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif //BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
|
||||
|
||||
template <class InpIter1, class Sent, class InpIter2, class BinaryPred, class Tag, class Cat>
|
||||
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, Cat)
|
||||
template <class SrcIter, class Sent, class Iter2, class Iter2Sent, class BinaryPred, class Iter2Tag, class SrcCat>
|
||||
typename algo_enable_if_c<!Iter2Tag::value, bool>::type
|
||||
segmented_mismatch_iter2_bounded
|
||||
(SrcIter &first1_out, Sent last1, Iter2 &iter2_first, Iter2Sent iter2_last, BinaryPred pred, Iter2Tag, SrcCat)
|
||||
{
|
||||
while (first1 != last1 && pred(*first1, *first2)) {
|
||||
++first1, ++first2;
|
||||
}
|
||||
SrcIter first1 = first1_out;
|
||||
Iter2 first2 = iter2_first;
|
||||
|
||||
return std::pair<InpIter1, InpIter2>(first1, first2);
|
||||
for(; first1 != last1; ++first1) {
|
||||
if(first2 == iter2_last)
|
||||
goto out_path;
|
||||
if(!pred(*first1, *first2)) {
|
||||
first1_out = first1;
|
||||
iter2_first = first2;
|
||||
return false;
|
||||
}
|
||||
++first2;
|
||||
}
|
||||
out_path:
|
||||
first1_out = first1;
|
||||
iter2_first = first2;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class SrcIter, class Sent, class SegIter2, class BinaryPred, class SrcCat>
|
||||
bool segmented_mismatch_iter2_bounded
|
||||
(SrcIter &first1, Sent last1, SegIter2 &iter2_first_out, SegIter2 iter2_last, BinaryPred pred,
|
||||
segmented_iterator_tag, SrcCat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegIter2> iter2_traits;
|
||||
typedef typename iter2_traits::local_iterator iter2_local_iterator;
|
||||
typedef typename iter2_traits::segment_iterator iter2_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<iter2_local_iterator>::is_segmented_iterator iter2_is_local_seg_t;
|
||||
|
||||
iter2_segment_iterator sfirst = iter2_traits::segment(iter2_first_out);
|
||||
const iter2_segment_iterator slast = iter2_traits::segment(iter2_last);
|
||||
|
||||
if(sfirst == slast) {
|
||||
iter2_local_iterator loc2 = iter2_traits::local(iter2_first_out);
|
||||
bool r = (segmented_mismatch_iter2_bounded)
|
||||
(first1, last1, loc2, iter2_traits::local(iter2_last), pred, iter2_is_local_seg_t(), SrcCat());
|
||||
iter2_first_out = iter2_traits::compose(sfirst, loc2);
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
iter2_local_iterator loc2 = iter2_traits::local(iter2_first_out);
|
||||
if(!(segmented_mismatch_iter2_bounded)
|
||||
(first1, last1, loc2, iter2_traits::end(sfirst), pred, iter2_is_local_seg_t(), SrcCat())) {
|
||||
iter2_first_out = iter2_traits::compose(sfirst, loc2);
|
||||
return false;
|
||||
}
|
||||
if(first1 == last1) {
|
||||
iter2_first_out = iter2_traits::compose(sfirst, loc2);
|
||||
return true;
|
||||
}
|
||||
|
||||
for(++sfirst; sfirst != slast; ++sfirst) {
|
||||
loc2 = iter2_traits::begin(sfirst);
|
||||
if(!(segmented_mismatch_iter2_bounded)
|
||||
(first1, last1, loc2, iter2_traits::end(sfirst), pred, iter2_is_local_seg_t(), SrcCat())) {
|
||||
iter2_first_out = iter2_traits::compose(sfirst, loc2);
|
||||
return false;
|
||||
}
|
||||
if(first1 == last1) {
|
||||
iter2_first_out = iter2_traits::compose(sfirst, loc2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
loc2 = iter2_traits::begin(slast);
|
||||
bool r = (segmented_mismatch_iter2_bounded)
|
||||
(first1, last1, loc2, iter2_traits::local(iter2_last), pred, iter2_is_local_seg_t(), SrcCat());
|
||||
iter2_first_out = iter2_traits::compose(sfirst, loc2);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Iter2 dispatch: routes to bounded helper.
|
||||
// Non-segmented iter2: single unbounded call (unreachable_sentinel_t).
|
||||
// Segmented iter2: loop over iter2 segments, bounded per segment.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Sent, class InpIter2, class BinaryPred, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE bool segmented_mismatch_iter2_dispatch
|
||||
(SrcIter &first1, Sent last1, InpIter2 &first2, BinaryPred pred,
|
||||
const non_segmented_iterator_tag &, Cat)
|
||||
{
|
||||
return (segmented_mismatch_iter2_bounded)
|
||||
(first1, last1, first2, unreachable_sentinel_t(), pred, non_segmented_iterator_tag(), Cat());
|
||||
}
|
||||
|
||||
template <class SrcIter, class Sent, class SegIter2, class BinaryPred, class Cat>
|
||||
bool segmented_mismatch_iter2_dispatch
|
||||
(SrcIter &first1, Sent last1, SegIter2 &first2_out, BinaryPred pred,
|
||||
const segmented_iterator_tag &, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegIter2> iter2_traits;
|
||||
typedef typename iter2_traits::local_iterator iter2_local_iterator;
|
||||
typedef typename iter2_traits::segment_iterator iter2_segment_iterator;
|
||||
typedef typename segmented_iterator_traits<iter2_local_iterator>::is_segmented_iterator iter2_is_local_seg_t;
|
||||
|
||||
if(first1 == last1)
|
||||
return true;
|
||||
|
||||
iter2_segment_iterator seg2 = iter2_traits::segment(first2_out);
|
||||
iter2_local_iterator loc2 = iter2_traits::local(first2_out);
|
||||
|
||||
while(first1 != last1) {
|
||||
iter2_local_iterator end2 = iter2_traits::end(seg2);
|
||||
if(!(segmented_mismatch_iter2_bounded)
|
||||
(first1, last1, loc2, end2, pred, iter2_is_local_seg_t(), Cat())) {
|
||||
first2_out = iter2_traits::compose(seg2, loc2);
|
||||
return false;
|
||||
}
|
||||
if(first1 != last1) {
|
||||
++seg2;
|
||||
loc2 = iter2_traits::begin(seg2);
|
||||
}
|
||||
}
|
||||
first2_out = iter2_traits::compose(seg2, loc2);
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Source dispatch: walks the source (first1) segments.
|
||||
// Returns std::pair<Iter1, Iter2>.
|
||||
// Internally uses the iter2 dispatch which returns bool and updates first2
|
||||
// by reference. The source dispatch reconstructs the composed first1
|
||||
// position when a mismatch is found.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class SrcIter, class Sent, class InpIter2, class BinaryPred, class Tag, class Cat>
|
||||
BOOST_CONTAINER_FORCEINLINE
|
||||
typename algo_enable_if_c
|
||||
< !Tag::value || is_sentinel<Sent, SrcIter>::value
|
||||
, std::pair<SrcIter, InpIter2>
|
||||
>::type
|
||||
segmented_mismatch_dispatch(SrcIter first1, Sent last1, InpIter2 first2, BinaryPred pred, Tag, Cat)
|
||||
{
|
||||
#if !defined(BOOST_CONTAINER_DISABLE_SEGMENTED_OUTPUT)
|
||||
typedef segmented_iterator_traits<InpIter2> iter2_traits;
|
||||
bool ok = (segmented_mismatch_iter2_dispatch)
|
||||
(first1, last1, first2, pred, typename iter2_traits::is_segmented_iterator(), Cat());
|
||||
#else
|
||||
bool ok = (segmented_mismatch_iter2_dispatch)
|
||||
(first1, last1, first2, pred, non_segmented_iterator_tag(), Cat());
|
||||
#endif
|
||||
(void)ok;
|
||||
return std::pair<SrcIter, InpIter2>(first1, first2);
|
||||
}
|
||||
|
||||
template <class SegIter, class InpIter2, class BinaryPred, class Cat>
|
||||
std::pair<SegIter, InpIter2> segmented_mismatch_dispatch
|
||||
(SegIter first1, SegIter last1, InpIter2 first2, BinaryPred pred, segmented_iterator_tag, Cat)
|
||||
{
|
||||
typedef segmented_iterator_traits<SegIter> traits;
|
||||
typedef typename traits::local_iterator local_iterator;
|
||||
typedef typename traits::segment_iterator segment_iterator;
|
||||
typedef segmented_iterator_traits<SegIter> traits;
|
||||
typedef typename traits::local_iterator local_iterator;
|
||||
typedef typename traits::segment_iterator segment_iterator;
|
||||
typedef typename segmented_iterator_traits<local_iterator>::is_segmented_iterator is_local_seg_t;
|
||||
typedef typename iterator_traits<local_iterator>::iterator_category local_cat_t;
|
||||
|
||||
@@ -136,13 +278,11 @@ std::pair<SegIter, InpIter2> segmented_mismatch_dispatch
|
||||
return return_t((r.first != ll) ? traits::compose(sfirst, r.first) : last1, r.second);
|
||||
}
|
||||
else {
|
||||
// First segment
|
||||
local_iterator le = traits::end(sfirst);
|
||||
local_return_t r = (segmented_mismatch_dispatch)(traits::local(first1), le, first2, pred, is_local_seg_t(), local_cat_t());
|
||||
if (r.first != le)
|
||||
return return_t(traits::compose(sfirst, r.first), r.second);
|
||||
|
||||
// Middle segments
|
||||
for (++sfirst; sfirst != slast; ++sfirst) {
|
||||
le = traits::end(sfirst);
|
||||
r = (segmented_mismatch_dispatch)(traits::begin(sfirst), le, r.second, pred, is_local_seg_t(), local_cat_t());
|
||||
@@ -150,7 +290,6 @@ std::pair<SegIter, InpIter2> segmented_mismatch_dispatch
|
||||
return return_t(traits::compose(sfirst, r.first), r.second);
|
||||
}
|
||||
|
||||
// Last segment
|
||||
le = traits::local(last1);
|
||||
r = (segmented_mismatch_dispatch)(traits::begin(slast), le, r.second, pred, is_local_seg_t(), local_cat_t());
|
||||
return return_t((r.first != le) ? traits::compose(sfirst, r.first) : last1, r.second);
|
||||
@@ -162,6 +301,7 @@ std::pair<SegIter, InpIter2> segmented_mismatch_dispatch
|
||||
//! Returns a pair of iterators to the first elements where
|
||||
//! \c pred(*it1, *it2) is false in [first1, last1) and the range
|
||||
//! starting at \c first2, or {last1, first2 + N} if all match.
|
||||
//! Exploits segmentation on both ranges.
|
||||
template <class InpIter1, class Sent, class InpIter2, class BinaryPred>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<InpIter1, InpIter2>
|
||||
segmented_mismatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred)
|
||||
@@ -174,6 +314,7 @@ segmented_mismatch(InpIter1 first1, Sent last1, InpIter2 first2, BinaryPred pred
|
||||
//! Returns a pair of iterators to the first mismatching elements
|
||||
//! in [first1, last1) and the range starting at \c first2, or
|
||||
//! {last1, first2 + N} if all elements match.
|
||||
//! Exploits segmentation on both ranges.
|
||||
template <class InpIter1, class Sent, class InpIter2>
|
||||
BOOST_CONTAINER_FORCEINLINE std::pair<InpIter1, InpIter2>
|
||||
segmented_mismatch(InpIter1 first1, Sent last1, InpIter2 first2)
|
||||
|
||||
Reference in New Issue
Block a user