File indexing completed on 2025-01-18 09:30:02
0001
0002
0003
0004
0005
0006
0007
0008
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
0032 template<class Iterator>
0033 class strided_iterator;
0034
0035 namespace detail {
0036
0037
0038
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
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
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 }
0110
0111
0112
0113
0114
0115
0116
0117
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
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
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
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
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
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
0279
0280 difference_type range = std::distance(first, last);
0281 difference_type d = (range - 1) / stride;
0282 d *= stride;
0283 d -= range;
0284
0285
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
0292 template<class Iterator>
0293 struct is_device_iterator<strided_iterator<Iterator> > : boost::true_type {};
0294
0295 }
0296 }
0297
0298 #endif