//@HEADER // ************************************************************************ // // Kokkos v. 4.0 // Copyright (2022) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. // See https://kokkos.org/LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //@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 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE #define KOKKOS_IMPL_PUBLIC_INCLUDE #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_PAIR #endif #include #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. using first_type = T1; //! The second template parameter of this class. using second_type = T2; //! 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_DEFAULTED_FUNCTION constexpr pair() = default; /// \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. #if defined(KOKKOS_COMPILER_NVHPC) && KOKKOS_COMPILER_NVHPC < 230700 KOKKOS_FORCEINLINE_FUNCTION #else KOKKOS_FORCEINLINE_FUNCTION constexpr #endif 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 #if defined(KOKKOS_COMPILER_NVHPC) && KOKKOS_COMPILER_NVHPC < 230700 KOKKOS_FORCEINLINE_FUNCTION #else KOKKOS_FORCEINLINE_FUNCTION constexpr #endif pair(const pair& p) : first(p.first), second(p.second) { } #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4 /// \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_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr pair( const volatile pair& p) : first(p.first), second(p.second) {} #endif /// \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; } #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4 /// \brief Assignment operator, for volatile *this. /// /// \param p [in] Input; right-hand side of the assignment. /// /// This calls the assignment operators of T1 and T2. It will not /// compile if the assignment operators are not defined and public. /// /// This operator returns \c void instead of volatile pair& . See Kokkos Issue #177 for the explanation. In /// practice, this means that you should not chain assignments with /// volatile lvalues. template KOKKOS_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION void operator=( const volatile pair& p) volatile { first = p.first; second = p.second; // We deliberately do not return anything here. See explanation // in public documentation above. } #endif // 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. using first_type = T1&; //! The second template parameter of this class. using second_type = T2&; //! 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 constexpr 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 constexpr 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. using first_type = T1; //! The second template parameter of this class. using second_type = T2&; //! 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 constexpr 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 constexpr 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. using first_type = T1&; //! The second template parameter of this class. using second_type = T2; //! 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 constexpr 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 constexpr 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 constexpr 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 constexpr bool operator!=(const pair& lhs, const pair& rhs) { return !(lhs == rhs); } //! Less-than operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator<(const pair& lhs, const pair& rhs) { return lhs.first < rhs.first || (!(rhs.first < lhs.first) && lhs.second < rhs.second); } //! Less-than-or-equal-to operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator<=(const pair& lhs, const pair& rhs) { return !(rhs < lhs); } //! Greater-than operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator>(const pair& lhs, const pair& rhs) { return rhs < lhs; } //! Greater-than-or-equal-to operator for Kokkos::pair. template KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator>=(const pair& lhs, const pair& rhs) { return !(lhs < rhs); } /// \brief Return a new pair. /// /// This is a "nonmember constructor" for Kokkos::pair. It works just /// like std::make_pair. template KOKKOS_FORCEINLINE_FUNCTION constexpr 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)); } #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4 // // 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 KOKKOS_DEPRECATED pair { using first_type = T1; using second_type = void; first_type first; enum { second = 0 }; KOKKOS_DEFAULTED_FUNCTION constexpr pair() = default; KOKKOS_FORCEINLINE_FUNCTION constexpr pair(const first_type& f) : first(f) {} KOKKOS_FORCEINLINE_FUNCTION constexpr pair(const first_type& f, int) : first(f) {} template KOKKOS_FORCEINLINE_FUNCTION constexpr 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_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator==( const pair& lhs, const pair& rhs) { return lhs.first == rhs.first; } template KOKKOS_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator!=( const pair& lhs, const pair& rhs) { return !(lhs == rhs); } template KOKKOS_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator<( const pair& lhs, const pair& rhs) { return lhs.first < rhs.first; } template KOKKOS_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator<=( const pair& lhs, const pair& rhs) { return !(rhs < lhs); } template KOKKOS_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator>( const pair& lhs, const pair& rhs) { return rhs < lhs; } template KOKKOS_DEPRECATED KOKKOS_FORCEINLINE_FUNCTION constexpr bool operator>=( const pair& lhs, const pair& rhs) { return !(lhs < rhs); } #endif namespace Impl { template struct is_pair_like : std::false_type {}; template struct is_pair_like> : std::true_type {}; template struct is_pair_like> : std::true_type {}; } // end namespace Impl } // namespace Kokkos #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_PAIR #undef KOKKOS_IMPL_PUBLIC_INCLUDE #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_PAIR #endif #endif // KOKKOS_PAIR_HPP