Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:41:54

0001 /*=============================================================================
0002     Copyright (c) 2011 Eric Niebler
0003 
0004     Distributed under the Boost Software License, Version 1.0. (See accompanying
0005     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 ==============================================================================*/
0007 #if !defined(BOOST_FUSION_SEGMENTED_ITERATOR_RANGE_HPP_INCLUDED)
0008 #define BOOST_FUSION_SEGMENTED_ITERATOR_RANGE_HPP_INCLUDED
0009 
0010 #include <boost/fusion/support/config.hpp>
0011 #include <boost/detail/workaround.hpp>
0012 #include <boost/mpl/assert.hpp>
0013 #include <boost/type_traits/add_const.hpp>
0014 #include <boost/type_traits/remove_reference.hpp>
0015 #include <boost/fusion/support/tag_of.hpp>
0016 #include <boost/fusion/sequence/intrinsic/begin.hpp>
0017 #include <boost/fusion/sequence/intrinsic/end.hpp>
0018 #include <boost/fusion/iterator/next.hpp>
0019 #include <boost/fusion/iterator/deref.hpp>
0020 #include <boost/fusion/sequence/intrinsic/segments.hpp>
0021 #include <boost/fusion/algorithm/transformation/push_back.hpp>
0022 #include <boost/fusion/algorithm/transformation/push_front.hpp>
0023 #include <boost/fusion/iterator/equal_to.hpp>
0024 #include <boost/fusion/container/list/detail/reverse_cons.hpp>
0025 #include <boost/fusion/iterator/detail/segment_sequence.hpp>
0026 #include <boost/fusion/support/is_sequence.hpp>
0027 #include <boost/utility/enable_if.hpp>
0028 
0029 //  Invariants:
0030 //  - Each segmented iterator has a stack
0031 //  - Each value in the stack is an iterator range
0032 //  - The range at the top of the stack points to values
0033 //  - All other ranges point to ranges
0034 //  - The front of each range in the stack (besides the
0035 //    topmost) is the range above it
0036 
0037 namespace boost { namespace fusion
0038 {
0039     template <typename First, typename Last>
0040     struct iterator_range;
0041 
0042     namespace result_of
0043     {
0044         template <typename Sequence, typename T>
0045         struct push_back;
0046 
0047         template <typename Sequence, typename T>
0048         struct push_front;
0049     }
0050 
0051     template <typename Sequence, typename T>
0052     BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0053     inline typename
0054         lazy_enable_if<
0055             traits::is_sequence<Sequence>
0056           , result_of::push_back<Sequence const, T>
0057         >::type
0058     push_back(Sequence const& seq, T const& x);
0059 
0060     template <typename Sequence, typename T>
0061     BOOST_CXX14_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0062     inline typename
0063         lazy_enable_if<
0064             traits::is_sequence<Sequence>
0065           , result_of::push_front<Sequence const, T>
0066         >::type
0067     push_front(Sequence const& seq, T const& x);
0068 }}
0069 
0070 namespace boost { namespace fusion { namespace detail
0071 {
0072     //auto make_segment_sequence_front(stack_begin)
0073     //{
0074     //  switch (size(stack_begin))
0075     //  {
0076     //  case 1:
0077     //    return nil_;
0078     //  case 2:
0079     //    // car(cdr(stack_begin)) is a range over values.
0080     //    assert(end(front(car(stack_begin))) == end(car(cdr(stack_begin))));
0081     //    return iterator_range(begin(car(cdr(stack_begin))), end(front(car(stack_begin))));
0082     //  default:
0083     //    // car(cdr(stack_begin)) is a range over segments. We replace the
0084     //    // front with a view that is restricted.
0085     //    assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin))));
0086     //    return segment_sequence(
0087     //      push_front(
0088     //        // The following could be a segment_sequence. It then gets wrapped
0089     //        // in a single_view, and push_front puts it in a join_view with the
0090     //        // following iterator_range.
0091     //        iterator_range(next(begin(car(cdr(stack_begin)))), end(segments(front(car(stack_begin))))),
0092     //        make_segment_sequence_front(cdr(stack_begin))));
0093     //  }
0094     //}
0095 
0096     template <typename Stack, std::size_t Size = Stack::size::value>
0097     struct make_segment_sequence_front
0098     {
0099         // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin))));
0100         BOOST_MPL_ASSERT((
0101             result_of::equal_to<
0102                 typename result_of::end<
0103                     typename remove_reference<
0104                         typename add_const<
0105                             typename result_of::segments<
0106                                 typename remove_reference<
0107                                     typename add_const<
0108                                         typename result_of::deref<
0109                                             typename Stack::car_type::begin_type
0110                                         >::type
0111                                     >::type
0112                                 >::type
0113                             >::type
0114                         >::type
0115                     >::type
0116                 >::type
0117               , typename Stack::cdr_type::car_type::end_type
0118             >));
0119 
0120         typedef
0121             iterator_range<
0122                 typename result_of::next<
0123                     typename Stack::cdr_type::car_type::begin_type
0124                 >::type
0125               , typename result_of::end<
0126                     typename remove_reference<
0127                         typename add_const<
0128                             typename result_of::segments<
0129                                 typename remove_reference<
0130                                     typename add_const<
0131                                         typename result_of::deref<
0132                                             typename Stack::car_type::begin_type
0133                                         >::type
0134                                     >::type
0135                                 >::type
0136                             >::type
0137                         >::type
0138                     >::type
0139                 >::type
0140             >
0141         rest_type;
0142 
0143         typedef
0144             make_segment_sequence_front<typename Stack::cdr_type>
0145         recurse;
0146 
0147         typedef
0148             segment_sequence<
0149                 typename result_of::push_front<
0150                     rest_type const
0151                   , typename recurse::type
0152                 >::type
0153             >
0154         type;
0155 
0156         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0157         static type call(Stack const& stack)
0158         {
0159             //return segment_sequence(
0160             //  push_front(
0161             //    iterator_range(next(begin(car(cdr(stack_begin)))), end(segments(front(car(stack_begin))))),
0162             //    make_segment_sequence_front(cdr(stack_begin))));
0163             return type(
0164                 fusion::push_front(
0165                     rest_type(fusion::next(stack.cdr.car.first), fusion::end(fusion::segments(*stack.car.first)))
0166                   , recurse::call(stack.cdr)));
0167         }
0168     };
0169 
0170     template <typename Stack>
0171     struct make_segment_sequence_front<Stack, 2>
0172     {
0173         // assert(end(front(car(stack_begin))) == end(car(cdr(stack_begin))));
0174         BOOST_MPL_ASSERT((
0175             result_of::equal_to<
0176                 typename result_of::end<
0177                     typename remove_reference<
0178                         typename add_const<
0179                             typename result_of::deref<
0180                                 typename Stack::car_type::begin_type
0181                             >::type
0182                         >::type
0183                     >::type
0184                 >::type
0185               , typename Stack::cdr_type::car_type::end_type
0186             >));
0187 
0188         typedef
0189             iterator_range<
0190                 typename Stack::cdr_type::car_type::begin_type
0191               , typename result_of::end<
0192                     typename remove_reference<
0193                         typename add_const<
0194                             typename result_of::deref<
0195                                 typename Stack::car_type::begin_type
0196                             >::type
0197                         >::type
0198                     >::type
0199                 >::type
0200             >
0201         type;
0202 
0203         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0204         static type call(Stack const& stack)
0205         {
0206             // return iterator_range(begin(car(cdr(stack_begin))), end(front(car(stack_begin))));
0207             return type(stack.cdr.car.first, fusion::end(*stack.car.first));
0208         }
0209     };
0210 
0211     template <typename Stack>
0212     struct make_segment_sequence_front<Stack, 1>
0213     {
0214         typedef typename Stack::cdr_type type; // nil_
0215 
0216         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0217         static type call(Stack const &stack)
0218         {
0219             return stack.cdr;
0220         }
0221     };
0222 
0223     //auto make_segment_sequence_back(stack_end)
0224     //{
0225     //  switch (size(stack_end))
0226     //  {
0227     //  case 1:
0228     //    return nil_;
0229     //  case 2:
0230     //    // car(cdr(stack_back)) is a range over values.
0231     //    assert(end(front(car(stack_end))) == end(car(cdr(stack_end))));
0232     //    return iterator_range(begin(front(car(stack_end))), begin(car(cdr(stack_end))));
0233     //  default:
0234     //    // car(cdr(stack_begin)) is a range over segments. We replace the
0235     //    // back with a view that is restricted.
0236     //    assert(end(segments(front(car(stack_end)))) == end(car(cdr(stack_end))));
0237     //    return segment_sequence(
0238     //      push_back(
0239     //        iterator_range(begin(segments(front(car(stack_end)))), begin(car(cdr(stack_end)))),
0240     //        make_segment_sequence_back(cdr(stack_end))));
0241     //  }
0242     //}
0243 
0244     template <typename Stack, std::size_t Size = Stack::size::value>
0245     struct make_segment_sequence_back
0246     {
0247         // assert(end(segments(front(car(stack_begin)))) == end(car(cdr(stack_begin))));
0248         BOOST_MPL_ASSERT((
0249             result_of::equal_to<
0250                 typename result_of::end<
0251                     typename remove_reference<
0252                         typename add_const<
0253                             typename result_of::segments<
0254                                 typename remove_reference<
0255                                     typename add_const<
0256                                         typename result_of::deref<
0257                                             typename Stack::car_type::begin_type
0258                                         >::type
0259                                     >::type
0260                                 >::type
0261                             >::type
0262                         >::type
0263                     >::type
0264                 >::type
0265               , typename Stack::cdr_type::car_type::end_type
0266             >));
0267 
0268         typedef
0269             iterator_range<
0270                 typename result_of::begin<
0271                     typename remove_reference<
0272                         typename add_const<
0273                             typename result_of::segments<
0274                                 typename remove_reference<
0275                                     typename add_const<
0276                                         typename result_of::deref<
0277                                             typename Stack::car_type::begin_type
0278                                         >::type
0279                                     >::type
0280                                 >::type
0281                             >::type
0282                         >::type
0283                     >::type
0284                 >::type
0285               , typename Stack::cdr_type::car_type::begin_type
0286             >
0287         rest_type;
0288 
0289         typedef
0290             make_segment_sequence_back<typename Stack::cdr_type>
0291         recurse;
0292 
0293         typedef
0294             segment_sequence<
0295                 typename result_of::push_back<
0296                     rest_type const
0297                   , typename recurse::type
0298                 >::type
0299             >
0300         type;
0301 
0302         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0303         static type call(Stack const& stack)
0304         {
0305             //  return segment_sequence(
0306             //    push_back(
0307             //      iterator_range(begin(segments(front(car(stack_end)))), begin(car(cdr(stack_end)))),
0308             //      make_segment_sequence_back(cdr(stack_end))));
0309             return type(
0310                 fusion::push_back(
0311                     rest_type(fusion::begin(fusion::segments(*stack.car.first)), stack.cdr.car.first)
0312                   , recurse::call(stack.cdr)));
0313         }
0314     };
0315 
0316     template <typename Stack>
0317     struct make_segment_sequence_back<Stack, 2>
0318     {
0319         // assert(end(front(car(stack_end))) == end(car(cdr(stack_end))));
0320         BOOST_MPL_ASSERT((
0321             result_of::equal_to<
0322                 typename result_of::end<
0323                     typename remove_reference<
0324                         typename add_const<
0325                             typename result_of::deref<
0326                                 typename Stack::car_type::begin_type
0327                             >::type
0328                         >::type
0329                     >::type
0330                 >::type
0331               , typename Stack::cdr_type::car_type::end_type
0332             >));
0333 
0334         typedef
0335             iterator_range<
0336                 typename result_of::begin<
0337                     typename remove_reference<
0338                         typename add_const<
0339                             typename result_of::deref<
0340                                 typename Stack::car_type::begin_type
0341                             >::type
0342                         >::type
0343                     >::type
0344                 >::type
0345               , typename Stack::cdr_type::car_type::begin_type
0346             >
0347         type;
0348 
0349         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0350         static type call(Stack const& stack)
0351         {
0352             // return iterator_range(begin(front(car(stack_end))), begin(car(cdr(stack_end))));
0353             return type(fusion::begin(*stack.car.first), stack.cdr.car.first);
0354         }
0355     };
0356 
0357     template <typename Stack>
0358     struct make_segment_sequence_back<Stack, 1>
0359     {
0360         typedef typename Stack::cdr_type type; // nil_
0361 
0362         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0363         static type call(Stack const& stack)
0364         {
0365             return stack.cdr;
0366         }
0367     };
0368 
0369     //auto make_segmented_range_reduce(stack_begin, stack_end)
0370     //{
0371     //  if (size(stack_begin) == 1 && size(stack_end) == 1)
0372     //  {
0373     //    return segment_sequence(
0374     //      single_view(
0375     //        iterator_range(begin(car(stack_begin)), begin(car(stack_end)))));
0376     //  }
0377     //  else
0378     //  {
0379     //    // We are in the case where both begin_stack and/or end_stack have
0380     //    // more than one element. Throw away any part of the tree where
0381     //    // begin and end refer to the same segment.
0382     //    if (begin(car(stack_begin)) == begin(car(stack_end)))
0383     //    {
0384     //      return make_segmented_range_reduce(cdr(stack_begin), cdr(stack_end));
0385     //    }
0386     //    else
0387     //    {
0388     //      // We are in the case where begin_stack and end_stack (a) have
0389     //      // more than one element each, and (b) they point to different
0390     //      // segments. We must construct a segmented sequence.
0391     //      return segment_sequence(
0392     //          push_back(
0393     //            push_front(
0394     //                iterator_range(
0395     //                    fusion::next(begin(car(stack_begin))),
0396     //                    begin(car(stack_end))),                 // a range of (possibly segmented) ranges.
0397     //              make_segment_sequence_front(stack_begin)),    // should be a (possibly segmented) range.
0398     //            make_segment_sequence_back(stack_end)));        // should be a (possibly segmented) range.
0399     //    }
0400     //  }
0401     //}
0402 
0403     template <
0404         typename StackBegin
0405       , typename StackEnd
0406       , int StackBeginSize = StackBegin::size::value
0407       , int StackEndSize   = StackEnd::size::value>
0408     struct make_segmented_range_reduce;
0409 
0410     template <
0411         typename StackBegin
0412       , typename StackEnd
0413       , bool SameSegment
0414 #if !(BOOST_WORKAROUND(BOOST_GCC, >= 40000) && BOOST_WORKAROUND(BOOST_GCC, < 40200))
0415           = result_of::equal_to<
0416                 typename StackBegin::car_type::begin_type
0417               , typename StackEnd::car_type::begin_type
0418             >::type::value
0419 #endif
0420     >
0421     struct make_segmented_range_reduce2
0422     {
0423         typedef
0424             iterator_range<
0425                 typename result_of::next<
0426                     typename StackBegin::car_type::begin_type
0427                 >::type
0428               , typename StackEnd::car_type::begin_type
0429             >
0430         rest_type;
0431 
0432         typedef
0433             segment_sequence<
0434                 typename result_of::push_back<
0435                     typename result_of::push_front<
0436                         rest_type const
0437                       , typename make_segment_sequence_front<StackBegin>::type
0438                     >::type const
0439                   , typename make_segment_sequence_back<StackEnd>::type
0440                 >::type
0441             >
0442         type;
0443 
0444         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0445         static type call(StackBegin stack_begin, StackEnd stack_end)
0446         {
0447             //return segment_sequence(
0448             //    push_back(
0449             //      push_front(
0450             //        iterator_range(
0451             //            fusion::next(begin(car(stack_begin))),
0452             //            begin(car(stack_end))),                 // a range of (possibly segmented) ranges.
0453             //        make_segment_sequence_front(stack_begin)),  // should be a (possibly segmented) range.
0454             //      make_segment_sequence_back(stack_end)));      // should be a (possibly segmented) range.
0455             return type(
0456                 fusion::push_back(
0457                     fusion::push_front(
0458                         rest_type(fusion::next(stack_begin.car.first), stack_end.car.first)
0459                       , make_segment_sequence_front<StackBegin>::call(stack_begin))
0460                   , make_segment_sequence_back<StackEnd>::call(stack_end)));
0461         }
0462     };
0463 
0464     template <typename StackBegin, typename StackEnd>
0465     struct make_segmented_range_reduce2<StackBegin, StackEnd, true>
0466     {
0467         typedef
0468             make_segmented_range_reduce<
0469                 typename StackBegin::cdr_type
0470               , typename StackEnd::cdr_type
0471             >
0472         impl;
0473 
0474         typedef
0475             typename impl::type
0476         type;
0477 
0478         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0479         static type call(StackBegin stack_begin, StackEnd stack_end)
0480         {
0481             return impl::call(stack_begin.cdr, stack_end.cdr);
0482         }
0483     };
0484 
0485     template <typename StackBegin, typename StackEnd, int StackBeginSize, int StackEndSize>
0486     struct make_segmented_range_reduce
0487       : make_segmented_range_reduce2<StackBegin, StackEnd
0488 #if BOOST_WORKAROUND(BOOST_GCC, >= 40000) && BOOST_WORKAROUND(BOOST_GCC, < 40200)
0489           , result_of::equal_to<
0490                 typename StackBegin::car_type::begin_type
0491               , typename StackEnd::car_type::begin_type
0492             >::type::value
0493 #endif
0494         >
0495     {};
0496 
0497     template <typename StackBegin, typename StackEnd>
0498     struct make_segmented_range_reduce<StackBegin, StackEnd, 1, 1>
0499     {
0500         typedef
0501             iterator_range<
0502                 typename StackBegin::car_type::begin_type
0503               , typename StackEnd::car_type::begin_type
0504             >
0505         range_type;
0506 
0507         typedef
0508             single_view<range_type>
0509         segment_type;
0510 
0511         typedef
0512             segment_sequence<segment_type>
0513         type;
0514 
0515         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0516         static type call(StackBegin stack_begin, StackEnd stack_end)
0517         {
0518             //return segment_sequence(
0519             //  single_view(
0520             //    iterator_range(begin(car(stack_begin)), begin(car(stack_end)))));
0521             return type(segment_type(range_type(stack_begin.car.first, stack_end.car.first)));
0522         }
0523     };
0524 
0525     //auto make_segmented_range(begin, end)
0526     //{
0527     //  return make_segmented_range_reduce(reverse(begin.context), reverse(end.context));
0528     //}
0529 
0530     template <typename Begin, typename End>
0531     struct make_segmented_range
0532     {
0533         typedef reverse_cons<typename Begin::context_type>   reverse_begin_cons;
0534         typedef reverse_cons<typename End::context_type>     reverse_end_cons;
0535 
0536         typedef
0537             make_segmented_range_reduce<
0538                 typename reverse_begin_cons::type
0539               , typename reverse_end_cons::type
0540             >
0541         impl;
0542 
0543         typedef typename impl::type type;
0544 
0545         BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
0546         static type call(Begin const& begin, End const& end)
0547         {
0548             return impl::call(
0549                 reverse_begin_cons::call(begin.context)
0550               , reverse_end_cons::call(end.context));
0551         }
0552     };
0553 
0554 }}}
0555 
0556 #endif