1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef _LIBCPP___MATH_TRAITS_H 10 #define _LIBCPP___MATH_TRAITS_H 11 12 #include <__config> 13 #include <__type_traits/enable_if.h> 14 #include <__type_traits/is_arithmetic.h> 15 #include <__type_traits/is_integral.h> 16 #include <__type_traits/is_signed.h> 17 #include <__type_traits/promote.h> 18 19 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 20 # pragma GCC system_header 21 #endif 22 23 _LIBCPP_BEGIN_NAMESPACE_STD 24 25 namespace __math { 26 27 // signbit 28 29 // TODO(LLVM 22): Remove conditional once support for Clang 19 is dropped. 30 #if defined(_LIBCPP_COMPILER_GCC) || __has_constexpr_builtin(__builtin_signbit) 31 # define _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_CONSTEXPR_SINCE_CXX23 32 #else 33 # define _LIBCPP_SIGNBIT_CONSTEXPR 34 #endif 35 36 // The universal C runtime (UCRT) in the WinSDK provides floating point overloads 37 // for std::signbit(). By defining our overloads as templates, we can work around 38 // this issue as templates are less preferred than non-template functions. 39 template <class = void> 40 [[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT { 41 return __builtin_signbit(__x); 42 } 43 44 template <class = void> 45 [[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT { 46 return __builtin_signbit(__x); 47 } 48 49 template <class = void> 50 [[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT { 51 return __builtin_signbit(__x); 52 } 53 54 template <class _A1, __enable_if_t<is_integral<_A1>::value && is_signed<_A1>::value, int> = 0> 55 [[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { 56 return __x < 0; 57 } 58 59 template <class _A1, __enable_if_t<is_integral<_A1>::value && !is_signed<_A1>::value, int> = 0> 60 [[__nodiscard__]] inline _LIBCPP_SIGNBIT_CONSTEXPR _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { 61 return false; 62 } 63 64 // isfinite 65 66 template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0> 67 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { 68 return true; 69 } 70 71 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(float __x) _NOEXCEPT { 72 return __builtin_isfinite(__x); 73 } 74 75 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(double __x) _NOEXCEPT { 76 return __builtin_isfinite(__x); 77 } 78 79 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(long double __x) _NOEXCEPT { 80 return __builtin_isfinite(__x); 81 } 82 83 // isinf 84 85 template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0> 86 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { 87 return false; 88 } 89 90 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { 91 return __builtin_isinf(__x); 92 } 93 94 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI 95 #ifdef _LIBCPP_PREFERRED_OVERLOAD 96 _LIBCPP_PREFERRED_OVERLOAD 97 #endif 98 bool 99 isinf(double __x) _NOEXCEPT { 100 return __builtin_isinf(__x); 101 } 102 103 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { 104 return __builtin_isinf(__x); 105 } 106 107 // isnan 108 109 template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0> 110 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { 111 return false; 112 } 113 114 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { 115 return __builtin_isnan(__x); 116 } 117 118 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI 119 #ifdef _LIBCPP_PREFERRED_OVERLOAD 120 _LIBCPP_PREFERRED_OVERLOAD 121 #endif 122 bool 123 isnan(double __x) _NOEXCEPT { 124 return __builtin_isnan(__x); 125 } 126 127 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { 128 return __builtin_isnan(__x); 129 } 130 131 // isnormal 132 133 template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0> 134 [[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { 135 return __x != 0; 136 } 137 138 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(float __x) _NOEXCEPT { 139 return __builtin_isnormal(__x); 140 } 141 142 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(double __x) _NOEXCEPT { 143 return __builtin_isnormal(__x); 144 } 145 146 [[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(long double __x) _NOEXCEPT { 147 return __builtin_isnormal(__x); 148 } 149 150 // isgreater 151 152 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> 153 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { 154 using type = typename __promote<_A1, _A2>::type; 155 return __builtin_isgreater((type)__x, (type)__y); 156 } 157 158 // isgreaterequal 159 160 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> 161 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { 162 using type = typename __promote<_A1, _A2>::type; 163 return __builtin_isgreaterequal((type)__x, (type)__y); 164 } 165 166 // isless 167 168 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> 169 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { 170 using type = typename __promote<_A1, _A2>::type; 171 return __builtin_isless((type)__x, (type)__y); 172 } 173 174 // islessequal 175 176 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> 177 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { 178 using type = typename __promote<_A1, _A2>::type; 179 return __builtin_islessequal((type)__x, (type)__y); 180 } 181 182 // islessgreater 183 184 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> 185 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { 186 using type = typename __promote<_A1, _A2>::type; 187 return __builtin_islessgreater((type)__x, (type)__y); 188 } 189 190 // isunordered 191 192 template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> 193 [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { 194 using type = typename __promote<_A1, _A2>::type; 195 return __builtin_isunordered((type)__x, (type)__y); 196 } 197 198 } // namespace __math 199 200 _LIBCPP_END_NAMESPACE_STD 201 202 #endif // _LIBCPP___MATH_TRAITS_H 203