Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:02

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2015 Jakub Szuppe <j.szuppe@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
0009 //---------------------------------------------------------------------------//
0010 
0011 #ifndef BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP
0012 #define BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP
0013 
0014 #include <cstddef>
0015 #include <iterator>
0016 
0017 #include <boost/config.hpp>
0018 #include <boost/iterator/iterator_adaptor.hpp>
0019 
0020 #include <boost/compute/functional.hpp>
0021 #include <boost/compute/detail/meta_kernel.hpp>
0022 #include <boost/compute/detail/is_buffer_iterator.hpp>
0023 #include <boost/compute/detail/read_write_single_value.hpp>
0024 #include <boost/compute/iterator/detail/get_base_iterator_buffer.hpp>
0025 #include <boost/compute/type_traits/is_device_iterator.hpp>
0026 #include <boost/compute/type_traits/result_of.hpp>
0027 
0028 namespace boost {
0029 namespace compute {
0030 
0031 // forward declaration for strided_iterator
0032 template<class Iterator>
0033 class strided_iterator;
0034 
0035 namespace detail {
0036 
0037 // helper class which defines the iterator_adaptor super-class
0038 // type for strided_iterator
0039 template<class Iterator>
0040 class strided_iterator_base
0041 {
0042 public:
0043     typedef ::boost::iterator_adaptor<
0044         ::boost::compute::strided_iterator<Iterator>,
0045         Iterator,
0046         typename std::iterator_traits<Iterator>::value_type,
0047         typename std::iterator_traits<Iterator>::iterator_category
0048     > type;
0049 };
0050 
0051 // helper class for including stride value in index expression
0052 template<class IndexExpr, class Stride>
0053 struct stride_expr
0054 {
0055     stride_expr(const IndexExpr &expr, const Stride &stride)
0056         : m_index_expr(expr),
0057           m_stride(stride)
0058     {
0059     }
0060 
0061     const IndexExpr m_index_expr;
0062     const Stride m_stride;
0063 };
0064 
0065 template<class IndexExpr, class Stride>
0066 inline stride_expr<IndexExpr, Stride> make_stride_expr(const IndexExpr &expr,
0067                                                        const Stride &stride)
0068 {
0069     return stride_expr<IndexExpr, Stride>(expr, stride);
0070 }
0071 
0072 template<class IndexExpr, class Stride>
0073 inline meta_kernel& operator<<(meta_kernel &kernel,
0074                                const stride_expr<IndexExpr, Stride> &expr)
0075 {
0076     // (expr.m_stride * (expr.m_index_expr))
0077     return kernel << "(" << static_cast<ulong_>(expr.m_stride)
0078                   << " * (" << expr.m_index_expr << "))";
0079 }
0080 
0081 template<class Iterator, class Stride, class IndexExpr>
0082 struct strided_iterator_index_expr
0083 {
0084     typedef typename std::iterator_traits<Iterator>::value_type result_type;
0085 
0086     strided_iterator_index_expr(const Iterator &input_iter,
0087                                 const Stride &stride,
0088                                 const IndexExpr &index_expr)
0089         : m_input_iter(input_iter),
0090           m_stride(stride),
0091           m_index_expr(index_expr)
0092     {
0093     }
0094 
0095     const Iterator m_input_iter;
0096     const Stride m_stride;
0097     const IndexExpr m_index_expr;
0098 };
0099 
0100 template<class Iterator, class Stride, class IndexExpr>
0101 inline meta_kernel& operator<<(meta_kernel &kernel,
0102                                const strided_iterator_index_expr<Iterator,
0103                                                                  Stride,
0104                                                                  IndexExpr> &expr)
0105 {
0106     return kernel << expr.m_input_iter[make_stride_expr(expr.m_index_expr, expr.m_stride)];
0107 }
0108 
0109 } // end detail namespace
0110 
0111 /// \class strided_iterator
0112 /// \brief An iterator adaptor with adjustable iteration step.
0113 ///
0114 /// The strided iterator adaptor skips over multiple elements each time
0115 /// it is incremented or decremented.
0116 ///
0117 /// \see buffer_iterator, make_strided_iterator(), make_strided_iterator_end()
0118 template<class Iterator>
0119 class strided_iterator :
0120     public detail::strided_iterator_base<Iterator>::type
0121 {
0122 public:
0123     typedef typename
0124         detail::strided_iterator_base<Iterator>::type super_type;
0125     typedef typename super_type::value_type value_type;
0126     typedef typename super_type::reference reference;
0127     typedef typename super_type::base_type base_type;
0128     typedef typename super_type::difference_type difference_type;
0129 
0130     strided_iterator(Iterator iterator, difference_type stride)
0131         : super_type(iterator),
0132           m_stride(static_cast<difference_type>(stride))
0133     {
0134         // stride must be greater than zero
0135         BOOST_ASSERT_MSG(stride > 0, "Stride must be greater than zero");
0136     }
0137 
0138     strided_iterator(const strided_iterator<Iterator> &other)
0139         : super_type(other.base()),
0140           m_stride(other.m_stride)
0141     {
0142     }
0143 
0144     strided_iterator<Iterator>&
0145     operator=(const strided_iterator<Iterator> &other)
0146     {
0147         if(this != &other){
0148             super_type::operator=(other);
0149 
0150             m_stride = other.m_stride;
0151         }
0152 
0153         return *this;
0154     }
0155 
0156     ~strided_iterator()
0157     {
0158     }
0159 
0160     size_t get_index() const
0161     {
0162         return super_type::base().get_index();
0163     }
0164 
0165     const buffer& get_buffer() const
0166     {
0167         return detail::get_base_iterator_buffer(*this);
0168     }
0169 
0170     template<class IndexExpression>
0171     detail::strided_iterator_index_expr<Iterator, difference_type, IndexExpression>
0172     operator[](const IndexExpression &expr) const
0173     {
0174         typedef
0175             typename detail::strided_iterator_index_expr<Iterator,
0176                                                          difference_type,
0177                                                          IndexExpression>
0178             StridedIndexExprType;
0179         return StridedIndexExprType(super_type::base(),m_stride, expr);
0180     }
0181 
0182 private:
0183     friend class ::boost::iterator_core_access;
0184 
0185     reference dereference() const
0186     {
0187         return reference();
0188     }
0189 
0190     bool equal(const strided_iterator<Iterator> &other) const
0191     {
0192         return (other.m_stride == m_stride)
0193                    && (other.base_reference() == this->base_reference());
0194     }
0195 
0196     void increment()
0197     {
0198         std::advance(super_type::base_reference(), m_stride);
0199     }
0200 
0201     void decrement()
0202     {
0203         std::advance(super_type::base_reference(),-m_stride);
0204     }
0205 
0206     void advance(typename super_type::difference_type n)
0207     {
0208         std::advance(super_type::base_reference(), n * m_stride);
0209     }
0210 
0211     difference_type distance_to(const strided_iterator<Iterator> &other) const
0212     {
0213         return std::distance(this->base_reference(), other.base_reference()) / m_stride;
0214     }
0215 
0216 private:
0217     difference_type m_stride;
0218 };
0219 
0220 /// Returns a strided_iterator for \p iterator with \p stride.
0221 ///
0222 /// \param iterator the underlying iterator
0223 /// \param stride the iteration step for strided_iterator
0224 ///
0225 /// \return a \c strided_iterator for \p iterator with \p stride.
0226 ///
0227 /// For example, to create an iterator which iterates over every other
0228 /// element in a \c vector<int>:
0229 /// \code
0230 /// auto strided_iterator = make_strided_iterator(vec.begin(), 2);
0231 /// \endcode
0232 template<class Iterator>
0233 inline strided_iterator<Iterator>
0234 make_strided_iterator(Iterator iterator,
0235                       typename std::iterator_traits<Iterator>::difference_type stride)
0236 {
0237     return strided_iterator<Iterator>(iterator, stride);
0238 }
0239 
0240 /// Returns a strided_iterator which refers to element that would follow
0241 /// the last element accessible through strided_iterator for \p first iterator
0242 /// with \p stride.
0243 ///
0244 /// Parameter \p stride must be greater than zero.
0245 ///
0246 /// \param first the iterator referring to the first element accessible
0247 ///        through strided_iterator for \p first with \p stride
0248 /// \param last the iterator referring to the last element that may be
0249 ////       accessible through strided_iterator for \p first with \p stride
0250 /// \param stride the iteration step
0251 ///
0252 /// \return a \c strided_iterator referring to element that would follow
0253 ///         the last element accessible through strided_iterator for \p first
0254 ///         iterator with \p stride.
0255 ///
0256 /// It can be helpful when iterating over strided_iterator:
0257 /// \code
0258 /// // vec.size() may not be divisible by 3
0259 /// auto strided_iterator_begin = make_strided_iterator(vec.begin(), 3);
0260 /// auto strided_iterator_end = make_strided_iterator_end(vec.begin(), vec.end(), 3);
0261 ///
0262 /// // copy every 3rd element to result
0263 /// boost::compute::copy(
0264 ///         strided_iterator_begin,
0265 ///         strided_iterator_end,
0266 ///         result.begin(),
0267 ///         queue
0268 /// );
0269 /// \endcode
0270 template<class Iterator>
0271 strided_iterator<Iterator>
0272 make_strided_iterator_end(Iterator first,
0273                           Iterator last,
0274                           typename std::iterator_traits<Iterator>::difference_type stride)
0275 {
0276     typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
0277 
0278     // calculate distance from end to the last element that would be
0279     // accessible through strided_iterator.
0280     difference_type range = std::distance(first, last);
0281     difference_type d = (range - 1) / stride;
0282     d *= stride;
0283     d -= range;
0284     // advance from end to the element that would follow the last
0285     // accessible element
0286     Iterator end_for_strided_iterator = last;
0287     std::advance(end_for_strided_iterator, d + stride);
0288     return strided_iterator<Iterator>(end_for_strided_iterator, stride);
0289 }
0290 
0291 /// \internal_ (is_device_iterator specialization for strided_iterator)
0292 template<class Iterator>
0293 struct is_device_iterator<strided_iterator<Iterator> > : boost::true_type {};
0294 
0295 } // end compute namespace
0296 } // end boost namespace
0297 
0298 #endif // BOOST_COMPUTE_ITERATOR_STRIDED_ITERATOR_HPP