Skip to content

Commit 453ce17

Browse files
committed
Implement optimization for random access iterators in segmented_copy_if: a 32 bit fixed loop is implemented in case there is room for non-checked stores with a final loop
1 parent 82eb27f commit 453ce17

1 file changed

Lines changed: 34 additions & 26 deletions

File tree

include/boost/container/experimental/segmented_copy_if.hpp

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -70,39 +70,47 @@ segmented_copy_if_dst_bounded
7070
{
7171
typedef typename iterator_traits<RASrcIter>::difference_type difference_type;
7272

73-
difference_type src_n = last - first;
74-
difference_type dst_n = difference_type(dst_last - dst_first);
75-
7673
(void)src_tag;
77-
RASrcIter cur = first;
74+
RASrcIter cur = first;
7875
RADstIter dst_cur = dst_first;
79-
if(src_n <= dst_n) {
80-
// Whole source fits the remaining destination capacity: lean pass,
81-
// no destination-full check (mirrors the original single-chunk kernel).
82-
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
83-
while(src_n) {
84-
--src_n;
85-
if(pred(*cur)) {
86-
*dst_cur = *cur;
87-
++dst_cur;
76+
77+
const difference_type B = 32;
78+
difference_type avail = last - cur;
79+
for(;;) {
80+
difference_type room = dst_last - dst_cur;
81+
difference_type chunk = room < avail ? room : avail;
82+
if(chunk == 0)
83+
goto end;
84+
if(chunk >= B) {
85+
avail -= B;
86+
chunk = B;
87+
BOOST_CONTAINER_SEGMENTED_AUTO_UNROLL
88+
while(chunk) {
89+
--chunk;
90+
if(pred(*cur)) {
91+
*dst_cur = *cur;
92+
++dst_cur;
93+
}
94+
++cur;
8895
}
89-
++cur;
96+
}
97+
else{
98+
break;
9099
}
91100
}
92-
else {
93-
// Source spans more than the destination segment: single bounded pass,
94-
// check the destination only on a hit -- avoids repeated chunk set-ups.
95-
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
96-
while(cur != last) {
97-
if(pred(*cur)) {
98-
if(dst_cur == dst_last)
99-
break;
100-
*dst_cur = *cur;
101-
++dst_cur;
102-
}
103-
++cur;
101+
102+
BOOST_CONTAINER_SEGMENTED_UNROLL(4)
103+
while(cur != last) {
104+
if(pred(*cur)) {
105+
if (dst_cur == dst_last)
106+
break;
107+
*dst_cur = *cur;
108+
++dst_cur;
104109
}
110+
++cur;
105111
}
112+
end:
113+
106114
return segduo<RASrcIter, RADstIter>(cur, dst_cur);
107115
}
108116

0 commit comments

Comments
 (0)