2 * Copyright 2008-2013 NVIDIA Corporation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <thrust/iterator/iterator_traits.h>
20 #include <thrust/iterator/iterator_facade.h>
21 #include <thrust/iterator/iterator_categories.h>
22 #include <thrust/iterator/detail/minimum_category.h>
23 #include <thrust/iterator/detail/minimum_system.h>
24 #include <thrust/tuple.h>
25 #include <thrust/detail/tuple_meta_transform.h>
26 #include <thrust/detail/tuple_transform.h>
27 #include <thrust/detail/type_traits.h>
28 #include <thrust/iterator/detail/tuple_of_iterator_references.h>
33 // forward declare zip_iterator for zip_iterator_base
34 template<typename IteratorTuple> class zip_iterator;
40 // Functors to be used with tuple algorithms
42 template<typename DiffType>
43 class advance_iterator
46 inline __host__ __device__
47 advance_iterator(DiffType step) : m_step(step) {}
49 template<typename Iterator>
50 inline __host__ __device__
51 void operator()(Iterator& it) const
56 }; // end advance_iterator
59 struct increment_iterator
61 template<typename Iterator>
62 inline __host__ __device__
63 void operator()(Iterator& it)
65 }; // end increment_iterator
68 struct decrement_iterator
70 template<typename Iterator>
71 inline __host__ __device__
72 void operator()(Iterator& it)
74 }; // end decrement_iterator
77 struct dereference_iterator
79 template<typename Iterator>
83 iterator_traits<Iterator>::reference
87 // XXX silence warnings of the form "calling a __host__ function from a __host__ __device__ function is not allowed
88 __thrust_hd_warning_disable__
89 template<typename Iterator>
91 typename apply<Iterator>::type operator()(Iterator const& it)
95 }; // end dereference_iterator
98 // The namespace tuple_impl_specific provides two meta-
99 // algorithms and two algorithms for tuples.
100 namespace tuple_impl_specific
103 // define apply1 for tuple_meta_transform_impl
104 template<typename UnaryMetaFunctionClass, class Arg>
106 : UnaryMetaFunctionClass::template apply<Arg>
111 // define apply2 for tuple_meta_accumulate_impl
112 template<typename UnaryMetaFunctionClass, class Arg1, class Arg2>
114 : UnaryMetaFunctionClass::template apply<Arg1,Arg2>
119 // Meta-accumulate algorithm for tuples. Note: The template
120 // parameter StartType corresponds to the initial value in
121 // ordinary accumulation.
123 template<class Tuple, class BinaryMetaFun, class StartType>
124 struct tuple_meta_accumulate;
128 , class BinaryMetaFun
131 struct tuple_meta_accumulate_impl
133 typedef typename apply2<
135 , typename Tuple::head_type
136 , typename tuple_meta_accumulate<
137 typename Tuple::tail_type
147 , class BinaryMetaFun
150 struct tuple_meta_accumulate
151 : thrust::detail::eval_if<
152 thrust::detail::is_same<Tuple, thrust::null_type>::value
153 , thrust::detail::identity_<StartType>
154 , tuple_meta_accumulate_impl<
161 }; // end tuple_meta_accumulate
164 // transform algorithm for tuples. The template parameter Fun
165 // must be a unary functor which is also a unary metafunction
166 // class that computes its return type based on its argument
167 // type. For example:
171 // template <class Arg>
174 // typedef Arg* type;
177 // template <class Arg>
178 // Arg* operator()(Arg x);
183 // for_each algorithm for tuples.
185 template<typename Fun, typename System>
186 inline __host__ __device__
187 Fun tuple_for_each(thrust::null_type, Fun f, System *)
190 } // end tuple_for_each()
193 template<typename Tuple, typename Fun, typename System>
194 inline __host__ __device__
195 Fun tuple_for_each(Tuple& t, Fun f, System *dispatch_tag)
198 return tuple_for_each(t.get_tail(), f, dispatch_tag);
199 } // end tuple_for_each()
202 template<typename Tuple, typename Fun>
203 inline __host__ __device__
204 Fun tuple_for_each(Tuple& t, Fun f, thrust::host_system_tag *dispatch_tag)
206 // XXX this path is required in order to accomodate pure host iterators
207 // (such as std::vector::iterator) in a zip_iterator
208 #ifndef __CUDA_ARCH__
210 return tuple_for_each(t.get_tail(), f, dispatch_tag);
212 // this code will never be called
215 } // end tuple_for_each()
218 // Equality of tuples. NOTE: "==" for tuples currently (7/2003)
219 // has problems under some compilers, so I just do my own.
220 // No point in bringing in a bunch of #ifdefs here. This is
221 // going to go away with the next tuple implementation anyway.
224 inline bool tuple_equal(thrust::null_type, thrust::null_type)
228 template<typename Tuple1, typename Tuple2>
230 bool tuple_equal(Tuple1 const& t1, Tuple2 const& t2)
232 return t1.get_head() == t2.get_head() &&
233 tuple_equal(t1.get_tail(), t2.get_tail());
234 } // end tuple_equal()
236 } // end end tuple_impl_specific
239 // Metafunction to obtain the type of the tuple whose element types
240 // are the value_types of an iterator tupel.
242 template<typename IteratorTuple>
243 struct tuple_of_value_types
244 : tuple_meta_transform<
249 }; // end tuple_of_value_types
252 struct minimum_category_lambda
254 template<typename T1, typename T2>
255 struct apply : minimum_category<T1,T2>
261 // Metafunction to obtain the minimal traversal tag in a tuple
264 template<typename IteratorTuple>
265 struct minimum_traversal_category_in_iterator_tuple
267 typedef typename tuple_meta_transform<
269 , thrust::iterator_traversal
270 >::type tuple_of_traversal_tags;
272 typedef typename tuple_impl_specific::tuple_meta_accumulate<
273 tuple_of_traversal_tags
274 , minimum_category_lambda
275 , thrust::random_access_traversal_tag
280 struct minimum_system_lambda
282 template<typename T1, typename T2>
283 struct apply : minimum_system<T1,T2>
289 // Metafunction to obtain the minimal system tag in a tuple
291 template<typename IteratorTuple>
292 struct minimum_system_in_iterator_tuple
294 typedef typename thrust::detail::tuple_meta_transform<
296 thrust::iterator_system
297 >::type tuple_of_system_tags;
299 typedef typename tuple_impl_specific::tuple_meta_accumulate<
300 tuple_of_system_tags,
301 minimum_system_lambda,
302 thrust::any_system_tag
306 namespace zip_iterator_base_ns
310 template<int i, typename Tuple>
311 struct tuple_elements_helper
313 (i < tuple_size<Tuple>::value),
314 tuple_element<i,Tuple>,
315 identity_<thrust::null_type>
320 template<typename Tuple>
321 struct tuple_elements
323 typedef typename tuple_elements_helper<0,Tuple>::type T0;
324 typedef typename tuple_elements_helper<1,Tuple>::type T1;
325 typedef typename tuple_elements_helper<2,Tuple>::type T2;
326 typedef typename tuple_elements_helper<3,Tuple>::type T3;
327 typedef typename tuple_elements_helper<4,Tuple>::type T4;
328 typedef typename tuple_elements_helper<5,Tuple>::type T5;
329 typedef typename tuple_elements_helper<6,Tuple>::type T6;
330 typedef typename tuple_elements_helper<7,Tuple>::type T7;
331 typedef typename tuple_elements_helper<8,Tuple>::type T8;
332 typedef typename tuple_elements_helper<9,Tuple>::type T9;
336 template<typename IteratorTuple>
337 struct tuple_of_iterator_references
339 // get a thrust::tuple of the iterators' references
340 typedef typename tuple_meta_transform<
343 >::type tuple_of_references;
345 // get at the individual tuple element types by name
346 typedef tuple_elements<tuple_of_references> elements;
348 // map thrust::tuple<T...> to tuple_of_iterator_references<T...>
349 typedef thrust::detail::tuple_of_iterator_references<
350 typename elements::T0,
351 typename elements::T1,
352 typename elements::T2,
353 typename elements::T3,
354 typename elements::T4,
355 typename elements::T5,
356 typename elements::T6,
357 typename elements::T7,
358 typename elements::T8,
359 typename elements::T9
364 } // end zip_iterator_base_ns
366 ///////////////////////////////////////////////////////////////////
368 // Class zip_iterator_base
370 // Builds and exposes the iterator facade type from which the zip
371 // iterator will be derived.
373 template<typename IteratorTuple>
374 struct zip_iterator_base
377 // reference type is the type of the tuple obtained from the
378 // iterators' reference types.
379 typedef typename zip_iterator_base_ns::tuple_of_iterator_references<IteratorTuple>::type reference;
381 // Boost's Value type is the same as reference type.
382 //typedef reference value_type;
383 typedef typename tuple_of_value_types<IteratorTuple>::type value_type;
385 // Difference type is the first iterator's difference type
386 typedef typename thrust::iterator_traits<
387 typename thrust::tuple_element<0, IteratorTuple>::type
388 >::difference_type difference_type;
390 // Iterator system is the minimum system tag in the
393 minimum_system_in_iterator_tuple<IteratorTuple>::type system;
395 // Traversal category is the minimum traversal category in the
398 minimum_traversal_category_in_iterator_tuple<IteratorTuple>::type traversal_category;
402 // The iterator facade type from which the zip iterator will
404 typedef thrust::iterator_facade<
405 zip_iterator<IteratorTuple>,
412 }; // end zip_iterator_base