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.
283 lines
11 KiB
283 lines
11 KiB
/* |
|
* 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/detail/config.h> |
|
#include <thrust/detail/type_traits.h> |
|
#include <thrust/iterator/detail/host_system_tag.h> |
|
#include <thrust/iterator/detail/device_system_tag.h> |
|
#include <thrust/iterator/detail/any_system_tag.h> |
|
#include <thrust/iterator/iterator_categories.h> |
|
#include <thrust/iterator/detail/iterator_traversal_tags.h> |
|
#include <thrust/iterator/detail/is_iterator_category.h> |
|
#include <thrust/iterator/detail/iterator_category_to_traversal.h> |
|
|
|
namespace thrust |
|
{ |
|
|
|
namespace detail |
|
{ |
|
|
|
template<typename Category, typename System, typename Traversal> |
|
struct iterator_category_with_system_and_traversal |
|
: Category |
|
{ |
|
}; // end iterator_category_with_system_and_traversal |
|
|
|
// specialize iterator_category_to_system for iterator_category_with_system_and_traversal |
|
template<typename Category> struct iterator_category_to_system; |
|
|
|
template<typename Category, typename System, typename Traversal> |
|
struct iterator_category_to_system<iterator_category_with_system_and_traversal<Category,System,Traversal> > |
|
{ |
|
typedef System type; |
|
}; // end iterator_category_with_system_and_traversal |
|
|
|
|
|
// adapted from http://www.boost.org/doc/libs/1_37_0/libs/iterator/doc/iterator_facade.html#iterator-category |
|
// |
|
// in our implementation, R need not be a reference type to result in a category |
|
// derived from forward_XXX_iterator_tag |
|
// |
|
// iterator-category(T,V,R) := |
|
// if(T is convertible to input_host_iterator_tag |
|
// || T is convertible to output_host_iterator_tag |
|
// || T is convertible to input_device_iterator_tag |
|
// || T is convertible to output_device_iterator_tag |
|
// ) |
|
// return T |
|
// |
|
// else if (T is not convertible to incrementable_traversal_tag) |
|
// the program is ill-formed |
|
// |
|
// else return a type X satisfying the following two constraints: |
|
// |
|
// 1. X is convertible to X1, and not to any more-derived |
|
// type, where X1 is defined by: |
|
// |
|
// if (T is convertible to forward_traversal_tag) |
|
// { |
|
// if (T is convertible to random_access_traversal_tag) |
|
// X1 = random_access_host_iterator_tag |
|
// else if (T is convertible to bidirectional_traversal_tag) |
|
// X1 = bidirectional_host_iterator_tag |
|
// else |
|
// X1 = forward_host_iterator_tag |
|
// } |
|
// else |
|
// { |
|
// if (T is convertible to single_pass_traversal_tag |
|
// && R is convertible to V) |
|
// X1 = input_host_iterator_tag |
|
// else |
|
// X1 = T |
|
// } |
|
// |
|
// 2. category-to-traversal(X) is convertible to the most |
|
// derived traversal tag type to which X is also convertible, |
|
// and not to any more-derived traversal tag type. |
|
|
|
|
|
template<typename System, typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_default_category; |
|
|
|
|
|
// Thrust's implementation of iterator_facade_default_category is slightly |
|
// different from Boost's equivalent. |
|
// Thrust does not check is_convertible<Reference, ValueParam> because Reference |
|
// may not be a complete type at this point, and implementations of is_convertible |
|
// typically require that both types be complete. |
|
// Instead, it simply assumes that if is_convertible<Traversal, single_pass_traversal_tag>, |
|
// then the category is input_iterator_tag |
|
|
|
|
|
// this is the function for standard system iterators |
|
template<typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_default_category_std : |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>::value, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value, |
|
thrust::detail::identity_<std::random_access_iterator_tag>, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value, |
|
thrust::detail::identity_<std::bidirectional_iterator_tag>, |
|
thrust::detail::identity_<std::forward_iterator_tag> |
|
> |
|
>, |
|
thrust::detail::eval_if< // XXX note we differ from Boost here |
|
thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>::value, |
|
thrust::detail::identity_<std::input_iterator_tag>, |
|
thrust::detail::identity_<Traversal> |
|
> |
|
> |
|
{ |
|
}; // end iterator_facade_default_category_std |
|
|
|
|
|
// this is the function for host system iterators |
|
template<typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_default_category_host : |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>::value, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::random_access_host_iterator_tag>, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::bidirectional_host_iterator_tag>, |
|
thrust::detail::identity_<thrust::forward_host_iterator_tag> |
|
> |
|
>, |
|
thrust::detail::eval_if< // XXX note we differ from Boost here |
|
thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::input_host_iterator_tag>, |
|
thrust::detail::identity_<Traversal> |
|
> |
|
> |
|
{ |
|
}; // end iterator_facade_default_category_host |
|
|
|
|
|
// this is the function for device system iterators |
|
template<typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_default_category_device : |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>::value, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::random_access_device_iterator_tag>, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::bidirectional_device_iterator_tag>, |
|
thrust::detail::identity_<thrust::forward_device_iterator_tag> |
|
> |
|
>, |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>::value, // XXX note we differ from Boost here |
|
thrust::detail::identity_<thrust::input_device_iterator_tag>, |
|
thrust::detail::identity_<Traversal> |
|
> |
|
> |
|
{ |
|
}; // end iterator_facade_default_category_device |
|
|
|
|
|
// this is the function for any system iterators |
|
template<typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_default_category_any : |
|
thrust::detail::eval_if< |
|
|
|
thrust::detail::is_convertible<Traversal, thrust::forward_traversal_tag>::value, |
|
|
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::random_access_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::random_access_universal_iterator_tag>, |
|
|
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::bidirectional_traversal_tag>::value, |
|
thrust::detail::identity_<thrust::bidirectional_universal_iterator_tag>, |
|
thrust::detail::identity_<thrust::forward_universal_iterator_tag> |
|
> |
|
>, |
|
|
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<Traversal, thrust::single_pass_traversal_tag>::value, // XXX note we differ from Boost here |
|
thrust::detail::identity_<thrust::input_universal_iterator_tag>, |
|
thrust::detail::identity_<Traversal> |
|
> |
|
> |
|
{ |
|
}; // end iterator_facade_default_category_any |
|
|
|
|
|
template<typename System, typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_default_category |
|
// check for any system |
|
: thrust::detail::eval_if< |
|
thrust::detail::is_convertible<System, thrust::any_system_tag>::value, |
|
iterator_facade_default_category_any<Traversal, ValueParam, Reference>, |
|
|
|
// check for host system |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<System, thrust::host_system_tag>::value, |
|
iterator_facade_default_category_host<Traversal, ValueParam, Reference>, |
|
|
|
// check for device system |
|
thrust::detail::eval_if< |
|
thrust::detail::is_convertible<System, thrust::device_system_tag>::value, |
|
iterator_facade_default_category_device<Traversal, ValueParam, Reference>, |
|
|
|
// if we don't recognize the system, get a standard iterator category |
|
// and combine it with System & Traversal |
|
thrust::detail::identity_< |
|
thrust::detail::iterator_category_with_system_and_traversal< |
|
typename iterator_facade_default_category_std<Traversal, ValueParam, Reference>::type, |
|
System, |
|
Traversal |
|
> |
|
> |
|
> |
|
> |
|
> |
|
{}; |
|
|
|
|
|
template<typename System, typename Traversal, typename ValueParam, typename Reference> |
|
struct iterator_facade_category_impl |
|
{ |
|
typedef typename iterator_facade_default_category< |
|
System,Traversal,ValueParam,Reference |
|
>::type category; |
|
|
|
// we must be able to deduce both Traversal & System from category |
|
// otherwise, munge them all together |
|
typedef typename thrust::detail::eval_if< |
|
thrust::detail::and_< |
|
thrust::detail::is_same< |
|
Traversal, |
|
typename thrust::detail::iterator_category_to_traversal<category>::type |
|
>, |
|
thrust::detail::is_same< |
|
System, |
|
typename thrust::detail::iterator_category_to_system<category>::type |
|
> |
|
>::value, |
|
thrust::detail::identity_<category>, |
|
thrust::detail::identity_<thrust::detail::iterator_category_with_system_and_traversal<category,System,Traversal> > |
|
>::type type; |
|
}; // end iterator_facade_category_impl |
|
|
|
|
|
template<typename CategoryOrSystem, |
|
typename CategoryOrTraversal, |
|
typename ValueParam, |
|
typename Reference> |
|
struct iterator_facade_category |
|
{ |
|
typedef typename |
|
thrust::detail::eval_if< |
|
thrust::detail::is_iterator_category<CategoryOrTraversal>::value, |
|
thrust::detail::identity_<CategoryOrTraversal>, // categories are fine as-is |
|
iterator_facade_category_impl<CategoryOrSystem, CategoryOrTraversal, ValueParam, Reference> |
|
>::type type; |
|
}; // end iterator_facade_category |
|
|
|
|
|
} // end detail |
|
} // end thrust |
|
|
|
|