//@HEADER // ************************************************************************ // // Kokkos v. 2.0 // Copyright (2014) Sandia Corporation // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov) // // ************************************************************************ //@HEADER /// \file Kokkos_Pair.hpp /// \brief Declaration and definition of Kokkos::pair. /// /// This header file declares and defines Kokkos::pair and its related /// nonmember functions. #ifndef KOKKOS_PAIR_HPP #define KOKKOS_PAIR_HPP #include #include namespace Kokkos { /// \struct pair /// \brief Replacement for std::pair that works on CUDA devices. /// /// The instance methods of std::pair, including its constructors, are /// not marked as __device__ functions. Thus, they cannot be /// called on a CUDA device, such as an NVIDIA GPU. This struct /// implements the same interface as std::pair, but can be used on a /// CUDA device as well as on the host. template struct pair { //! The first template parameter of this class. typedef T1 first_type; //! The second template parameter of this class. typedef T2 second_type; //! The first element of the pair. first_type first; //! The second element of the pair. second_type second; /// \brief Default constructor. /// /// This calls the default constructors of T1 and T2. It won't /// compile if those default constructors are not defined and /// public. KOKKOS_FORCEINLINE_FUNCTION pair() : first(), second() {} /// \brief Constructor that takes both elements of the pair. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. KOKKOS_FORCEINLINE_FUNCTION pair(first_type const& f, second_type const& s) : first(f), second(s) {} /// \brief Copy constructor. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair( const pair &p) : first(p.first), second(p.second) {} /// \brief Copy constructor. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair( const volatile pair &p) : first(p.first), second(p.second) {} /// \brief Assignment operator. /// /// This calls the assignment operators of T1 and T2. It won't /// compile if the assignment operators are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair & operator=(const pair &p) { first = p.first; second = p.second; return *this; } /// \brief Assignment operator. /// /// This calls the assignment operators of T1 and T2. It won't /// compile if the assignment operators are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION volatile pair & operator=(const volatile pair &p) volatile { first = p.first; second = p.second; return *this; } // from std::pair template pair( const std::pair &p) : first(p.first), second(p.second) {} /// \brief Return the std::pair version of this object. /// /// This is not a device function; you may not call it on a /// CUDA device. It is meant to be called on the host, if the user /// wants an std::pair instead of a Kokkos::pair. /// /// \note This is not a conversion operator, since defining a /// conversion operator made the relational operators have /// ambiguous definitions. std::pair to_std_pair() const { return std::make_pair(first,second); } }; template struct pair { //! The first template parameter of this class. typedef T1& first_type; //! The second template parameter of this class. typedef T2& second_type; //! The first element of the pair. first_type first; //! The second element of the pair. second_type second; /// \brief Constructor that takes both elements of the pair. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. KOKKOS_FORCEINLINE_FUNCTION pair(first_type f, second_type s) : first(f), second(s) {} /// \brief Copy constructor. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair( const pair &p) : first(p.first), second(p.second) {} // from std::pair template pair( const std::pair &p) : first(p.first), second(p.second) {} /// \brief Assignment operator. /// /// This calls the assignment operators of T1 and T2. It won't /// compile if the assignment operators are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair & operator=(const pair &p) { first = p.first; second = p.second; return *this; } /// \brief Return the std::pair version of this object. /// /// This is not a device function; you may not call it on a /// CUDA device. It is meant to be called on the host, if the user /// wants an std::pair instead of a Kokkos::pair. /// /// \note This is not a conversion operator, since defining a /// conversion operator made the relational operators have /// ambiguous definitions. std::pair to_std_pair() const { return std::make_pair(first,second); } }; template struct pair { //! The first template parameter of this class. typedef T1 first_type; //! The second template parameter of this class. typedef T2& second_type; //! The first element of the pair. first_type first; //! The second element of the pair. second_type second; /// \brief Constructor that takes both elements of the pair. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. KOKKOS_FORCEINLINE_FUNCTION pair(first_type const& f, second_type s) : first(f), second(s) {} /// \brief Copy constructor. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair( const pair &p) : first(p.first), second(p.second) {} // from std::pair template pair( const std::pair &p) : first(p.first), second(p.second) {} /// \brief Assignment operator. /// /// This calls the assignment operators of T1 and T2. It won't /// compile if the assignment operators are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair & operator=(const pair &p) { first = p.first; second = p.second; return *this; } /// \brief Return the std::pair version of this object. /// /// This is not a device function; you may not call it on a /// CUDA device. It is meant to be called on the host, if the user /// wants an std::pair instead of a Kokkos::pair. /// /// \note This is not a conversion operator, since defining a /// conversion operator made the relational operators have /// ambiguous definitions. std::pair to_std_pair() const { return std::make_pair(first,second); } }; template struct pair { //! The first template parameter of this class. typedef T1& first_type; //! The second template parameter of this class. typedef T2 second_type; //! The first element of the pair. first_type first; //! The second element of the pair. second_type second; /// \brief Constructor that takes both elements of the pair. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. KOKKOS_FORCEINLINE_FUNCTION pair(first_type f, second_type const& s) : first(f), second(s) {} /// \brief Copy constructor. /// /// This calls the copy constructors of T1 and T2. It won't compile /// if those copy constructors are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair( const pair &p) : first(p.first), second(p.second) {} // from std::pair template pair( const std::pair &p) : first(p.first), second(p.second) {} /// \brief Assignment operator. /// /// This calls the assignment operators of T1 and T2. It won't /// compile if the assignment operators are not defined and public. template KOKKOS_FORCEINLINE_FUNCTION pair & operator=(const pair &p) { first = p.first; second = p.second; return *this; } /// \brief Return the std::pair version of this object. /// /// This is not a device function; you may not call it on a /// CUDA device. It is meant to be called on the host, if the user /// wants an std::pair instead of a Kokkos::pair. /// /// \note This is not a conversion operator, since defining a /// conversion operator made the relational operators have /// ambiguous definitions. std::pair to_std_pair() const { return std::make_pair(first,second); } }; //! Equality operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION bool operator== (const pair& lhs, const pair& rhs) { return lhs.first==rhs.first && lhs.second==rhs.second; } //! Inequality operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION bool operator!= (const pair& lhs, const pair& rhs) { return !(lhs==rhs); } //! Less-than operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION bool operator< (const pair& lhs, const pair& rhs) { return lhs.first KOKKOS_FORCEINLINE_FUNCTION bool operator<= (const pair& lhs, const pair& rhs) { return !(rhs KOKKOS_FORCEINLINE_FUNCTION bool operator> (const pair& lhs, const pair& rhs) { return rhs KOKKOS_FORCEINLINE_FUNCTION bool operator>= (const pair& lhs, const pair& rhs) { return !(lhs KOKKOS_FORCEINLINE_FUNCTION pair make_pair (T1 x, T2 y) { return ( pair(x,y) ); } /// \brief Return a pair of references to the input arguments. /// /// This compares to std::tie (new in C++11). You can use it to /// assign to two variables at once, from the result of a function /// that returns a pair. For example (__device__ and /// __host__ attributes omitted for brevity): /// \code /// // Declaration of the function to call. /// // First return value: operation count. /// // Second return value: whether all operations succeeded. /// Kokkos::pair someFunction (); /// /// // Code that uses Kokkos::tie. /// int myFunction () { /// int count = 0; /// bool success = false; /// /// // This assigns to both count and success. /// Kokkos::tie (count, success) = someFunction (); /// /// if (! success) { /// // ... Some operation failed; /// // take corrective action ... /// } /// return count; /// } /// \endcode /// /// The line that uses tie() could have been written like this: /// \code /// Kokkos::pair result = someFunction (); /// count = result.first; /// success = result.second; /// \endcode /// /// Using tie() saves two lines of code and avoids a copy of each /// element of the pair. The latter could be significant if one or /// both elements of the pair are more substantial objects than \c int /// or \c bool. template KOKKOS_FORCEINLINE_FUNCTION pair tie (T1 & x, T2 & y) { return ( pair(x,y) ); } // // Specialization of Kokkos::pair for a \c void second argument. This // is not actually a "pair"; it only contains one element, the first. // template struct pair { typedef T1 first_type; typedef void second_type; first_type first; enum { second = 0 }; KOKKOS_FORCEINLINE_FUNCTION pair() : first() {} KOKKOS_FORCEINLINE_FUNCTION pair(const first_type & f) : first(f) {} KOKKOS_FORCEINLINE_FUNCTION pair(const first_type & f, int) : first(f) {} template KOKKOS_FORCEINLINE_FUNCTION pair( const pair &p) : first(p.first) {} template KOKKOS_FORCEINLINE_FUNCTION pair & operator=(const pair &p) { first = p.first; return *this; } }; // // Specialization of relational operators for Kokkos::pair. // template KOKKOS_FORCEINLINE_FUNCTION bool operator== (const pair& lhs, const pair& rhs) { return lhs.first==rhs.first; } template KOKKOS_FORCEINLINE_FUNCTION bool operator!= (const pair& lhs, const pair& rhs) { return !(lhs==rhs); } template KOKKOS_FORCEINLINE_FUNCTION bool operator< (const pair& lhs, const pair& rhs) { return lhs.first KOKKOS_FORCEINLINE_FUNCTION bool operator<= (const pair& lhs, const pair& rhs) { return !(rhs KOKKOS_FORCEINLINE_FUNCTION bool operator> (const pair& lhs, const pair& rhs) { return rhs KOKKOS_FORCEINLINE_FUNCTION bool operator>= (const pair& lhs, const pair& rhs) { return !(lhs