Advertisement
Dukales

Peak finder

Nov 22nd, 2012
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.49 KB | None | 0 0
  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.         : partition_iterator_base(std::move(other.o))
  103.     {
  104.         this->swap(other);
  105.     }
  106.  
  107.     template < class I_, bool valley_, bool peak_, bool plain_ >
  108.     partition_iterator_base & operator = (
  109.             other_partition_iterator_base< I_, valley_, peak_, plain_ > other
  110.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  111.             // defenseless poor thing
  112.         #endif
  113.             ) noexcept
  114.     {
  115.         this->swap(other);
  116.         return *this;
  117.     }
  118.  
  119.  
  120.     template < class I_, bool valley_, bool peak_, bool plain_ >
  121.     friend
  122.     void swap(
  123.             partition_iterator_base & lhs
  124.             , other_partition_iterator_base< I_, valley_, peak_, plain_ > & rhs
  125.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  126.             , typename boost::detail::enable_if_interoperable< I_, I, enabler >::type = enabler()
  127.         #endif
  128.             ) noexcept
  129.     {
  130.         lhs.swap(rhs);
  131.     }
  132.  
  133. private :
  134.  
  135.     friend class boost::iterator_core_access;
  136.  
  137.     template< class I_, bool valley_, bool peak_, bool plain_ >
  138.     bool equal(
  139.             other_partition_iterator_base< I_, valley_, peak_, plain_ > const & other
  140.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  141.             , typename boost::detail::enable_if_interoperable< I_, I, enabler >::type = enabler()
  142.         #endif
  143.             ) const
  144.     {
  145.         return ((prev == other.prev) || ((prev == invalid) && (other.prev == other.invalid)));
  146.     }
  147.  
  148.     void increment()
  149.     {
  150.         I curr(next);
  151.         if (next != invalid) {
  152.             while (++next != invalid) {
  153.                 bool const pc(o(*prev, *curr));
  154.                 bool const cp(o(*curr, *prev));
  155.                 bool const nc(o(*next, *curr));
  156.                 bool const cn(o(*curr, *next));
  157.                 if (plain) { // plains borders
  158.                     if ((pc || cp) != (nc || cn)) { // xor: http://stackoverflow.com/questions/1596668
  159.                         break;
  160.                     }
  161.                 }
  162.                 if (cp && cn) {
  163.                     if (valley) {
  164.                         break;
  165.                     } else {
  166.                         prev = curr;
  167.                     }
  168.                 } else if (pc && nc) {
  169.                     if (peak) {
  170.                         break;
  171.                     } else {
  172.                         prev = curr;
  173.                     }
  174.                 }
  175.                 curr = next;
  176.             }
  177.         }
  178.         prev = curr;
  179.     }
  180.  
  181.     typename I::reference dereference() const
  182.     {
  183.         return *prev;
  184.     }
  185.  
  186. private :
  187.  
  188.     O o;
  189.  
  190.     I prev;
  191.     I next;
  192.     I invalid;
  193.  
  194.     template < class I_, bool valley_, bool peak_, bool plain_ >
  195.     void swap(
  196.             other_partition_iterator_base< I_, valley_, peak_, plain_ > & other
  197.         #if !defined(BOOST_NO_SFINAE) && defined(PARTITION_CHECK_IS_ITERATOR_CONVERTIBLE)
  198.             , typename boost::detail::enable_if_interoperable< I_, I, enabler >::type = enabler()
  199.         #endif
  200.             ) noexcept
  201.     {
  202.         using std::swap;
  203.         swap(prev, other.prev);
  204.         swap(next, other.next);
  205.         swap(invalid, other.invalid);
  206.     }
  207.  
  208. };
  209.  
  210. template < class container, bool valley, bool peak, bool plain, class O = std::less< typename container::value_type > const >
  211. using partition_iterator = partition_iterator_base< typename container::iterator, valley, peak, plain, O >;
  212. template < class container, bool valley, bool peak, bool plain, class O = std::less< typename container::value_type > const >
  213. using const_partition_iterator = partition_iterator_base< typename container::const_iterator, valley, peak, plain, O >;
  214.  
  215. template< class container, class O = std::less< typename container::value_type > const >
  216. using peak_iterator = partition_iterator< container, true, false, false, O >;
  217. template< class container, class O = std::less< typename container::value_type > const >
  218. using const_peak_iterator = const_partition_iterator< container, true, false, false, O >;
  219.  
  220. } // namespace mas::details
  221.  
  222. using details::partition_iterator;
  223. using details::const_partition_iterator;
  224.  
  225. using details::peak_iterator;
  226. using details::const_peak_iterator;
  227.  
  228. } // namespace msa
  229.  
  230. #endif // PARTITION_HPP
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement