stlab.adobe.com Adobe Systems Incorporated

selection_algorithms.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
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, // S models ForwardIterator, value_type(S) == I
00055           typename O, // O models OutputIterator
00056           typename P> // P models BinaryPredicate
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,      // C1 models ConvertibleToBool
00090           typename C2 = C1> // C2 models ConvertibleToBool
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, // S1 models ForwardIterator, value_type(S1) == value_type(S2)
00105           typename S2, // S2 models ForwardIterator, value_type(S2) == value_type(S1)
00106           typename O,  // O models OutputIterator
00107           typename P,  // P models BinaryPredicate
00108           typename C>  // C models StrictWeakOrdering
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, // S1 models ForwardIterator, value_type(S1) == I
00167           typename S2, // S2 models ForwardIterator, value_type(S2) == I
00168           typename O,  // O models OutputIterator
00169           typename C>  // C models StrictWeakOrdering
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, // S1 models ForwardIterator, value_type(S1) == I
00195           typename S2, // S2 models ForwardIterator, value_type(S2) == I
00196           typename O,  // O models OutputIterator
00197           typename C>  // C models StrictWeakOrdering
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, // S1 models ForwardIterator, value_type(S1) == I
00223           typename S2, // S2 models ForwardIterator, value_type(S2) == I
00224           typename O,  // O models OutputIterator
00225           typename C>  // C models StrictWeakOrdering
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, // S1 models ForwardIterator, value_type(S1) == I
00250           typename S2, // S2 models ForwardIterator, value_type(S2) == I
00251           typename O,  // O models OutputIterator
00252           typename C>  // C models StrictWeakOrdering
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, // S1 models InputIterator, value_type(S1) == I
00278           typename S2, // S2 models InputIterator, value_type(S2) == I
00279           typename C>  // C models StrictWeakOrdering
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     // s2_inside == true
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     // this is the case when the selection has no elements, but it starts selected
00477     // (in other words, every item in the selection is toggled as selected)
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, // O1 models OutputIterator
00575           typename O2> // O2 models OutputIterator
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         // REVISIT (fbrereto) : It'd be nice to collapse the following into ? :
00600         //                      notation, but some compilers require that the
00601         //                      types returned by ? : be the same, which we cannot
00602         //                      guarantee here.
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     // REVISIT (fbrereto) : This would go much faster using divide-and-conquer
00906     //                      and eventually balanced reduction.
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 } // namespace adobe
00966 
00967 /*************************************************************************************************/
00968 
00969 #endif
00970 
00971 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google