You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
419 lines
10 KiB
419 lines
10 KiB
![]()
11 years ago
|
/*
|
||
|
* Copyright 2008-2012 NVIDIA Corporation
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <thrust/iterator/iterator_traits.h>
|
||
|
#include <thrust/iterator/iterator_facade.h>
|
||
|
#include <thrust/iterator/iterator_categories.h>
|
||
|
#include <thrust/iterator/detail/minimum_category.h>
|
||
|
#include <thrust/iterator/detail/minimum_system.h>
|
||
|
#include <thrust/tuple.h>
|
||
|
#include <thrust/detail/tuple_meta_transform.h>
|
||
|
#include <thrust/detail/tuple_transform.h>
|
||
|
#include <thrust/detail/type_traits.h>
|
||
|
#include <thrust/iterator/detail/tuple_of_iterator_references.h>
|
||
|
|
||
|
namespace thrust
|
||
|
{
|
||
|
|
||
|
// forward declare zip_iterator for zip_iterator_base
|
||
|
template<typename IteratorTuple> class zip_iterator;
|
||
|
|
||
|
namespace detail
|
||
|
{
|
||
|
|
||
|
|
||
|
// Functors to be used with tuple algorithms
|
||
|
//
|
||
|
template<typename DiffType>
|
||
|
class advance_iterator
|
||
|
{
|
||
|
public:
|
||
|
inline __host__ __device__
|
||
|
advance_iterator(DiffType step) : m_step(step) {}
|
||
|
|
||
|
template<typename Iterator>
|
||
|
inline __host__ __device__
|
||
|
void operator()(Iterator& it) const
|
||
|
{ it += m_step; }
|
||
|
|
||
|
private:
|
||
|
DiffType m_step;
|
||
|
}; // end advance_iterator
|
||
|
|
||
|
|
||
|
struct increment_iterator
|
||
|
{
|
||
|
template<typename Iterator>
|
||
|
inline __host__ __device__
|
||
|
void operator()(Iterator& it)
|
||
|
{ ++it; }
|
||
|
}; // end increment_iterator
|
||
|
|
||
|
|
||
|
struct decrement_iterator
|
||
|
{
|
||
|
template<typename Iterator>
|
||
|
inline __host__ __device__
|
||
|
void operator()(Iterator& it)
|
||
|
{ --it; }
|
||
|
}; // end decrement_iterator
|
||
|
|
||
|
|
||
|
struct dereference_iterator
|
||
|
{
|
||
|
template<typename Iterator>
|
||
|
struct apply
|
||
|
{
|
||
|
typedef typename
|
||
|
iterator_traits<Iterator>::reference
|
||
|
type;
|
||
|
}; // end apply
|
||
|
|
||
|
// XXX silence warnings of the form "calling a __host__ function from a __host__ __device__ function is not allowed
|
||
|
__thrust_hd_warning_disable__
|
||
|
template<typename Iterator>
|
||
|
__host__ __device__
|
||
|
typename apply<Iterator>::type operator()(Iterator const& it)
|
||
|
{
|
||
|
return *it;
|
||
|
}
|
||
|
}; // end dereference_iterator
|
||
|
|
||
|
|
||
|
// The namespace tuple_impl_specific provides two meta-
|
||
|
// algorithms and two algorithms for tuples.
|
||
|
namespace tuple_impl_specific
|
||
|
{
|
||
|
|
||
|
// define apply1 for tuple_meta_transform_impl
|
||
|
template<typename UnaryMetaFunctionClass, class Arg>
|
||
|
struct apply1
|
||
|
: UnaryMetaFunctionClass::template apply<Arg>
|
||
|
{
|
||
|
}; // end apply1
|
||
|
|
||
|
|
||
|
// define apply2 for tuple_meta_accumulate_impl
|
||
|
template<typename UnaryMetaFunctionClass, class Arg1, class Arg2>
|
||
|
struct apply2
|
||
|
: UnaryMetaFunctionClass::template apply<Arg1,Arg2>
|
||
|
{
|
||
|
}; // end apply2
|
||
|
|
||
|
|
||
|
// Meta-accumulate algorithm for tuples. Note: The template
|
||
|
// parameter StartType corresponds to the initial value in
|
||
|
// ordinary accumulation.
|
||
|
//
|
||
|
template<class Tuple, class BinaryMetaFun, class StartType>
|
||
|
struct tuple_meta_accumulate;
|
||
|
|
||
|
template<
|
||
|
typename Tuple
|
||
|
, class BinaryMetaFun
|
||
|
, typename StartType
|
||
|
>
|
||
|
struct tuple_meta_accumulate_impl
|
||
|
{
|
||
|
typedef typename apply2<
|
||
|
BinaryMetaFun
|
||
|
, typename Tuple::head_type
|
||
|
, typename tuple_meta_accumulate<
|
||
|
typename Tuple::tail_type
|
||
|
, BinaryMetaFun
|
||
|
, StartType
|
||
|
>::type
|
||
|
>::type type;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<
|
||
|
typename Tuple
|
||
|
, class BinaryMetaFun
|
||
|
, typename StartType
|
||
|
>
|
||
|
struct tuple_meta_accumulate
|
||
|
: thrust::detail::eval_if<
|
||
|
thrust::detail::is_same<Tuple, thrust::null_type>::value
|
||
|
, thrust::detail::identity_<StartType>
|
||
|
, tuple_meta_accumulate_impl<
|
||
|
Tuple
|
||
|
, BinaryMetaFun
|
||
|
, StartType
|
||
|
>
|
||
|
> // end eval_if
|
||
|
{
|
||
|
}; // end tuple_meta_accumulate
|
||
|
|
||
|
|
||
|
// transform algorithm for tuples. The template parameter Fun
|
||
|
// must be a unary functor which is also a unary metafunction
|
||
|
// class that computes its return type based on its argument
|
||
|
// type. For example:
|
||
|
//
|
||
|
// struct to_ptr
|
||
|
// {
|
||
|
// template <class Arg>
|
||
|
// struct apply
|
||
|
// {
|
||
|
// typedef Arg* type;
|
||
|
// }
|
||
|
//
|
||
|
// template <class Arg>
|
||
|
// Arg* operator()(Arg x);
|
||
|
// };
|
||
|
|
||
|
|
||
|
|
||
|
// for_each algorithm for tuples.
|
||
|
//
|
||
|
template<typename Fun, typename System>
|
||
|
inline __host__ __device__
|
||
|
Fun tuple_for_each(thrust::null_type, Fun f, System *)
|
||
|
{
|
||
|
return f;
|
||
|
} // end tuple_for_each()
|
||
|
|
||
|
|
||
|
template<typename Tuple, typename Fun, typename System>
|
||
|
inline __host__ __device__
|
||
|
Fun tuple_for_each(Tuple& t, Fun f, System *dispatch_tag)
|
||
|
{
|
||
|
f( t.get_head() );
|
||
|
return tuple_for_each(t.get_tail(), f, dispatch_tag);
|
||
|
} // end tuple_for_each()
|
||
|
|
||
|
|
||
|
template<typename Tuple, typename Fun>
|
||
|
inline __host__ __device__
|
||
|
Fun tuple_for_each(Tuple& t, Fun f, thrust::host_system_tag *dispatch_tag)
|
||
|
{
|
||
|
// XXX this path is required in order to accomodate pure host iterators
|
||
|
// (such as std::vector::iterator) in a zip_iterator
|
||
|
#ifndef __CUDA_ARCH__
|
||
|
f( t.get_head() );
|
||
|
return tuple_for_each(t.get_tail(), f, dispatch_tag);
|
||
|
#else
|
||
|
// this code will never be called
|
||
|
return f;
|
||
|
#endif
|
||
|
} // end tuple_for_each()
|
||
|
|
||
|
|
||
|
// Equality of tuples. NOTE: "==" for tuples currently (7/2003)
|
||
|
// has problems under some compilers, so I just do my own.
|
||
|
// No point in bringing in a bunch of #ifdefs here. This is
|
||
|
// going to go away with the next tuple implementation anyway.
|
||
|
//
|
||
|
__host__ __device__
|
||
|
inline bool tuple_equal(thrust::null_type, thrust::null_type)
|
||
|
{ return true; }
|
||
|
|
||
|
|
||
|
template<typename Tuple1, typename Tuple2>
|
||
|
__host__ __device__
|
||
|
bool tuple_equal(Tuple1 const& t1, Tuple2 const& t2)
|
||
|
{
|
||
|
return t1.get_head() == t2.get_head() &&
|
||
|
tuple_equal(t1.get_tail(), t2.get_tail());
|
||
|
} // end tuple_equal()
|
||
|
|
||
|
} // end end tuple_impl_specific
|
||
|
|
||
|
|
||
|
// Metafunction to obtain the type of the tuple whose element types
|
||
|
// are the value_types of an iterator tupel.
|
||
|
//
|
||
|
template<typename IteratorTuple>
|
||
|
struct tuple_of_value_types
|
||
|
: tuple_meta_transform<
|
||
|
IteratorTuple,
|
||
|
iterator_value
|
||
|
>
|
||
|
{
|
||
|
}; // end tuple_of_value_types
|
||
|
|
||
|
|
||
|
struct minimum_category_lambda
|
||
|
{
|
||
|
template<typename T1, typename T2>
|
||
|
struct apply : minimum_category<T1,T2>
|
||
|
{};
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
// Metafunction to obtain the minimal traversal tag in a tuple
|
||
|
// of iterators.
|
||
|
//
|
||
|
template<typename IteratorTuple>
|
||
|
struct minimum_traversal_category_in_iterator_tuple
|
||
|
{
|
||
|
typedef typename tuple_meta_transform<
|
||
|
IteratorTuple
|
||
|
, thrust::iterator_traversal
|
||
|
>::type tuple_of_traversal_tags;
|
||
|
|
||
|
typedef typename tuple_impl_specific::tuple_meta_accumulate<
|
||
|
tuple_of_traversal_tags
|
||
|
, minimum_category_lambda
|
||
|
, thrust::random_access_traversal_tag
|
||
|
>::type type;
|
||
|
};
|
||
|
|
||
|
|
||
|
struct minimum_system_lambda
|
||
|
{
|
||
|
template<typename T1, typename T2>
|
||
|
struct apply : minimum_system<T1,T2>
|
||
|
{};
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
// Metafunction to obtain the minimal system tag in a tuple
|
||
|
// of iterators.
|
||
|
template<typename IteratorTuple>
|
||
|
struct minimum_system_in_iterator_tuple
|
||
|
{
|
||
|
typedef typename thrust::detail::tuple_meta_transform<
|
||
|
IteratorTuple,
|
||
|
thrust::iterator_system
|
||
|
>::type tuple_of_system_tags;
|
||
|
|
||
|
typedef typename tuple_impl_specific::tuple_meta_accumulate<
|
||
|
tuple_of_system_tags,
|
||
|
minimum_system_lambda,
|
||
|
thrust::any_system_tag
|
||
|
>::type type;
|
||
|
};
|
||
|
|
||
|
namespace zip_iterator_base_ns
|
||
|
{
|
||
|
|
||
|
|
||
|
template<int i, typename Tuple>
|
||
|
struct tuple_elements_helper
|
||
|
: eval_if<
|
||
|
(i < tuple_size<Tuple>::value),
|
||
|
tuple_element<i,Tuple>,
|
||
|
identity_<thrust::null_type>
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
template<typename Tuple>
|
||
|
struct tuple_elements
|
||
|
{
|
||
|
typedef typename tuple_elements_helper<0,Tuple>::type T0;
|
||
|
typedef typename tuple_elements_helper<1,Tuple>::type T1;
|
||
|
typedef typename tuple_elements_helper<2,Tuple>::type T2;
|
||
|
typedef typename tuple_elements_helper<3,Tuple>::type T3;
|
||
|
typedef typename tuple_elements_helper<4,Tuple>::type T4;
|
||
|
typedef typename tuple_elements_helper<5,Tuple>::type T5;
|
||
|
typedef typename tuple_elements_helper<6,Tuple>::type T6;
|
||
|
typedef typename tuple_elements_helper<7,Tuple>::type T7;
|
||
|
typedef typename tuple_elements_helper<8,Tuple>::type T8;
|
||
|
typedef typename tuple_elements_helper<9,Tuple>::type T9;
|
||
|
};
|
||
|
|
||
|
|
||
|
template<typename IteratorTuple>
|
||
|
struct tuple_of_iterator_references
|
||
|
{
|
||
|
// get a thrust::tuple of the iterators' references
|
||
|
typedef typename tuple_meta_transform<
|
||
|
IteratorTuple,
|
||
|
iterator_reference
|
||
|
>::type tuple_of_references;
|
||
|
|
||
|
// get at the individual tuple element types by name
|
||
|
typedef tuple_elements<tuple_of_references> elements;
|
||
|
|
||
|
// map thrust::tuple<T...> to tuple_of_iterator_references<T...>
|
||
|
typedef thrust::detail::tuple_of_iterator_references<
|
||
|
typename elements::T0,
|
||
|
typename elements::T1,
|
||
|
typename elements::T2,
|
||
|
typename elements::T3,
|
||
|
typename elements::T4,
|
||
|
typename elements::T5,
|
||
|
typename elements::T6,
|
||
|
typename elements::T7,
|
||
|
typename elements::T8,
|
||
|
typename elements::T9
|
||
|
> type;
|
||
|
};
|
||
|
|
||
|
|
||
|
} // end zip_iterator_base_ns
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Class zip_iterator_base
|
||
|
//
|
||
|
// Builds and exposes the iterator facade type from which the zip
|
||
|
// iterator will be derived.
|
||
|
//
|
||
|
template<typename IteratorTuple>
|
||
|
struct zip_iterator_base
|
||
|
{
|
||
|
//private:
|
||
|
// reference type is the type of the tuple obtained from the
|
||
|
// iterators' reference types.
|
||
|
typedef typename zip_iterator_base_ns::tuple_of_iterator_references<IteratorTuple>::type reference;
|
||
|
|
||
|
// Boost's Value type is the same as reference type.
|
||
|
//typedef reference value_type;
|
||
|
typedef typename tuple_of_value_types<IteratorTuple>::type value_type;
|
||
|
|
||
|
// Difference type is the first iterator's difference type
|
||
|
typedef typename thrust::iterator_traits<
|
||
|
typename thrust::tuple_element<0, IteratorTuple>::type
|
||
|
>::difference_type difference_type;
|
||
|
|
||
|
// Iterator system is the minimum system tag in the
|
||
|
// iterator tuple
|
||
|
typedef typename
|
||
|
minimum_system_in_iterator_tuple<IteratorTuple>::type system;
|
||
|
|
||
|
// Traversal category is the minimum traversal category in the
|
||
|
// iterator tuple
|
||
|
typedef typename
|
||
|
minimum_traversal_category_in_iterator_tuple<IteratorTuple>::type traversal_category;
|
||
|
|
||
|
public:
|
||
|
|
||
|
// The iterator facade type from which the zip iterator will
|
||
|
// be derived.
|
||
|
typedef thrust::iterator_facade<
|
||
|
zip_iterator<IteratorTuple>,
|
||
|
value_type,
|
||
|
system,
|
||
|
traversal_category,
|
||
|
reference,
|
||
|
difference_type
|
||
|
> type;
|
||
|
}; // end zip_iterator_base
|
||
|
|
||
|
} // end detail
|
||
|
|
||
|
} // end thrust
|
||
|
|
||
|
|