/* * 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 namespace thrust { namespace detail { // specialize is_unwrappable // a tuple is_unwrappable if any of its elements is_unwrappable template< typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > struct is_unwrappable< thrust::tuple > : or_< is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable > {}; // specialize is_unwrappable // a tuple_of_iterator_references is_unwrappable if any of its elements is_unwrappable template< typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > struct is_unwrappable< thrust::detail::tuple_of_iterator_references > : or_< is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable, is_unwrappable > {}; namespace raw_reference_detail { // unlike raw_reference, // raw_reference_tuple_helper needs to return a value // when it encounters one, rather than a reference // upon encountering tuple, recurse // // we want the following behavior: // 1. T -> T // 2. T& -> T& // 3. null_type -> null_type // 4. reference -> T& // 5. tuple_of_iterator_references -> tuple_of_iterator_references::type> // wrapped references are unwrapped using raw_reference, otherwise, return T template struct raw_reference_tuple_helper : eval_if< is_unwrappable< typename remove_cv::type >::value, raw_reference, identity_ > {}; // recurse on tuples template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > struct raw_reference_tuple_helper< thrust::tuple > { typedef thrust::tuple< typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type > type; }; template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > struct raw_reference_tuple_helper< thrust::detail::tuple_of_iterator_references > { typedef thrust::detail::tuple_of_iterator_references< typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type, typename raw_reference_tuple_helper::type > type; }; } // end raw_reference_detail // if a tuple "tuple_type" is_unwrappable, // then the raw_reference of tuple_type is a tuple of its members' raw_references // else the raw_reference of tuple_type is tuple_type & template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > struct raw_reference< thrust::tuple > { private: typedef thrust::tuple tuple_type; public: typedef typename eval_if< is_unwrappable::value, raw_reference_detail::raw_reference_tuple_helper, add_reference >::type type; }; template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > struct raw_reference< thrust::detail::tuple_of_iterator_references > { private: typedef detail::tuple_of_iterator_references tuple_type; public: typedef typename raw_reference_detail::raw_reference_tuple_helper::type type; // XXX figure out why is_unwrappable seems to be broken for tuple_of_iterator_references //typedef typename eval_if< // is_unwrappable::value, // raw_reference_detail::raw_reference_tuple_helper, // add_reference //>::type type; }; struct raw_reference_caster { template __host__ __device__ typename detail::raw_reference::type operator()(T &ref) { return thrust::raw_reference_cast(ref); } template __host__ __device__ typename detail::raw_reference::type operator()(const T &ref) { return thrust::raw_reference_cast(ref); } template< typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > __host__ __device__ typename detail::raw_reference< thrust::detail::tuple_of_iterator_references >::type operator()(thrust::detail::tuple_of_iterator_references t, typename enable_if< is_unwrappable >::value >::type * = 0) { return thrust::raw_reference_cast(t); } }; // end raw_reference_caster } // end detail template< typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > __host__ __device__ typename detail::enable_if_unwrappable< thrust::detail::tuple_of_iterator_references, typename detail::raw_reference< thrust::detail::tuple_of_iterator_references >::type >::type raw_reference_cast(thrust::detail::tuple_of_iterator_references t) { thrust::detail::raw_reference_caster f; // note that we pass raw_reference_tuple_helper, not raw_reference as the unary metafunction // the subtle difference is important return thrust::detail::tuple_host_device_transform(t, f); } // end raw_reference_cast } // end thrust