Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:36

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@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_ZIP_ITERATOR_HPP
0012 #define BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP
0013 
0014 #include <cstddef>
0015 #include <iterator>
0016 
0017 #include <boost/config.hpp>
0018 #include <boost/fusion/algorithm/iteration/for_each.hpp>
0019 #include <boost/iterator/iterator_facade.hpp>
0020 #include <boost/mpl/back_inserter.hpp>
0021 #include <boost/mpl/transform.hpp>
0022 #include <boost/mpl/vector.hpp>
0023 #include <boost/preprocessor/repetition.hpp>
0024 #include <boost/tuple/tuple.hpp>
0025 #include <boost/tuple/tuple_comparison.hpp>
0026 
0027 #include <boost/compute/config.hpp>
0028 #include <boost/compute/functional.hpp>
0029 #include <boost/compute/detail/meta_kernel.hpp>
0030 #include <boost/compute/detail/mpl_vector_to_tuple.hpp>
0031 #include <boost/compute/types/tuple.hpp>
0032 #include <boost/compute/type_traits/is_device_iterator.hpp>
0033 #include <boost/compute/type_traits/type_name.hpp>
0034 
0035 namespace boost {
0036 namespace compute {
0037 
0038 // forward declaration for zip_iterator
0039 template<class IteratorTuple>
0040 class zip_iterator;
0041 
0042 namespace detail {
0043 
0044 namespace mpl = boost::mpl;
0045 
0046 // meta-function returning the value_type for an iterator
0047 template<class Iterator>
0048 struct make_iterator_value_type
0049 {
0050     typedef typename std::iterator_traits<Iterator>::value_type type;
0051 };
0052 
0053 // meta-function returning the value_type for a zip_iterator
0054 template<class IteratorTuple>
0055 struct make_zip_iterator_value_type
0056 {
0057     typedef typename
0058         detail::mpl_vector_to_tuple<
0059             typename mpl::transform<
0060                 IteratorTuple,
0061                 make_iterator_value_type<mpl::_1>,
0062                 mpl::back_inserter<mpl::vector<> >
0063             >::type
0064         >::type type;
0065 };
0066 
0067 // helper class which defines the iterator_facade super-class
0068 // type for zip_iterator
0069 template<class IteratorTuple>
0070 class zip_iterator_base
0071 {
0072 public:
0073     typedef ::boost::iterator_facade<
0074         ::boost::compute::zip_iterator<IteratorTuple>,
0075         typename make_zip_iterator_value_type<IteratorTuple>::type,
0076         ::std::random_access_iterator_tag,
0077         typename make_zip_iterator_value_type<IteratorTuple>::type
0078     > type;
0079 };
0080 
0081 template<class IteratorTuple, class IndexExpr>
0082 struct zip_iterator_index_expr
0083 {
0084     typedef typename
0085         make_zip_iterator_value_type<IteratorTuple>::type
0086         result_type;
0087 
0088     zip_iterator_index_expr(const IteratorTuple &iterators,
0089                             const IndexExpr &index_expr)
0090         : m_iterators(iterators),
0091           m_index_expr(index_expr)
0092     {
0093     }
0094 
0095     const IteratorTuple m_iterators;
0096     const IndexExpr m_index_expr;
0097 };
0098 
0099 /// \internal_
0100 #define BOOST_COMPUTE_PRINT_ELEM(z, n, unused)                                 \
0101         BOOST_PP_EXPR_IF(n, << ", ")                                           \
0102         << boost::get<n>(expr.m_iterators)[expr.m_index_expr]
0103 
0104 /// \internal_
0105 #define BOOST_COMPUTE_PRINT_ZIP_IDX(z, n, unused)                              \
0106 template<BOOST_PP_ENUM_PARAMS(n, class Iterator), class IndexExpr>             \
0107 inline meta_kernel& operator<<(                                                \
0108         meta_kernel &kernel,                                                   \
0109         const zip_iterator_index_expr<                                         \
0110                   boost::tuple<BOOST_PP_ENUM_PARAMS(n, Iterator)>,             \
0111                   IndexExpr                                                    \
0112               > &expr)                                                         \
0113 {                                                                              \
0114     typedef typename                                                           \
0115         boost::tuple<BOOST_PP_ENUM_PARAMS(n, Iterator)>                        \
0116         tuple_type;                                                            \
0117     typedef typename                                                           \
0118         make_zip_iterator_value_type<tuple_type>::type                         \
0119         value_type;                                                            \
0120     kernel.inject_type<value_type>();                                          \
0121     return kernel                                                              \
0122         << "(" << type_name<value_type>() << ")"                               \
0123         << "{ "                                                                \
0124         BOOST_PP_REPEAT(n, BOOST_COMPUTE_PRINT_ELEM, ~)                        \
0125         << "}";                                                                \
0126 }
0127 
0128 BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_PRINT_ZIP_IDX, ~)
0129 
0130 #undef BOOST_COMPUTE_PRINT_ZIP_IDX
0131 #undef BOOST_COMPUTE_PRINT_ELEM
0132 
0133 struct iterator_advancer
0134 {
0135     iterator_advancer(size_t n)
0136         : m_distance(n)
0137     {
0138     }
0139 
0140     template<class Iterator>
0141     void operator()(Iterator &i) const
0142     {
0143         std::advance(i, m_distance);
0144     }
0145 
0146     size_t m_distance;
0147 };
0148 
0149 template<class Iterator>
0150 void increment_iterator(Iterator &i)
0151 {
0152     i++;
0153 }
0154 
0155 template<class Iterator>
0156 void decrement_iterator(Iterator &i)
0157 {
0158     i--;
0159 }
0160 
0161 } // end detail namespace
0162 
0163 /// \class zip_iterator
0164 /// \brief A zip iterator adaptor.
0165 ///
0166 /// The zip_iterator class combines values from multiple input iterators. When
0167 /// dereferenced it returns a tuple containing each value at the current
0168 /// position in each input range.
0169 ///
0170 /// \see make_zip_iterator()
0171 template<class IteratorTuple>
0172 class zip_iterator : public detail::zip_iterator_base<IteratorTuple>::type
0173 {
0174 public:
0175     typedef typename
0176         detail::zip_iterator_base<IteratorTuple>::type
0177         super_type;
0178     typedef typename super_type::value_type value_type;
0179     typedef typename super_type::reference reference;
0180     typedef typename super_type::difference_type difference_type;
0181     typedef IteratorTuple iterator_tuple;
0182 
0183     zip_iterator(IteratorTuple iterators)
0184         : m_iterators(iterators)
0185     {
0186     }
0187 
0188     zip_iterator(const zip_iterator<IteratorTuple> &other)
0189         : m_iterators(other.m_iterators)
0190     {
0191     }
0192 
0193     zip_iterator<IteratorTuple>&
0194     operator=(const zip_iterator<IteratorTuple> &other)
0195     {
0196         if(this != &other){
0197             super_type::operator=(other);
0198 
0199             m_iterators = other.m_iterators;
0200         }
0201 
0202         return *this;
0203     }
0204 
0205     ~zip_iterator()
0206     {
0207     }
0208 
0209     const IteratorTuple& get_iterator_tuple() const
0210     {
0211         return m_iterators;
0212     }
0213 
0214     template<class IndexExpression>
0215     detail::zip_iterator_index_expr<IteratorTuple, IndexExpression>
0216     operator[](const IndexExpression &expr) const
0217     {
0218         return detail::zip_iterator_index_expr<IteratorTuple,
0219                                                IndexExpression>(m_iterators,
0220                                                                 expr);
0221     }
0222 
0223 private:
0224     friend class ::boost::iterator_core_access;
0225 
0226     reference dereference() const
0227     {
0228         return reference();
0229     }
0230 
0231     bool equal(const zip_iterator<IteratorTuple> &other) const
0232     {
0233         return m_iterators == other.m_iterators;
0234     }
0235 
0236     void increment()
0237     {
0238         boost::fusion::for_each(m_iterators, detail::increment_iterator);
0239     }
0240 
0241     void decrement()
0242     {
0243         boost::fusion::for_each(m_iterators, detail::decrement_iterator);
0244     }
0245 
0246     void advance(difference_type n)
0247     {
0248         boost::fusion::for_each(m_iterators, detail::iterator_advancer(n));
0249     }
0250 
0251     difference_type distance_to(const zip_iterator<IteratorTuple> &other) const
0252     {
0253         return std::distance(boost::get<0>(m_iterators),
0254                              boost::get<0>(other.m_iterators));
0255     }
0256 
0257 private:
0258     IteratorTuple m_iterators;
0259 };
0260 
0261 /// Creates a zip_iterator for \p iterators.
0262 ///
0263 /// \param iterators a tuple of input iterators to zip together
0264 ///
0265 /// \return a \c zip_iterator for \p iterators
0266 ///
0267 /// For example, to zip together iterators from three vectors (\c a, \c b, and
0268 /// \p c):
0269 /// \code
0270 /// auto zipped = boost::compute::make_zip_iterator(
0271 ///     boost::make_tuple(a.begin(), b.begin(), c.begin())
0272 /// );
0273 /// \endcode
0274 template<class IteratorTuple>
0275 inline zip_iterator<IteratorTuple>
0276 make_zip_iterator(IteratorTuple iterators)
0277 {
0278     return zip_iterator<IteratorTuple>(iterators);
0279 }
0280 
0281 /// \internal_ (is_device_iterator specialization for zip_iterator)
0282 template<class IteratorTuple>
0283 struct is_device_iterator<zip_iterator<IteratorTuple> > : boost::true_type {};
0284 
0285 namespace detail {
0286 
0287 // get<N>() specialization for zip_iterator
0288 /// \internal_
0289 #define BOOST_COMPUTE_ZIP_GET_N(z, n, unused)                                  \
0290 template<size_t N, class IteratorTuple, class IndexExpr,                       \
0291     BOOST_PP_ENUM_PARAMS(n, class T)>                                          \
0292 inline meta_kernel&                                                            \
0293 operator<<(meta_kernel &kernel,                                                \
0294            const invoked_get<                                                  \
0295                N,                                                              \
0296                zip_iterator_index_expr<IteratorTuple, IndexExpr>,              \
0297                boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)>                        \
0298             > &expr)                                                           \
0299 {                                                                              \
0300     typedef typename boost::tuple<BOOST_PP_ENUM_PARAMS(n, T)> Tuple;           \
0301     typedef typename boost::tuples::element<N, Tuple>::type T;                 \
0302     BOOST_STATIC_ASSERT(N < size_t(boost::tuples::length<Tuple>::value));      \
0303     kernel.inject_type<T>();                                                   \
0304     return kernel                                                              \
0305         << boost::get<N>(expr.m_arg.m_iterators)[expr.m_arg.m_index_expr];     \
0306 }
0307 
0308 BOOST_PP_REPEAT_FROM_TO(1, BOOST_COMPUTE_MAX_ARITY, BOOST_COMPUTE_ZIP_GET_N, ~)
0309 
0310 #undef BOOST_COMPUTE_ZIP_GET_N
0311 
0312 } // end detail namespace
0313 } // end compute namespace
0314 } // end boost namespace
0315 
0316 #endif // BOOST_COMPUTE_ITERATOR_ZIP_ITERATOR_HPP