1*a9ac8606Spatrick/*===---- algorithm - CUDA wrapper for <algorithm> -------------------------=== 2e5dd7070Spatrick * 3e5dd7070Spatrick * Permission is hereby granted, free of charge, to any person obtaining a copy 4e5dd7070Spatrick * of this software and associated documentation files (the "Software"), to deal 5e5dd7070Spatrick * in the Software without restriction, including without limitation the rights 6e5dd7070Spatrick * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7e5dd7070Spatrick * copies of the Software, and to permit persons to whom the Software is 8e5dd7070Spatrick * furnished to do so, subject to the following conditions: 9e5dd7070Spatrick * 10e5dd7070Spatrick * The above copyright notice and this permission notice shall be included in 11e5dd7070Spatrick * all copies or substantial portions of the Software. 12e5dd7070Spatrick * 13e5dd7070Spatrick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14e5dd7070Spatrick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15e5dd7070Spatrick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16e5dd7070Spatrick * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17e5dd7070Spatrick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18e5dd7070Spatrick * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19e5dd7070Spatrick * THE SOFTWARE. 20e5dd7070Spatrick * 21e5dd7070Spatrick *===-----------------------------------------------------------------------=== 22e5dd7070Spatrick */ 23e5dd7070Spatrick 24e5dd7070Spatrick#ifndef __CLANG_CUDA_WRAPPERS_ALGORITHM 25e5dd7070Spatrick#define __CLANG_CUDA_WRAPPERS_ALGORITHM 26e5dd7070Spatrick 27e5dd7070Spatrick// This header defines __device__ overloads of std::min/max. 28e5dd7070Spatrick// 29e5dd7070Spatrick// Ideally we'd declare these functions only if we're <= C++11. In C++14, 30e5dd7070Spatrick// these functions are constexpr, and so are implicitly __host__ __device__. 31e5dd7070Spatrick// 32e5dd7070Spatrick// However, the compiler being in C++14 mode does not imply that the standard 33e5dd7070Spatrick// library supports C++14. There is no macro we can test to check that the 34e5dd7070Spatrick// stdlib has constexpr std::min/max. Thus we have to unconditionally define 35e5dd7070Spatrick// our device overloads. 36e5dd7070Spatrick// 37e5dd7070Spatrick// A host+device function cannot be overloaded, and a constexpr function 38e5dd7070Spatrick// implicitly become host device if there's no explicitly host or device 39e5dd7070Spatrick// overload preceding it. So the simple thing to do would be to declare our 40e5dd7070Spatrick// device min/max overloads, and then #include_next <algorithm>. This way our 41e5dd7070Spatrick// device overloads would come first, and so if we have a C++14 stdlib, its 42e5dd7070Spatrick// min/max won't become host+device and conflict with our device overloads. 43e5dd7070Spatrick// 44e5dd7070Spatrick// But that also doesn't work. libstdc++ is evil and declares std::min/max in 45e5dd7070Spatrick// an internal header that is included *before* <algorithm>. Thus by the time 46e5dd7070Spatrick// we're inside of this file, std::min/max may already have been declared, and 47e5dd7070Spatrick// thus we can't prevent them from becoming host+device if they're constexpr. 48e5dd7070Spatrick// 49e5dd7070Spatrick// Therefore we perpetrate the following hack: We mark our __device__ overloads 50e5dd7070Spatrick// with __attribute__((enable_if(true, ""))). This causes the signature of the 51e5dd7070Spatrick// function to change without changing anything else about it. (Except that 52e5dd7070Spatrick// overload resolution will prefer it over the __host__ __device__ version 53e5dd7070Spatrick// rather than considering them equally good). 54e5dd7070Spatrick 55e5dd7070Spatrick#include_next <algorithm> 56e5dd7070Spatrick 57e5dd7070Spatrick// We need to define these overloads in exactly the namespace our standard 58e5dd7070Spatrick// library uses (including the right inline namespace), otherwise they won't be 59e5dd7070Spatrick// picked up by other functions in the standard library (e.g. functions in 60e5dd7070Spatrick// <complex>). Thus the ugliness below. 61e5dd7070Spatrick#ifdef _LIBCPP_BEGIN_NAMESPACE_STD 62e5dd7070Spatrick_LIBCPP_BEGIN_NAMESPACE_STD 63e5dd7070Spatrick#else 64e5dd7070Spatricknamespace std { 65e5dd7070Spatrick#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION 66e5dd7070Spatrick_GLIBCXX_BEGIN_NAMESPACE_VERSION 67e5dd7070Spatrick#endif 68e5dd7070Spatrick#endif 69e5dd7070Spatrick 70e5dd7070Spatrick#pragma push_macro("_CPP14_CONSTEXPR") 71e5dd7070Spatrick#if __cplusplus >= 201402L 72e5dd7070Spatrick#define _CPP14_CONSTEXPR constexpr 73e5dd7070Spatrick#else 74e5dd7070Spatrick#define _CPP14_CONSTEXPR 75e5dd7070Spatrick#endif 76e5dd7070Spatrick 77e5dd7070Spatricktemplate <class __T, class __Cmp> 78e5dd7070Spatrick__attribute__((enable_if(true, ""))) 79e5dd7070Spatrickinline _CPP14_CONSTEXPR __host__ __device__ const __T & 80e5dd7070Spatrickmax(const __T &__a, const __T &__b, __Cmp __cmp) { 81e5dd7070Spatrick return __cmp(__a, __b) ? __b : __a; 82e5dd7070Spatrick} 83e5dd7070Spatrick 84e5dd7070Spatricktemplate <class __T> 85e5dd7070Spatrick__attribute__((enable_if(true, ""))) 86e5dd7070Spatrickinline _CPP14_CONSTEXPR __host__ __device__ const __T & 87e5dd7070Spatrickmax(const __T &__a, const __T &__b) { 88e5dd7070Spatrick return __a < __b ? __b : __a; 89e5dd7070Spatrick} 90e5dd7070Spatrick 91e5dd7070Spatricktemplate <class __T, class __Cmp> 92e5dd7070Spatrick__attribute__((enable_if(true, ""))) 93e5dd7070Spatrickinline _CPP14_CONSTEXPR __host__ __device__ const __T & 94e5dd7070Spatrickmin(const __T &__a, const __T &__b, __Cmp __cmp) { 95e5dd7070Spatrick return __cmp(__b, __a) ? __b : __a; 96e5dd7070Spatrick} 97e5dd7070Spatrick 98e5dd7070Spatricktemplate <class __T> 99e5dd7070Spatrick__attribute__((enable_if(true, ""))) 100e5dd7070Spatrickinline _CPP14_CONSTEXPR __host__ __device__ const __T & 101e5dd7070Spatrickmin(const __T &__a, const __T &__b) { 102e5dd7070Spatrick return __a < __b ? __a : __b; 103e5dd7070Spatrick} 104e5dd7070Spatrick 105e5dd7070Spatrick#pragma pop_macro("_CPP14_CONSTEXPR") 106e5dd7070Spatrick 107e5dd7070Spatrick#ifdef _LIBCPP_END_NAMESPACE_STD 108e5dd7070Spatrick_LIBCPP_END_NAMESPACE_STD 109e5dd7070Spatrick#else 110e5dd7070Spatrick#ifdef _GLIBCXX_BEGIN_NAMESPACE_VERSION 111e5dd7070Spatrick_GLIBCXX_END_NAMESPACE_VERSION 112e5dd7070Spatrick#endif 113e5dd7070Spatrick} // namespace std 114e5dd7070Spatrick#endif 115e5dd7070Spatrick 116e5dd7070Spatrick#endif // __CLANG_CUDA_WRAPPERS_ALGORITHM 117