193 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			193 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //---------------------------------------------------------------------------// | ||
|  | // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com> | ||
|  | // | ||
|  | // Distributed under the Boost Software License, Version 1.0 | ||
|  | // See accompanying file LICENSE_1_0.txt or copy at | ||
|  | // http://www.boost.org/LICENSE_1_0.txt | ||
|  | // | ||
|  | // See http://boostorg.github.com/compute for more information. | ||
|  | //---------------------------------------------------------------------------// | ||
|  | 
 | ||
|  | #ifndef BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP | ||
|  | #define BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP | ||
|  | 
 | ||
|  | #include <string> | ||
|  | #include <cstddef> | ||
|  | #include <iterator> | ||
|  | 
 | ||
|  | #include <boost/config.hpp> | ||
|  | #include <boost/iterator/iterator_adaptor.hpp> | ||
|  | 
 | ||
|  | #include <boost/compute/functional.hpp> | ||
|  | #include <boost/compute/detail/meta_kernel.hpp> | ||
|  | #include <boost/compute/detail/is_buffer_iterator.hpp> | ||
|  | #include <boost/compute/detail/read_write_single_value.hpp> | ||
|  | #include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp> | ||
|  | #include <boost/compute/type_traits/is_device_iterator.hpp> | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace compute { | ||
|  | 
 | ||
|  | // forward declaration for transform_iterator | ||
|  | template<class ElementIterator, class IndexIterator> | ||
|  | class permutation_iterator; | ||
|  | 
 | ||
|  | namespace detail { | ||
|  | 
 | ||
|  | // helper class which defines the iterator_adaptor super-class | ||
|  | // type for permutation_iterator | ||
|  | template<class ElementIterator, class IndexIterator> | ||
|  | class permutation_iterator_base | ||
|  | { | ||
|  | public: | ||
|  |     typedef ::boost::iterator_adaptor< | ||
|  |         ::boost::compute::permutation_iterator<ElementIterator, IndexIterator>, | ||
|  |         ElementIterator | ||
|  |     > type; | ||
|  | }; | ||
|  | 
 | ||
|  | template<class ElementIterator, class IndexIterator, class IndexExpr> | ||
|  | struct permutation_iterator_access_expr | ||
|  | { | ||
|  |     typedef typename std::iterator_traits<ElementIterator>::value_type result_type; | ||
|  | 
 | ||
|  |     permutation_iterator_access_expr(const ElementIterator &e, | ||
|  |                                      const IndexIterator &i, | ||
|  |                                      const IndexExpr &expr) | ||
|  |         : m_element_iter(e), | ||
|  |           m_index_iter(i), | ||
|  |           m_expr(expr) | ||
|  |     { | ||
|  |     } | ||
|  | 
 | ||
|  |     ElementIterator m_element_iter; | ||
|  |     IndexIterator m_index_iter; | ||
|  |     IndexExpr m_expr; | ||
|  | }; | ||
|  | 
 | ||
|  | template<class ElementIterator, class IndexIterator, class IndexExpr> | ||
|  | inline meta_kernel& operator<<(meta_kernel &kernel, | ||
|  |                                const permutation_iterator_access_expr<ElementIterator, | ||
|  |                                                                       IndexIterator, | ||
|  |                                                                       IndexExpr> &expr) | ||
|  | { | ||
|  |     return kernel << expr.m_element_iter[expr.m_index_iter[expr.m_expr]]; | ||
|  | } | ||
|  | 
 | ||
|  | } // end detail namespace | ||
|  | 
 | ||
|  | /// \class permutation_iterator | ||
|  | /// \brief The permutation_iterator class provides a permuation iterator | ||
|  | /// | ||
|  | /// A permutation iterator iterates over a value range and an index range. When | ||
|  | /// dereferenced, it returns the value from the value range using the current | ||
|  | /// index from the index range. | ||
|  | /// | ||
|  | /// For example, to reverse a range using the copy() algorithm and a permutation | ||
|  | /// sequence: | ||
|  | /// | ||
|  | /// \snippet test/test_permutation_iterator.cpp reverse_range | ||
|  | /// | ||
|  | /// \see make_permutation_iterator() | ||
|  | template<class ElementIterator, class IndexIterator> | ||
|  | class permutation_iterator | ||
|  |     : public detail::permutation_iterator_base<ElementIterator, | ||
|  |                                                IndexIterator>::type | ||
|  | { | ||
|  | public: | ||
|  |     typedef typename | ||
|  |         detail::permutation_iterator_base<ElementIterator, | ||
|  |                                           IndexIterator>::type super_type; | ||
|  |     typedef typename super_type::value_type value_type; | ||
|  |     typedef typename super_type::reference reference; | ||
|  |     typedef typename super_type::base_type base_type; | ||
|  |     typedef typename super_type::difference_type difference_type; | ||
|  |     typedef IndexIterator index_iterator; | ||
|  | 
 | ||
|  |     permutation_iterator(ElementIterator e, IndexIterator i) | ||
|  |         : super_type(e), | ||
|  |           m_map(i) | ||
|  |     { | ||
|  |     } | ||
|  | 
 | ||
|  |     permutation_iterator(const permutation_iterator<ElementIterator, | ||
|  |                                                     IndexIterator> &other) | ||
|  |         : super_type(other), | ||
|  |           m_map(other.m_map) | ||
|  |     { | ||
|  |     } | ||
|  | 
 | ||
|  |     permutation_iterator<ElementIterator, IndexIterator>& | ||
|  |     operator=(const permutation_iterator<ElementIterator, | ||
|  |                                          IndexIterator> &other) | ||
|  |     { | ||
|  |         if(this != &other){ | ||
|  |             super_type::operator=(other); | ||
|  |             m_map = other.m_map; | ||
|  |         } | ||
|  | 
 | ||
|  |         return *this; | ||
|  |     } | ||
|  | 
 | ||
|  |     ~permutation_iterator() | ||
|  |     { | ||
|  |     } | ||
|  | 
 | ||
|  |     size_t get_index() const | ||
|  |     { | ||
|  |         return super_type::base().get_index(); | ||
|  |     } | ||
|  | 
 | ||
|  |     const buffer& get_buffer() const | ||
|  |     { | ||
|  |         return detail::get_base_iterator_buffer(*this); | ||
|  |     } | ||
|  | 
 | ||
|  |     template<class IndexExpr> | ||
|  |     detail::permutation_iterator_access_expr<ElementIterator, | ||
|  |                                              IndexIterator, | ||
|  |                                              IndexExpr> | ||
|  |     operator[](const IndexExpr &expr) const | ||
|  |     { | ||
|  |         return detail::permutation_iterator_access_expr<ElementIterator, | ||
|  |                                                         IndexIterator, | ||
|  |                                                         IndexExpr>(super_type::base(), | ||
|  |                                                                    m_map, | ||
|  |                                                                    expr); | ||
|  |     } | ||
|  | 
 | ||
|  | private: | ||
|  |     friend class ::boost::iterator_core_access; | ||
|  | 
 | ||
|  |     reference dereference() const | ||
|  |     { | ||
|  |         return reference(); | ||
|  |     } | ||
|  | 
 | ||
|  | private: | ||
|  |     IndexIterator m_map; | ||
|  | }; | ||
|  | 
 | ||
|  | /// Returns a permutation_iterator for \p e using indices from \p i. | ||
|  | /// | ||
|  | /// \param e the element range iterator | ||
|  | /// \param i the index range iterator | ||
|  | /// | ||
|  | /// \return a \c permutation_iterator for \p e using \p i | ||
|  | template<class ElementIterator, class IndexIterator> | ||
|  | inline permutation_iterator<ElementIterator, IndexIterator> | ||
|  | make_permutation_iterator(ElementIterator e, IndexIterator i) | ||
|  | { | ||
|  |     return permutation_iterator<ElementIterator, IndexIterator>(e, i); | ||
|  | } | ||
|  | 
 | ||
|  | /// \internal_ (is_device_iterator specialization for permutation_iterator) | ||
|  | template<class ElementIterator, class IndexIterator> | ||
|  | struct is_device_iterator< | ||
|  |     permutation_iterator<ElementIterator, IndexIterator> > : boost::true_type {}; | ||
|  | 
 | ||
|  | } // end compute namespace | ||
|  | } // end boost namespace | ||
|  | 
 | ||
|  | #endif // BOOST_COMPUTE_ITERATOR_PERMUTATION_ITERATOR_HPP |