diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -253,6 +253,7 @@ set(cuda_wrapper_files cuda_wrappers/algorithm + cuda_wrappers/cmath cuda_wrappers/complex cuda_wrappers/new ) diff --git a/clang/lib/Headers/cuda_wrappers/cmath b/clang/lib/Headers/cuda_wrappers/cmath new file mode 100644 --- /dev/null +++ b/clang/lib/Headers/cuda_wrappers/cmath @@ -0,0 +1,158 @@ +/*===---- cmath - CUDA wrapper for ---------------------------------=== + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + *===-----------------------------------------------------------------------=== + */ + +#ifndef __CLANG_CUDA_WRAPPERS_CMATH +#define __CLANG_CUDA_WRAPPERS_CMATH + +#include_next + +namespace std { + +#if defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER < 14 +__attribute__((device)) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 float __constexpr_fmax(float __x, float __y) _NOEXCEPT { +#if !__has_constexpr_builtin(__builtin_fmaxf) + if (__libcpp_is_constant_evaluated()) { + if (std::__constexpr_isnan(__x)) + return __y; + if (std::__constexpr_isnan(__y)) + return __x; + return __x < __y ? __y : __x; + } +#endif + return __builtin_fmaxf(__x, __y); +} + +__attribute__((device)) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 double __constexpr_fmax(double __x, double __y) _NOEXCEPT { +#if !__has_constexpr_builtin(__builtin_fmax) + if (__libcpp_is_constant_evaluated()) { + if (std::__constexpr_isnan(__x)) + return __y; + if (std::__constexpr_isnan(__y)) + return __x; + return __x < __y ? __y : __x; + } +#endif + return __builtin_fmax(__x, __y); +} + +__attribute__((device)) +inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 long double +__constexpr_fmax(long double __x, long double __y) _NOEXCEPT { +#if !__has_constexpr_builtin(__builtin_fmaxl) + if (__libcpp_is_constant_evaluated()) { + if (std::__constexpr_isnan(__x)) + return __y; + if (std::__constexpr_isnan(__y)) + return __x; + return __x < __y ? __y : __x; + } +#endif + return __builtin_fmaxl(__x, __y); +} + +template ::value && is_arithmetic<_Up>::value, int> = 0> +__attribute__((device)) +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __promote<_Tp, _Up>::type +__constexpr_fmax(_Tp __x, _Up __y) _NOEXCEPT { + using __result_type = typename __promote<_Tp, _Up>::type; + return std::__constexpr_fmax(static_cast<__result_type>(__x), static_cast<__result_type>(__y)); +} + +template +__attribute__((device)) +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __constexpr_logb(_Tp __x) { +#if !__has_constexpr_builtin(__builtin_logb) + if (__libcpp_is_constant_evaluated()) { + if (__x == _Tp(0)) { + // raise FE_DIVBYZERO + return -numeric_limits<_Tp>::infinity(); + } + + if (std::__constexpr_isinf(__x)) + return numeric_limits<_Tp>::infinity(); + + if (std::__constexpr_isnan(__x)) + return numeric_limits<_Tp>::quiet_NaN(); + + __x = std::__constexpr_fabs(__x); + unsigned long long __exp = 0; + while (__x >= numeric_limits<_Tp>::radix) { + __x /= numeric_limits<_Tp>::radix; + __exp += 1; + } + return _Tp(__exp); + } +#endif // !__has_constexpr_builtin(__builtin_logb) + return ::logb(__x); +} + +#endif // pre c++14 + +#if defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER < 20 +template +__attribute__((device)) +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp __constexpr_scalbn(_Tp __x, int __exp) { +#if !__has_constexpr_builtin(__builtin_scalbln) + if (__libcpp_is_constant_evaluated()) { + if (__x == _Tp(0)) + return __x; + + if (std::__constexpr_isinf(__x)) + return __x; + + if (__exp == _Tp(0)) + return __x; + + if (std::__constexpr_isnan(__x)) + return numeric_limits<_Tp>::quiet_NaN(); + + _Tp __mult(1); + if (__exp > 0) { + __mult = numeric_limits<_Tp>::radix; + --__exp; + } else { + ++__exp; + __exp = -__exp; + __mult /= numeric_limits<_Tp>::radix; + } + + while (__exp > 0) { + if (!(__exp & 1)) { + __mult *= __mult; + __exp >>= 1; + } else { + __x *= __mult; + --__exp; + } + } + return __x; + } +#endif // __has_constexpr_builtin(__builtin_scalbln) + return ::scalbn(__x, __exp); +} + +#endif // pre-c++20 +} // namespace std +#endif // include guard