00001
00002
00003
00004
00005
00006
00007
00008 #ifndef ADOBE_ALGORITHM_SELECTION_HPP
00009 #define ADOBE_ALGORITHM_SELECTION_HPP
00010
00011 #include <adobe/config.hpp>
00012
00013 #include <algorithm>
00014 #include <functional>
00015 #include <vector>
00016
00017 #include <boost/range/begin.hpp>
00018 #include <boost/range/end.hpp>
00019 #include <boost/range/value_type.hpp>
00020 #include <boost/range/size_type.hpp>
00021 #include <boost/range/size.hpp>
00022
00023 #include <adobe/algorithm/other_of.hpp>
00024 #include <adobe/algorithm/rotate.hpp>
00025 #include <adobe/iterator/type_functions.hpp>
00026
00027
00028
00029 namespace adobe {
00030
00031
00047
00054 template <typename S,
00055 typename O,
00056 typename P>
00057 inline O selection_operation_remainder(S first,
00058 S last,
00059 O output,
00060 bool this_inside,
00061 bool other_inside,
00062 P pred)
00063 {
00064 bool prev_op_result(pred(this_inside, other_inside));
00065
00066 while (first != last)
00067 {
00068 this_inside = !this_inside;
00069
00070 bool cur_op_result(pred(this_inside, other_inside));
00071
00072 if (prev_op_result ^ cur_op_result)
00073 *output++ = *first;
00074
00075 prev_op_result = cur_op_result;
00076
00077 ++first;
00078 }
00079
00080 return output;
00081 }
00082
00083
00089 template <typename C1,
00090 typename C2 = C1>
00091 struct logical_xor : std::binary_function<C1, C2, bool>
00092 {
00094 bool operator()(const C1& x, const C2& y) const
00095 { return static_cast<bool>(x) ^ static_cast<bool>(y); }
00096 };
00097
00098
00104 template <typename S1,
00105 typename S2,
00106 typename O,
00107 typename P,
00108 typename C>
00109 O selection_operation(S1 s1_first,
00110 S1 s1_last,
00111 S2 s2_first,
00112 S2 s2_last,
00113 O output,
00114 bool s1_inside,
00115 bool s2_inside,
00116 P pred,
00117 C comp)
00118 {
00119 if (s1_first == s1_last)
00120 return selection_operation_remainder(s2_first, s2_last, output, s2_inside, s1_inside, pred);
00121 else if (s2_first == s2_last)
00122 return selection_operation_remainder(s1_first, s1_last, output, s1_inside, s2_inside, pred);
00123
00124 bool prev_op_result(pred(s1_inside, s2_inside));
00125
00126 while (true)
00127 {
00128 typename std::iterator_traits<S1>::value_type next(comp(*s1_first, *s2_first) ? *s1_first : *s2_first);
00129
00130 if (*s1_first == next)
00131 {
00132 s1_inside = !s1_inside;
00133
00134 ++s1_first;
00135 }
00136
00137 if (*s2_first == next)
00138 {
00139 s2_inside = !s2_inside;
00140
00141 ++s2_first;
00142 }
00143
00144 bool cur_op_result(pred(s1_inside, s2_inside));
00145
00146 if (prev_op_result ^ cur_op_result)
00147 *output++ = next;
00148
00149 prev_op_result = cur_op_result;
00150
00151 if (s1_first == s1_last)
00152 return selection_operation_remainder(s2_first, s2_last, output, s2_inside, s1_inside, pred);
00153 else if (s2_first == s2_last)
00154 return selection_operation_remainder(s1_first, s1_last, output, s1_inside, s2_inside, pred);
00155 }
00156
00157 return output;
00158 }
00159
00160
00166 template <typename S1,
00167 typename S2,
00168 typename O,
00169 typename C>
00170 inline O selection_union(S1 s1_first,
00171 S1 s1_last,
00172 S2 s2_first,
00173 S2 s2_last,
00174 O output,
00175 C comp,
00176 bool s1_inside = false,
00177 bool s2_inside = false)
00178 {
00179 return selection_operation(s1_first, s1_last,
00180 s2_first, s2_last,
00181 output,
00182 s1_inside,
00183 s2_inside,
00184 std::logical_or<bool>(),
00185 comp);
00186 }
00187
00188
00194 template <typename S1,
00195 typename S2,
00196 typename O,
00197 typename C>
00198 inline O selection_intersection(S1 s1_first,
00199 S1 s1_last,
00200 S2 s2_first,
00201 S2 s2_last,
00202 O output,
00203 C comp,
00204 bool s1_inside = false,
00205 bool s2_inside = false)
00206 {
00207 return selection_operation(s1_first, s1_last,
00208 s2_first, s2_last,
00209 output,
00210 s1_inside,
00211 s2_inside,
00212 std::logical_and<bool>(),
00213 comp);
00214 }
00215
00216
00222 template <typename S1,
00223 typename S2,
00224 typename O,
00225 typename C>
00226 inline O selection_difference(S1 s1_first,
00227 S1 s1_last,
00228 S2 s2_first,
00229 S2 s2_last,
00230 O output,
00231 C comp,
00232 bool s1_inside = false,
00233 bool s2_inside = false)
00234 {
00235 return selection_intersection(s1_first, s1_last,
00236 s2_first, s2_last,
00237 output,
00238 comp,
00239 s1_inside,
00240 !s2_inside);
00241 }
00242
00243
00249 template <typename S1,
00250 typename S2,
00251 typename O,
00252 typename C>
00253 inline O selection_symmetric_difference(S1 s1_first,
00254 S1 s1_last,
00255 S2 s2_first,
00256 S2 s2_last,
00257 O output,
00258 C comp,
00259 bool s1_inside = false,
00260 bool s2_inside = false)
00261 {
00262 return selection_operation(s1_first, s1_last,
00263 s2_first, s2_last,
00264 output,
00265 s1_inside,
00266 s2_inside,
00267 logical_xor<bool>(),
00268 comp);
00269 }
00270
00271
00277 template <typename S1,
00278 typename S2,
00279 typename C>
00280 inline bool selection_includes(S1 s1_first,
00281 S1 s1_last,
00282 S2 s2_first,
00283 S2 s2_last,
00284 C comp,
00285 bool s1_inside = false,
00286 bool s2_inside = false)
00287 {
00288 if (s1_inside == s2_inside)
00289 {
00290 typedef typename std::iterator_traits<S1>::value_type value_type;
00291
00292 std::vector<value_type> result;
00293
00294 selection_intersection(s1_first, s1_last,
00295 s2_first, s2_last,
00296 std::back_inserter(result),
00297 comp,
00298 s1_inside, s2_inside);
00299
00300 return std::equal(s2_first, s2_last, result.begin());
00301 }
00302 else if (s1_inside)
00303 {
00304 return selection_includes(boost::next(s1_first), s1_last,
00305 s2_first, s2_last,
00306 comp, !s1_inside, s2_inside);
00307 }
00308
00309
00310 return selection_includes(s1_first, s1_last,
00311 boost::next(s2_first), s2_last,
00312 comp, s1_inside, !s2_inside);
00313 }
00314
00315
00321 template <typename Selection1, typename Selection2>
00322 Selection1 selection_intersection(const Selection1& x, const Selection2& y)
00323 {
00324 if (&x == &y)
00325 return x;
00326
00327 Selection1 result;
00328
00329 adobe::selection_intersection(x.begin(), x.end(),
00330 y.begin(), y.end(),
00331 std::back_inserter(result),
00332 std::less<typename boost::range_value<Selection1>::type>(),
00333 start_selected(x),
00334 start_selected(y));
00335
00336 return result;
00337 }
00338
00339
00345 template <typename Selection1, typename Selection2>
00346 Selection1 selection_union(const Selection1& x, const Selection2& y)
00347 {
00348 if (&x == &y)
00349 return x;
00350
00351 Selection1 result;
00352
00353 adobe::selection_union(x.begin(), x.end(),
00354 y.begin(), y.end(),
00355 std::back_inserter(result),
00356 std::less<typename boost::range_value<Selection1>::type>(),
00357 start_selected(x),
00358 start_selected(y));
00359
00360 return result;
00361 }
00362
00363
00369 template <typename Selection1, typename Selection2>
00370 Selection1 selection_difference(const Selection1& x, const Selection2& y)
00371 {
00372 if (&x == &y)
00373 return Selection1();
00374
00375 Selection1 result;
00376
00377 adobe::selection_difference(x.begin(), x.end(),
00378 y.begin(), y.end(),
00379 std::back_inserter(result),
00380 std::less<typename boost::range_value<Selection1>::type>(),
00381 start_selected(x),
00382 start_selected(y));
00383
00384 return result;
00385 }
00386
00387
00393 template <typename Selection1, typename Selection2>
00394 Selection1 selection_symmetric_difference(const Selection1& x, const Selection2& y)
00395 {
00396 if (&x == &y)
00397 return Selection1();
00398
00399 Selection1 result;
00400
00401 adobe::selection_symmetric_difference(x.begin(), x.end(),
00402 y.begin(), y.end(),
00403 std::back_inserter(result),
00404 std::less<typename boost::range_value<Selection1>::type>(),
00405 start_selected(x),
00406 start_selected(y));
00407
00408 return result;
00409 }
00410
00411
00417 template <typename Selection1, typename Selection2>
00418 bool selection_includes(const Selection1& x, const Selection2& y)
00419 {
00420 if (&x == &y)
00421 return true;
00422
00423 return adobe::selection_includes(x.begin(), x.end(),
00424 y.begin(), y.end(),
00425 std::less<typename boost::range_value<Selection1>::type>(),
00426 start_selected(x),
00427 start_selected(y));
00428 }
00429
00430
00436 template <typename Selection>
00437 inline void invert(Selection& x)
00438 { x.invert(); }
00439
00440
00446 template <typename Selection>
00447 inline bool start_selected(const Selection& x)
00448 { return x.start_selected(); }
00449
00450
00456 template <typename Selection>
00457 inline typename boost::range_size<Selection>::type size(const Selection& x)
00458 { return x.size(); }
00459
00460
00466 template <typename Selection, typename ForwardRange>
00467 typename boost::range_size<Selection>::type size(const Selection& x, const ForwardRange& range)
00468 {
00469 typedef typename boost::range_const_iterator<Selection>::type selection_const_iterator;
00470 typedef typename boost::range_size<Selection>::type selection_size_type;
00471 typedef typename boost::range_const_iterator<ForwardRange>::type range_const_iterator;
00472
00473 if (x.empty())
00474 return 0;
00475
00476
00477
00478 if (x.size() == 0)
00479 return boost::size(range);
00480
00481 selection_const_iterator s_iter(boost::begin(x));
00482 selection_const_iterator s_last(boost::end(x));
00483
00484 range_const_iterator prev(boost::begin(range));
00485 range_const_iterator iter(boost::next(prev, *s_iter));
00486 range_const_iterator last(boost::end(range));
00487
00488 selection_size_type result(0);
00489 bool inside(start_selected(x));
00490
00491 while (true)
00492 {
00493 if (inside)
00494 result += static_cast<selection_size_type>(std::distance(prev, iter));
00495
00496 if (iter == last)
00497 break;
00498
00499 prev = iter;
00500
00501 iter = ++s_iter == s_last ? last : boost::next(boost::begin(range), *s_iter);
00502
00503 inside = !inside;
00504 }
00505
00506 return result;
00507 }
00508
00509
00515 template <typename Selection>
00516 bool is_selected(const Selection& x, typename Selection::value_type index)
00517 {
00518 typename boost::range_const_iterator<Selection>::type found(std::upper_bound(boost::begin(x), boost::end(x), index));
00519 typename boost::range_size<Selection>::type count(std::distance(boost::begin(x), found));
00520
00521 return (count % 2 == 1) ^ start_selected(x);
00522 }
00523
00524
00531 template <typename Selection, typename ForwardRange, typename OutputIterator>
00532 OutputIterator selection_copy(const Selection& x, const ForwardRange& range, OutputIterator output)
00533 {
00534 typedef typename boost::range_const_iterator<Selection>::type selection_const_iterator;
00535 typedef typename boost::range_const_iterator<ForwardRange>::type range_const_iterator;
00536
00537 if (boost::size(range) == 0)
00538 return output;
00539
00540 bool inside(start_selected(x));
00541
00542 selection_const_iterator s_iter(boost::begin(x));
00543 selection_const_iterator s_last(boost::end(x));
00544
00545 range_const_iterator iter(boost::begin(range));
00546 range_const_iterator last(boost::end(range));
00547
00548 while (iter != last)
00549 {
00550 if (s_iter != s_last && iter == boost::next(boost::begin(range), *s_iter))
00551 {
00552 ++s_iter;
00553
00554 inside = !inside;
00555 }
00556
00557 if (inside)
00558 *output++ = *iter;
00559
00560 ++iter;
00561 }
00562
00563 return output;
00564 }
00565
00566
00572 template <typename Selection,
00573 typename ForwardRange,
00574 typename O1,
00575 typename O2>
00576 std::pair<O1, O2> selection_partition_copy(const Selection& selection,
00577 ForwardRange& range,
00578 O1 false_output,
00579 O2 true_output)
00580 {
00581 typedef typename boost::range_const_iterator<Selection>::type selection_const_iterator;
00582 typedef typename boost::range_iterator<ForwardRange>::type range_iterator;
00583
00584 if (boost::size(range) == 0)
00585 return std::make_pair(false_output, true_output);
00586
00587 selection_const_iterator selection_first(boost::begin(selection));
00588 selection_const_iterator selection_last(boost::end(selection));
00589
00590 range_iterator first(boost::begin(range));
00591 range_iterator last(boost::end(range));
00592
00593 bool inside(start_selected(selection));
00594
00595 while (true)
00596 {
00597 range_iterator copy_last(selection_first == selection_last ? last : boost::next(boost::begin(range), *selection_first));
00598
00599
00600
00601
00602
00603 if (inside)
00604 std::copy(first, copy_last, true_output);
00605 else
00606 std::copy(first, copy_last, false_output);
00607
00608 if (copy_last == last)
00609 break;
00610
00611 first = copy_last;
00612 ++selection_first;
00613 inside = !inside;
00614 }
00615
00616 return std::make_pair(false_output, true_output);
00617 }
00618
00619
00625 template <typename Selection, typename ForwardRange, typename UnaryFunction>
00626 UnaryFunction selection_foreach(const Selection& x, const ForwardRange& range, UnaryFunction proc)
00627 {
00628 typedef typename boost::range_const_iterator<Selection>::type selection_const_iterator;
00629 typedef typename boost::range_const_iterator<ForwardRange>::type range_const_iterator;
00630
00631 bool inside(start_selected(x));
00632
00633 selection_const_iterator s_iter(boost::begin(x));
00634 selection_const_iterator s_last(boost::end(x));
00635
00636 range_const_iterator iter(boost::begin(range));
00637 range_const_iterator last(boost::end(range));
00638
00639 while (iter != last)
00640 {
00641 if (s_iter != s_last && iter == boost::next(boost::begin(range), *s_iter))
00642 {
00643 ++s_iter;
00644
00645 inside = !inside;
00646 }
00647
00648 if (inside)
00649 proc(*iter);
00650
00651 ++iter;
00652 }
00653
00654 return proc;
00655 }
00656
00657
00663 template <typename Selection>
00664 inline
00665 std::pair<typename boost::range_const_iterator<Selection>::type,
00666 typename boost::range_size<Selection>::type>
00667 selection_find_boundary(const Selection& selection,
00668 typename Selection::size_type p,
00669 std::random_access_iterator_tag)
00670 {
00671 typedef typename boost::range_const_iterator<Selection>::type const_iterator;
00672 typedef typename boost::range_size<Selection>::type size_type;
00673 typedef std::pair<const_iterator, size_type> result_type;
00674
00675 const_iterator bound(std::lower_bound(boost::begin(selection), boost::end(selection), p));
00676
00677 return result_type(bound, static_cast<size_type>(std::distance(boost::begin(selection), bound)));
00678 }
00679
00680
00686 template <typename Selection>
00687 std::pair<typename boost::range_const_iterator<Selection>::type,
00688 typename boost::range_size<Selection>::type>
00689 selection_find_boundary(const Selection& selection,
00690 typename Selection::size_type p,
00691 std::forward_iterator_tag)
00692 {
00693 typedef typename boost::range_const_iterator<Selection>::type const_iterator;
00694 typedef typename boost::range_size<Selection>::type size_type;
00695 typedef std::pair<const_iterator, size_type> result_type;
00696
00697 const_iterator iter(boost::begin(selection));
00698 const_iterator last(boost::end(selection));
00699 size_type boundary_count(0);
00700
00701 while (iter != last && *iter < p)
00702 {
00703 ++boundary_count;
00704 ++iter;
00705 }
00706
00707 return result_type(iter, boundary_count);
00708 }
00709
00710
00729 template <typename Selection>
00730 inline
00731 std::pair<typename boost::range_const_iterator<Selection>::type,
00732 typename boost::range_size<Selection>::type>
00733 selection_find_boundary(const Selection& selection,
00734 typename Selection::size_type p)
00735 {
00736 typedef typename boost::range_const_iterator<Selection>::type const_iterator;
00737 typedef typename boost::range_size<Selection>::type size_type;
00738 typedef std::pair<const_iterator, size_type> result_type;
00739 typedef typename iterator_category<const_iterator>::type iterator_category;
00740
00741 if (boost::size(selection) == 0)
00742 return result_type(boost::end(selection), 0);
00743
00744 return selection_find_boundary(selection, p, iterator_category());
00745 }
00746
00747
00779 template <typename SelectionIterator, typename RangeIterator>
00780 RangeIterator selection_stable_partition(SelectionIterator selection_first,
00781 SelectionIterator selection_last,
00782 RangeIterator first,
00783 RangeIterator range_first,
00784 RangeIterator range_last,
00785 std::size_t boundary_count = 0)
00786 {
00787 std::size_t n(static_cast<std::size_t>(std::distance(selection_first, selection_last)));
00788
00789 if (n == 0)
00790 return boundary_count % 2 ? range_first : range_last;
00791
00792 std::size_t half(n / 2);
00793 SelectionIterator selection_middle(boost::next(selection_first, half));
00794 RangeIterator range_middle(boost::next(first, *selection_middle));
00795
00796 RangeIterator i(selection_stable_partition(selection_first, selection_middle,
00797 first, range_first, range_middle,
00798 boundary_count));
00799
00800 RangeIterator j(selection_stable_partition(boost::next(selection_middle), selection_last,
00801 first, range_middle, range_last,
00802 boundary_count + half + 1));
00803
00804 return other_of(adobe::rotate(i, range_middle, j), range_middle);
00805 }
00806
00807
00813 template <typename Selection,
00814 typename ForwardRange>
00815 inline
00816 typename boost::range_iterator<ForwardRange>::type
00817 selection_stable_partition(const Selection& selection,
00818 ForwardRange& range)
00819 {
00820 return selection_stable_partition(boost::begin(selection), boost::end(selection),
00821 boost::begin(range),
00822 boost::begin(range), boost::end(range),
00823 start_selected(selection));
00824 }
00825
00826
00862 template <typename Selection,
00863 typename ForwardRange>
00864 std::pair<typename boost::range_iterator<ForwardRange>::type,
00865 typename boost::range_iterator<ForwardRange>::type>
00866 selection_stable_partition_about(const Selection& selection,
00867 ForwardRange& range,
00868 std::size_t p,
00869 typename boost::range_size<Selection>::type prior_boundary_count = 0)
00870 {
00871 typedef typename boost::range_size<Selection>::type size_type;
00872 typedef typename boost::range_const_iterator<Selection>::type selection_const_iterator;
00873 typedef typename boost::range_iterator<ForwardRange>::type range_iterator;
00874
00875 std::pair<selection_const_iterator, size_type> selection_split =
00876 adobe::selection_find_boundary(selection, p);
00877
00878 range_iterator first(boost::begin(range));
00879 range_iterator range_p(boost::next(first, p));
00880 range_iterator last(boost::end(range));
00881
00882 range_iterator i(selection_stable_partition(boost::begin(selection), selection_split.first,
00883 first, first, range_p,
00884 prior_boundary_count));
00885
00886 range_iterator j(selection_stable_partition(selection_split.first, boost::end(selection),
00887 first, range_p, last,
00888 selection_split.second + 1));
00889
00890 return std::pair<range_iterator, range_iterator>(i, j);
00891 }
00892
00893
00899 template <typename Selection,
00900 typename ForwardRange>
00901 Selection index_set_to_selection(const ForwardRange& index_set)
00902 {
00903 Selection result;
00904
00905
00906
00907
00908 typedef typename boost::range_const_iterator<ForwardRange>::type range_const_iterator;
00909
00910 range_const_iterator iter(boost::begin(index_set));
00911 range_const_iterator last(boost::end(index_set));
00912
00913 for (; iter != last; ++iter)
00914 {
00915 Selection tmp;
00916
00917 tmp.push_back(*iter);
00918 tmp.push_back(*iter + 1);
00919
00920 result = selection_union(result, tmp);
00921 }
00922
00923 return result;
00924 }
00925
00926
00932 template <typename Selection,
00933 typename OutputIterator>
00934 OutputIterator selection_to_index_set(const Selection& selection,
00935 typename boost::range_size<Selection>::type max_index,
00936 OutputIterator output)
00937 {
00938 typedef typename boost::range_size<Selection>::type size_type;
00939 typedef typename boost::range_const_iterator<Selection>::type selection_const_iterator;
00940
00941 bool selected(start_selected(selection));
00942 std::size_t index(0);
00943 selection_const_iterator iter(boost::begin(selection));
00944 selection_const_iterator last(boost::end(selection));
00945
00946 while (iter != last)
00947 {
00948 while (index != *iter && index != max_index)
00949 {
00950 if (selected)
00951 *output++ = index;
00952
00953 ++index;
00954 }
00955
00956 selected = !selected;
00957 ++iter;
00958 }
00959
00960 return output;
00961 }
00962
00963
00964
00965 }
00966
00967
00968
00969 #endif
00970
00971