/* * 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 #include #include #include #include #include namespace thrust { namespace detail { template struct pointer_element; template class Ptr, typename Arg> struct pointer_element > { typedef Arg type; }; template class Ptr, typename Arg1, typename Arg2> struct pointer_element > { typedef Arg1 type; }; template class Ptr, typename Arg1, typename Arg2, typename Arg3> struct pointer_element > { typedef Arg1 type; }; template class Ptr, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct pointer_element > { typedef Arg1 type; }; template class Ptr, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct pointer_element > { typedef Arg1 type; }; template struct pointer_element { typedef T type; }; template struct pointer_difference { typedef typename Ptr::difference_type type; }; template struct pointer_difference { typedef std::ptrdiff_t type; }; template struct rebind_pointer; template struct rebind_pointer { typedef U* type; }; template class Ptr, typename Arg, typename T> struct rebind_pointer,T> { typedef Ptr type; }; template class Ptr, typename Arg1, typename Arg2, typename T> struct rebind_pointer,T> { typedef Ptr type; }; template class Ptr, typename Arg1, typename Arg2, typename Arg3, typename T> struct rebind_pointer,T> { typedef Ptr type; }; template class Ptr, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename T> struct rebind_pointer,T> { typedef Ptr 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 struct pointer_raw_pointer_impl {}; template struct pointer_raw_pointer_impl { typedef T* type; }; template struct pointer_raw_pointer_impl::value>::type> { typedef typename Ptr::raw_pointer type; }; } // end pointer_traits_detail template struct pointer_raw_pointer : pointer_traits_detail::pointer_raw_pointer_impl {}; namespace pointer_traits_detail { template struct capture_address { template __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 struct pointer_to_param : thrust::detail::eval_if< thrust::detail::is_void::value, thrust::detail::identity_ >, thrust::detail::add_reference > {}; } template struct pointer_traits { typedef Ptr pointer; typedef typename pointer_element::type element_type; typedef typename pointer_difference::type difference_type; template struct rebind { typedef typename rebind_pointer::type other; }; __host__ __device__ inline static pointer pointer_to(typename pointer_traits_detail::pointer_to_param::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::type raw_pointer; __host__ __device__ inline static raw_pointer get(pointer ptr) { return ptr.get(); } }; template struct pointer_traits { typedef T* pointer; typedef T element_type; typedef typename pointer_difference::type difference_type; template struct rebind { typedef U* other; }; __host__ __device__ inline static pointer pointer_to(typename pointer_traits_detail::pointer_to_param::type r) { return &r; } // thrust additions follow typedef typename pointer_raw_pointer::type raw_pointer; __host__ __device__ inline static raw_pointer get(pointer ptr) { return ptr; } }; template struct is_pointer_convertible : thrust::detail::and_< thrust::detail::is_convertible< typename pointer_element::type *, typename pointer_element::type * >, thrust::detail::is_convertible< typename iterator_system::type, typename iterator_system::type > > {}; // this could be a lot better, but for our purposes, it's probably // sufficient just to check if pointer_raw_pointer has meaning template struct is_thrust_pointer : is_metafunction_defined > {}; // avoid inspecting traits of the arguments if they aren't known to be pointers template struct lazy_is_pointer_convertible : thrust::detail::eval_if< is_thrust_pointer::value && is_thrust_pointer::value, is_pointer_convertible, thrust::detail::identity_ > {}; template struct enable_if_pointer_is_convertible : thrust::detail::enable_if< lazy_is_pointer_convertible::type::value, T > {}; } // end detail } // end thrust