Dukales

Peak finder

Dec 12th, 2012
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifndef PARTITION_HPP
  2. #define PARTITION_HPP
  3.  
  4. #ifdef __GNUG__
  5. #pragma interface
  6. #endif
  7.  
  8. #include <boost/iterator/iterator_facade.hpp>
  9. #include <boost/type_traits/is_convertible.hpp>
  10.  
  11. #include <type_traits>
  12. #include <utility>
  13. #include <functional>
  14. #include <memory>
  15.  
  16. #define PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE
  17.  
  18. namespace msa
  19. {
  20.  
  21. namespace details
  22. {
  23.  
  24. template < class I, bool valley, bool peak, bool plain, class O >
  25. class partition_iterator_base
  26.         : public boost::iterator_facade<
  27.         partition_iterator_base< I, valley, peak, plain, O >
  28.         , I
  29.         , boost::forward_traversal_tag
  30.         , typename I::reference
  31.         , typename I::difference_type
  32.         >
  33. {
  34.  
  35.     struct enabler {}; // a private type avoids misuse
  36.  
  37.     template< class I_, bool valley_, bool peak_, bool plain_ >
  38.     using other_partition_iterator_base = partition_iterator_base< I_, valley_, peak_, plain_, O >;
  39.  
  40.     //template< class I_, bool valley_, bool peak_, bool plain_ > friend class other_partition_iterator_base;
  41.  
  42. public :
  43.  
  44.     ~partition_iterator_base() noexcept = default;
  45.  
  46.     explicit
  47.     partition_iterator_base(O o_ = O())
  48.         : o(o_)
  49.         , prev()
  50.         , next()
  51.         , invalid()
  52.     { ; }
  53.  
  54.     template< class I_ >
  55.     explicit
  56.     partition_iterator_base(
  57.             I_ const begin, I_ const end, O o_ = O()
  58.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  59.             , typename std::enable_if< std::is_convertible< I_, I >::value, enabler >::type = enabler()
  60.         #endif
  61.             )
  62.         : o(o_)
  63.         , prev(begin)
  64.         , next(begin)
  65.         , invalid(end)
  66.     { ; }
  67.  
  68.     template< class container >
  69.     explicit
  70.     partition_iterator_base(
  71.             container & container_, O o_ = O()
  72.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  73.             , typename std::enable_if< std::is_convertible< typename std::conditional< std::is_const< container >::value, typename container::const_iterator, typename container::iterator >::type, I >::value, enabler >::type = enabler()
  74.         #endif
  75.             )
  76.         : o(o_)
  77.         , prev(container_.begin())
  78.         , next(container_.begin())
  79.         , invalid(container_.end())
  80.     { ; }
  81.  
  82.     template < class I_, bool valley_, bool peak_, bool plain_ >
  83.     partition_iterator_base(
  84.             other_partition_iterator_base< I_, valley_, peak_, plain_ > const & other
  85.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  86.             , typename std::enable_if< std::is_convertible< I_, I >::value, enabler >::type = enabler()
  87.         #endif
  88.             )
  89.         : o(other.o)
  90.         , prev(other.prev)
  91.         , next(other.next)
  92.         , invalid(other.invalid)
  93.     { ; }
  94.  
  95.     template < class I_, bool valley_, bool peak_, bool plain_ >
  96.     partition_iterator_base(
  97.             other_partition_iterator_base< I_, valley_, peak_, plain_ > && other
  98.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  99.             , typename std::enable_if< std::is_convertible< I_, I >::value, enabler >::type = enabler()
  100.         #endif
  101.             )
  102.         : o(std::move(other.o))
  103.         , prev(std::move(other.prev))
  104.         , next(std::move(other.next))
  105.         , invalid(std::move(other.invalid))
  106.     { ; }
  107.  
  108.     template < class I_, bool valley_, bool peak_, bool plain_ >
  109.     partition_iterator_base & operator = (
  110.             other_partition_iterator_base< I_, valley_, peak_, plain_ > other
  111.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  112.             // defenseless poor thing
  113.         #endif
  114.             ) noexcept
  115.     {
  116.         this->swap(other);
  117.         return *this;
  118.     }
  119.  
  120.  
  121.     template < class I_, bool valley_, bool peak_, bool plain_ >
  122.     friend
  123.     void swap(
  124.             partition_iterator_base & lhs
  125.             , other_partition_iterator_base< I_, valley_, peak_, plain_ > & rhs
  126.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  127.             , typename boost::detail::enable_if_interoperable< I_, I, enabler >::type = enabler()
  128.         #endif
  129.             ) noexcept
  130.     {
  131.         lhs.swap(rhs);
  132.     }
  133.  
  134. private :
  135.  
  136.     friend class boost::iterator_core_access;
  137.  
  138.     template< class I_, bool valley_, bool peak_, bool plain_ >
  139.     bool equal(
  140.             other_partition_iterator_base< I_, valley_, peak_, plain_ > const & other
  141.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  142.             , typename boost::detail::enable_if_interoperable< I_, I, enabler >::type = enabler()
  143.         #endif
  144.             ) const
  145.     {
  146.         return ((prev == other.prev) || ((prev == invalid) && (other.prev == other.invalid)));
  147.     }
  148.  
  149.     void increment()
  150.     {
  151.         I curr(next);
  152.         if (next != invalid) {
  153.             while (++next != invalid) {
  154.                 bool const pc(o(*prev, *curr));
  155.                 bool const cp(o(*curr, *prev));
  156.                 bool const nc(o(*next, *curr));
  157.                 bool const cn(o(*curr, *next));
  158.                 if (plain) { // plains borders
  159.                     if ((pc || cp) != (nc || cn)) { // xor: http://stackoverflow.com/questions/1596668
  160.                         break;
  161.                     }
  162.                 }
  163.                 if (cp && cn) {
  164.                     if (valley) {
  165.                         break;
  166.                     } else {
  167.                         prev = curr;
  168.                     }
  169.                 } else if (pc && nc) {
  170.                     if (peak) {
  171.                         break;
  172.                     } else {
  173.                         prev = curr;
  174.                     }
  175.                 }
  176.                 curr = next;
  177.             }
  178.         }
  179.         prev = curr;
  180.     }
  181.  
  182.     typename I::reference dereference() const
  183.     {
  184.         return *prev;
  185.     }
  186.  
  187. private :
  188.  
  189.     O o;
  190.  
  191.     I prev;
  192.     I next;
  193.     I invalid;
  194.  
  195.     template < class I_, bool valley_, bool peak_, bool plain_ >
  196.     void swap(
  197.             other_partition_iterator_base< I_, valley_, peak_, plain_ > & other
  198.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  199.             , typename boost::detail::enable_if_interoperable< I_, I, enabler >::type = enabler()
  200.         #endif
  201.             ) noexcept
  202.     {
  203.         using std::swap;
  204.         swap(prev, other.prev);
  205.         swap(next, other.next);
  206.         swap(invalid, other.invalid);
  207.     }
  208.  
  209. };
  210.  
  211. template < class container, bool valley, bool peak, bool plain, class O = std::less< typename container::value_type > const >
  212. using partition_iterator = partition_iterator_base< typename container::iterator, valley, peak, plain, O >;
  213. template < class container, bool valley, bool peak, bool plain, class O = std::less< typename container::value_type > const >
  214. using const_partition_iterator = partition_iterator_base< typename container::const_iterator, valley, peak, plain, O >;
  215.  
  216. template< class container, class O = std::less< typename container::value_type > const >
  217. using peak_iterator = partition_iterator< container, true, false, false, O >;
  218. template< class container, class O = std::less< typename container::value_type > const >
  219. using const_peak_iterator = const_partition_iterator< container, true, false, false, O >;
  220.  
  221. } // namespace mas::details
  222.  
  223. using details::partition_iterator;
  224. using details::const_partition_iterator;
  225.  
  226. using details::peak_iterator;
  227. using details::const_peak_iterator;
  228.  
  229. } // namespace msa
  230.  
  231. #endif // PARTITION_HPP
Advertisement
Add Comment
Please, Sign In to add comment