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.
277 lines
6.9 KiB
277 lines
6.9 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/detail/config.h>
|
||
|
#include <thrust/detail/type_traits.h>
|
||
|
#include <thrust/detail/type_traits/is_metafunction_defined.h>
|
||
|
#include <thrust/detail/type_traits/has_nested_type.h>
|
||
|
#include <thrust/iterator/iterator_traits.h>
|
||
|
#include <cstddef>
|
||
|
|
||
|
namespace thrust
|
||
|
{
|
||
|
namespace detail
|
||
|
{
|
||
|
|
||
|
template<typename Ptr> struct pointer_element;
|
||
|
|
||
|
template<template<typename> class Ptr, typename Arg>
|
||
|
struct pointer_element<Ptr<Arg> >
|
||
|
{
|
||
|
typedef Arg type;
|
||
|
};
|
||
|
|
||
|
template<template<typename,typename> class Ptr, typename Arg1, typename Arg2>
|
||
|
struct pointer_element<Ptr<Arg1,Arg2> >
|
||
|
{
|
||
|
typedef Arg1 type;
|
||
|
};
|
||
|
|
||
|
template<template<typename,typename,typename> class Ptr, typename Arg1, typename Arg2, typename Arg3>
|
||
|
struct pointer_element<Ptr<Arg1,Arg2,Arg3> >
|
||
|
{
|
||
|
typedef Arg1 type;
|
||
|
};
|
||
|
|
||
|
template<template<typename,typename,typename,typename> class Ptr, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
|
||
|
struct pointer_element<Ptr<Arg1,Arg2,Arg3,Arg4> >
|
||
|
{
|
||
|
typedef Arg1 type;
|
||
|
};
|
||
|
|
||
|
template<template<typename,typename,typename,typename,typename> class Ptr, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
|
||
|
struct pointer_element<Ptr<Arg1,Arg2,Arg3,Arg4,Arg5> >
|
||
|
{
|
||
|
typedef Arg1 type;
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
struct pointer_element<T*>
|
||
|
{
|
||
|
typedef T type;
|
||
|
};
|
||
|
|
||
|
template<typename Ptr>
|
||
|
struct pointer_difference
|
||
|
{
|
||
|
typedef typename Ptr::difference_type type;
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
struct pointer_difference<T*>
|
||
|
{
|
||
|
typedef std::ptrdiff_t type;
|
||
|
};
|
||
|
|
||
|
template<typename Ptr, typename T> struct rebind_pointer;
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
struct rebind_pointer<T*,U>
|
||
|
{
|
||
|
typedef U* type;
|
||
|
};
|
||
|
|
||
|
template<template<typename> class Ptr, typename Arg, typename T>
|
||
|
struct rebind_pointer<Ptr<Arg>,T>
|
||
|
{
|
||
|
typedef Ptr<T> type;
|
||
|
};
|
||
|
|
||
|
template<template<typename, typename> class Ptr, typename Arg1, typename Arg2, typename T>
|
||
|
struct rebind_pointer<Ptr<Arg1,Arg2>,T>
|
||
|
{
|
||
|
typedef Ptr<T,Arg2> type;
|
||
|
};
|
||
|
|
||
|
template<template<typename, typename, typename> class Ptr, typename Arg1, typename Arg2, typename Arg3, typename T>
|
||
|
struct rebind_pointer<Ptr<Arg1,Arg2,Arg3>,T>
|
||
|
{
|
||
|
typedef Ptr<T,Arg2,Arg3> type;
|
||
|
};
|
||
|
|
||
|
template<template<typename, typename, typename, typename> class Ptr, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename T>
|
||
|
struct rebind_pointer<Ptr<Arg1,Arg2,Arg3,Arg4>,T>
|
||
|
{
|
||
|
typedef Ptr<T,Arg2,Arg3,Arg4> type;
|
||
|
};
|
||
|
|
||
|
// XXX this should probably be renamed native_type or similar
|
||
|
__THRUST_DEFINE_HAS_NESTED_TYPE(has_raw_pointer, raw_pointer)
|
||
|
|
||
|
namespace pointer_traits_detail
|
||
|
{
|
||
|
|
||
|
template<typename Ptr, typename Enable = void> struct pointer_raw_pointer_impl {};
|
||
|
|
||
|
template<typename T>
|
||
|
struct pointer_raw_pointer_impl<T*>
|
||
|
{
|
||
|
typedef T* type;
|
||
|
};
|
||
|
|
||
|
template<typename Ptr>
|
||
|
struct pointer_raw_pointer_impl<Ptr, typename enable_if<has_raw_pointer<Ptr>::value>::type>
|
||
|
{
|
||
|
typedef typename Ptr::raw_pointer type;
|
||
|
};
|
||
|
|
||
|
} // end pointer_traits_detail
|
||
|
|
||
|
template<typename T>
|
||
|
struct pointer_raw_pointer
|
||
|
: pointer_traits_detail::pointer_raw_pointer_impl<T>
|
||
|
{};
|
||
|
|
||
|
namespace pointer_traits_detail
|
||
|
{
|
||
|
|
||
|
template<typename Void>
|
||
|
struct capture_address
|
||
|
{
|
||
|
template<typename T>
|
||
|
__host__ __device__
|
||
|
capture_address(T &r)
|
||
|
: m_addr(&r)
|
||
|
{}
|
||
|
|
||
|
inline __host__ __device__
|
||
|
Void *operator&() const
|
||
|
{
|
||
|
return m_addr;
|
||
|
}
|
||
|
|
||
|
Void *m_addr;
|
||
|
};
|
||
|
|
||
|
// metafunction to compute the type of pointer_to's parameter below
|
||
|
template<typename T>
|
||
|
struct pointer_to_param
|
||
|
: thrust::detail::eval_if<
|
||
|
thrust::detail::is_void<T>::value,
|
||
|
thrust::detail::identity_<capture_address<T> >,
|
||
|
thrust::detail::add_reference<T>
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
}
|
||
|
|
||
|
template<typename Ptr>
|
||
|
struct pointer_traits
|
||
|
{
|
||
|
typedef Ptr pointer;
|
||
|
typedef typename pointer_element<Ptr>::type element_type;
|
||
|
typedef typename pointer_difference<Ptr>::type difference_type;
|
||
|
|
||
|
template<typename U>
|
||
|
struct rebind
|
||
|
{
|
||
|
typedef typename rebind_pointer<Ptr,U>::type other;
|
||
|
};
|
||
|
|
||
|
__host__ __device__
|
||
|
inline static pointer pointer_to(typename pointer_traits_detail::pointer_to_param<element_type>::type r)
|
||
|
{
|
||
|
// XXX this is supposed to be pointer::pointer_to(&r); (i.e., call a static member function of pointer called pointer_to)
|
||
|
// assume that pointer has a constructor from raw pointer instead
|
||
|
|
||
|
return pointer(&r);
|
||
|
}
|
||
|
|
||
|
// thrust additions follow
|
||
|
typedef typename pointer_raw_pointer<Ptr>::type raw_pointer;
|
||
|
|
||
|
__host__ __device__
|
||
|
inline static raw_pointer get(pointer ptr)
|
||
|
{
|
||
|
return ptr.get();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename T>
|
||
|
struct pointer_traits<T*>
|
||
|
{
|
||
|
typedef T* pointer;
|
||
|
typedef T element_type;
|
||
|
typedef typename pointer_difference<T*>::type difference_type;
|
||
|
|
||
|
template<typename U>
|
||
|
struct rebind
|
||
|
{
|
||
|
typedef U* other;
|
||
|
};
|
||
|
|
||
|
__host__ __device__
|
||
|
inline static pointer pointer_to(typename pointer_traits_detail::pointer_to_param<element_type>::type r)
|
||
|
{
|
||
|
return &r;
|
||
|
}
|
||
|
|
||
|
// thrust additions follow
|
||
|
typedef typename pointer_raw_pointer<T*>::type raw_pointer;
|
||
|
|
||
|
__host__ __device__
|
||
|
inline static raw_pointer get(pointer ptr)
|
||
|
{
|
||
|
return ptr;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
template<typename FromPtr, typename ToPtr>
|
||
|
struct is_pointer_convertible
|
||
|
: thrust::detail::and_<
|
||
|
thrust::detail::is_convertible<
|
||
|
typename pointer_element<FromPtr>::type *,
|
||
|
typename pointer_element<ToPtr>::type *
|
||
|
>,
|
||
|
thrust::detail::is_convertible<
|
||
|
typename iterator_system<FromPtr>::type,
|
||
|
typename iterator_system<ToPtr>::type
|
||
|
>
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
// this could be a lot better, but for our purposes, it's probably
|
||
|
// sufficient just to check if pointer_raw_pointer<T> has meaning
|
||
|
template<typename T>
|
||
|
struct is_thrust_pointer
|
||
|
: is_metafunction_defined<pointer_raw_pointer<T> >
|
||
|
{};
|
||
|
|
||
|
// avoid inspecting traits of the arguments if they aren't known to be pointers
|
||
|
template<typename FromPtr, typename ToPtr>
|
||
|
struct lazy_is_pointer_convertible
|
||
|
: thrust::detail::eval_if<
|
||
|
is_thrust_pointer<FromPtr>::value && is_thrust_pointer<ToPtr>::value,
|
||
|
is_pointer_convertible<FromPtr,ToPtr>,
|
||
|
thrust::detail::identity_<thrust::detail::false_type>
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
template<typename FromPtr, typename ToPtr, typename T = void>
|
||
|
struct enable_if_pointer_is_convertible
|
||
|
: thrust::detail::enable_if<
|
||
|
lazy_is_pointer_convertible<FromPtr,ToPtr>::type::value,
|
||
|
T
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
|
||
|
} // end detail
|
||
|
} // end thrust
|
||
|
|