@@ -30,68 +30,42 @@ namespace detail_algo {
3030
3131// Recursive dispatch for `segmented_is_sorted_until`.
3232//
33- // Cross-segment state is carried by reference :
33+ // Cross-segment state is carried by value and returned in segduo<Iter, DeepIt> :
3434// - `prev` : iterator (of the deepest non-segmented local type) pointing
35- // at the most recently examined element. Valid only when
36- // `has_prev` is true.
37- // - `has_prev` : becomes true the first time any element is seen.
35+ // at the most recently examined element.
3836//
39- // The segmented overload is the workhorse: it decomposes a range into
40- // first / middle / last sub-ranges and dispatches each one back through
41- // `sorted_until_rec`, which recurses if the local iterator is itself
42- // segmented, until the non-segmented base case is reached. `prev` and
43- // `has_prev` thread through every level of recursion unchanged, which is how
44- // the "last element of segment K" is compared against "first element of
45- // segment K+1" even when K and K+1 live at different levels of the nesting.
37+ // All sorted_until_rec overloads return segduo<Iter, DeepIt> where .first is
38+ // the result iterator and .second is the updated prev value. Passing prev by
39+ // value instead of by reference avoids pointer aliasing and lets the compiler
40+ // keep prev in a register throughout the inner loop.
4641
4742// (1) Non-segmented base case.
4843// At this level FwdIt == DeepIt (the deepest type computed from the top).
4944template <class FwdIt , class Sent , class Comp , class DeepIt , class Cat >
50- FwdIt sorted_until_rec
45+ segduo< FwdIt, DeepIt> sorted_until_rec
5146 (FwdIt first, Sent last, Comp comp,
52- DeepIt &prev_out, bool &has_prev,
53- const non_segmented_iterator_tag &, Cat)
47+ DeepIt prev, const non_segmented_iterator_tag &, Cat)
5448{
55- DeepIt prev = prev_out;
56- if (!has_prev) {
57- if (first == last)
58- return first;
59- prev = first;
60- has_prev = true ;
61- ++first;
62- }
6349 for (; first != last; ++first) {
6450 if (comp (*first, *prev))
65- goto final_update ;
66- prev = first;
51+ break ;
52+ prev = detail_algo::deepest_local_iterator<FwdIt>:: get ( first) ;
6753 }
68- final_update:
69- prev_out = prev;
70- return first;
54+ return segduo<FwdIt, DeepIt>(first, prev);
7155}
7256
7357#if defined(BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING)
7458
7559// (1') Random-access unrolled variant of the non-segmented base case.
7660template <class RAIter , class Comp , class DeepIt >
77- RAIter sorted_until_rec
61+ segduo< RAIter, DeepIt> sorted_until_rec
7862 (RAIter first, RAIter last, Comp comp,
79- DeepIt &prev_out, bool &has_prev ,
63+ RAIter prev ,
8064 const non_segmented_iterator_tag &, const std::random_access_iterator_tag &)
8165{
8266 typedef typename iterator_traits<RAIter>::difference_type difference_type;
8367
8468 difference_type n = last - first;
85- if (n == difference_type (0 ))
86- return last;
87-
88- DeepIt prev = prev_out;
89- if (!has_prev) {
90- prev = first;
91- has_prev = true ;
92- ++first;
93- --n;
94- }
9569
9670 while (n >= difference_type (4 )) {
9771 if (comp (*first, *prev))
@@ -130,43 +104,33 @@ RAIter sorted_until_rec
130104 }
131105
132106 final_result:
133- prev_out = prev;
134- return first;
107+ return segduo<RAIter, DeepIt>(first, prev);
135108}
136109
137110#endif // BOOST_CONTAINER_SEGMENTED_LOOP_UNROLLING
138111
139112// (2) Segmented iterator with a heterogeneous sentinel as end.
140- // Cannot locate `last`'s segment, so falls back to a simple linear loop
141- // using a local iterator as previous. The `DeepIt &` / `has_prev &` are
142- // not used here because this overload is only ever invoked at the very
143- // top level (no cross-level state to propagate).
144- template <class SegIter , class Sent , class Comp , class DeepIt , class Cat >
145- typename algo_enable_if_c<is_sentinel<Sent, SegIter>::value, SegIter>::type
113+ // Cannot locate `last`'s segment, so falls back to a simple linear loop.
114+ template <class SegIter , class Sent , class Comp , class DeepIt , class Tag , class Cat >
115+ BOOST_CONTAINER_FORCEINLINE
116+ typename algo_enable_if_c< is_sentinel<Sent, SegIter>::value
117+ , segduo<SegIter, DeepIt> >::type
146118sorted_until_rec
147119 (SegIter first, Sent last, Comp comp,
148- DeepIt &, bool &,
149- const segmented_iterator_tag &, Cat)
120+ DeepIt prev, const Tag &, const Cat &cat)
150121{
151- if (first != last) {
152- SegIter prev_local = first;
153- for (; ++first != last; ) {
154- if (comp (*first, *prev_local))
155- return first;
156- prev_local = first;
157- }
158- }
159- return first;
122+ return sorted_until_rec
123+ (first, last, comp, prev, non_segmented_iterator_tag (), cat);
160124}
161125
162126// (3) Segmented iterator with a matching segmented iterator as end.
163127// Recursive: decomposes the range and dispatches each sub-range back to
164128// `sorted_until_rec`, so recursive segmentation is exploited at every
165- // level. `prev` / `has_prev` are threaded unchanged .
129+ // level. `prev` is threaded by value through the segduo return type .
166130template <class SegIter , class Comp , class DeepIt , class Cat >
167- SegIter sorted_until_rec
131+ segduo< SegIter, DeepIt> sorted_until_rec
168132 (SegIter first, SegIter last, Comp comp,
169- DeepIt & prev, bool &has_prev ,
133+ DeepIt prev,
170134 const segmented_iterator_tag &, Cat)
171135{
172136 typedef segmented_iterator_traits<SegIter> traits;
@@ -175,44 +139,35 @@ SegIter sorted_until_rec
175139 typedef typename segmented_iterator_traits<local_iterator>::is_segmented_iterator
176140 is_local_seg_t ;
177141 typedef typename iterator_traits<local_iterator>::iterator_category local_cat_t ;
142+ typedef segduo<local_iterator, DeepIt> local_result_t ;
178143
179144 segment_iterator sfirst = traits::segment (first);
180145 const segment_iterator slast = traits::segment (last);
181146
182147 if (sfirst == slast) {
183148 const local_iterator ll = traits::local (last);
184- const local_iterator lr = (sorted_until_rec)
185- (traits::local (first), ll, comp, prev, has_prev, is_local_seg_t (), local_cat_t ());
186- if (lr != ll)
187- return traits::compose (sfirst, lr);
149+ const local_result_t r = (sorted_until_rec)
150+ (traits::local (first), ll, comp, prev, is_local_seg_t (), local_cat_t ());
151+ return segduo<SegIter, DeepIt>(traits::compose (sfirst, r.first ), r.second );
188152 }
189153 else {
190- // First segment: from local(first) to end(sfirst)
191- {
192- const local_iterator le = traits::end (sfirst);
193- const local_iterator lr = (sorted_until_rec)
194- (traits::local (first), le, comp, prev, has_prev, is_local_seg_t (), local_cat_t ());
195- if (lr != le)
196- return traits::compose (sfirst, lr);
197- }
198- // Middle segments
154+ local_iterator le = traits::end (sfirst);
155+ local_result_t r = (sorted_until_rec)
156+ (traits::local (first), le, comp, prev, is_local_seg_t (), local_cat_t ());
157+ if (r.first != le)
158+ return segduo<SegIter, DeepIt>(traits::compose (sfirst, r.first ), r.second );
159+
199160 for (++sfirst; sfirst != slast; ++sfirst) {
200- const local_iterator le = traits::end (sfirst);
201- const local_iterator lr = (sorted_until_rec)
202- (traits::begin (sfirst), le, comp, prev, has_prev, is_local_seg_t (), local_cat_t ());
203- if (lr != le)
204- return traits::compose (sfirst, lr);
205- }
206- // Last segment: from begin(slast) to local(last)
207- {
208- const local_iterator ll = traits::local (last);
209- const local_iterator lr = (sorted_until_rec)
210- (traits::begin (slast), ll, comp, prev, has_prev, is_local_seg_t (), local_cat_t ());
211- if (lr != ll)
212- return traits::compose (sfirst, lr);
161+ le = traits::end (sfirst);
162+ r = (sorted_until_rec)
163+ (traits::begin (sfirst), le, comp, r.second , is_local_seg_t (), local_cat_t ());
164+ if (r.first != le)
165+ return segduo<SegIter, DeepIt>(traits::compose (sfirst, r.first ), r.second );
213166 }
167+ r = (sorted_until_rec)
168+ (traits::begin (slast), traits::local (last), comp, r.second , is_local_seg_t (), local_cat_t ());
169+ return segduo<SegIter, DeepIt>(traits::compose (sfirst, r.first ), r.second );
214170 }
215- return last;
216171}
217172
218173} // namespace detail_algo
@@ -224,14 +179,18 @@ template <class FwdIt, class Sent, class Comp>
224179BOOST_CONTAINER_FORCEINLINE
225180FwdIt segmented_is_sorted_until (FwdIt first, Sent last, Comp comp)
226181{
227- typedef segmented_iterator_traits<FwdIt> traits;
228- typedef typename detail_algo::deepest_local_iterator<FwdIt>::type deep_it;
229- deep_it prev = deep_it ();
230- bool has_prev = false ;
182+ if (first == last)
183+ return first;
184+
185+ typedef segmented_iterator_traits<FwdIt> traits;
186+ typedef detail_algo::deepest_local_iterator<FwdIt> deep_it_helper;
187+ typedef typename deep_it_helper::type deep_it;
188+
189+ deep_it prev = deep_it_helper::get (first);
231190 return detail_algo::sorted_until_rec
232- (first, last, comp, prev, has_prev ,
233- typename traits::is_segmented_iterator (),
234- typename iterator_traits<FwdIt>::iterator_category ());
191+ (++ first, last, comp, prev,
192+ typename traits::is_segmented_iterator (),
193+ typename iterator_traits<FwdIt>::iterator_category ()). first ;
235194}
236195
237196// ! Returns an iterator to the first element that is less than its predecessor
@@ -249,4 +208,4 @@ FwdIt segmented_is_sorted_until(FwdIt first, Sent last)
249208
250209#include < boost/container/detail/config_end.hpp>
251210
252- #endif // BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_IS_SORTED_UNTIL_HPP
211+ #endif // BOOST_CONTAINER_EXPERIMENTAL_SEGMENTED_IS_SORTED_UNTIL_HPP
0 commit comments