266 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef _LIBCPP___MATH_TRAITS_H10#define _LIBCPP___MATH_TRAITS_H11 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/promote.h>17 18#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)19# pragma GCC system_header20#endif21 22_LIBCPP_BEGIN_NAMESPACE_STD23 24namespace __math {25 26// signbit27 28// The universal C runtime (UCRT) in the WinSDK provides floating point overloads29// for std::signbit(). By defining our overloads as templates, we can work around30// this issue as templates are less preferred than non-template functions.31template <class = void>32[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(float __x) _NOEXCEPT {33 return __builtin_signbit(__x);34}35 36template <class = void>37[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(double __x) _NOEXCEPT {38 return __builtin_signbit(__x);39}40 41template <class = void>42[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(long double __x) _NOEXCEPT {43 return __builtin_signbit(__x);44}45 46template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>47[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT {48 return __x < 0;49}50 51// isfinite52 53template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>54[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT {55 return true;56}57 58[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(float __x) _NOEXCEPT {59 return __builtin_isfinite(__x);60}61 62[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(double __x) _NOEXCEPT {63 return __builtin_isfinite(__x);64}65 66[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(long double __x) _NOEXCEPT {67 return __builtin_isfinite(__x);68}69 70// isinf71 72template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>73[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT {74 return false;75}76 77[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT {78 return __builtin_isinf(__x);79}80 81[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI82#ifdef _LIBCPP_PREFERRED_OVERLOAD83_LIBCPP_PREFERRED_OVERLOAD84#endif85 bool86 isinf(double __x) _NOEXCEPT {87 return __builtin_isinf(__x);88}89 90[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT {91 return __builtin_isinf(__x);92}93 94// isnan95 96template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>97[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT {98 return false;99}100 101[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT {102 return __builtin_isnan(__x);103}104 105[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI106#ifdef _LIBCPP_PREFERRED_OVERLOAD107_LIBCPP_PREFERRED_OVERLOAD108#endif109 bool110 isnan(double __x) _NOEXCEPT {111 return __builtin_isnan(__x);112}113 114[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT {115 return __builtin_isnan(__x);116}117 118// isnormal119 120template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>121[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {122 return __x != 0;123}124 125[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(float __x) _NOEXCEPT {126 return __builtin_isnormal(__x);127}128 129[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(double __x) _NOEXCEPT {130 return __builtin_isnormal(__x);131}132 133[[__nodiscard__]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(long double __x) _NOEXCEPT {134 return __builtin_isnormal(__x);135}136 137// isgreater138 139template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>140[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT {141 using type = __promote_t<_A1, _A2>;142 return __builtin_isgreater((type)__x, (type)__y);143}144 145// isgreaterequal146 147template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>148[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT {149 using type = __promote_t<_A1, _A2>;150 return __builtin_isgreaterequal((type)__x, (type)__y);151}152 153// isless154 155template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>156[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT {157 using type = __promote_t<_A1, _A2>;158 return __builtin_isless((type)__x, (type)__y);159}160 161// islessequal162 163template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>164[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT {165 using type = __promote_t<_A1, _A2>;166 return __builtin_islessequal((type)__x, (type)__y);167}168 169// islessgreater170 171template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>172[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT {173 using type = __promote_t<_A1, _A2>;174 return __builtin_islessgreater((type)__x, (type)__y);175}176 177// isunordered178 179template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>180[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT {181 using type = __promote_t<_A1, _A2>;182 return __builtin_isunordered((type)__x, (type)__y);183}184 185// MS UCRT incorrectly defines some functions in a way not working with integer types. Until C++20, this was worked186// around by -fdelayed-template-parsing. Since C++20, we can use standard feature "requires" instead.187 188// TODO: Remove the workaround once UCRT fixes these functions. Note that this doesn't seem planned as of 2025-07 per189// https://developercommunity.visualstudio.com/t/10294165.190 191#if defined(_LIBCPP_MSVCRT) && _LIBCPP_STD_VER >= 20192namespace __ucrt {193template <class _A1>194 requires is_integral_v<_A1>195[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) noexcept {196 return true;197}198 199template <class _A1>200 requires is_integral_v<_A1>201[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) noexcept {202 return false;203}204 205template <class _A1>206 requires is_integral_v<_A1>207[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) noexcept {208 return false;209}210 211template <class _A1>212 requires is_integral_v<_A1>213[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) noexcept {214 return __x != 0;215}216 217template <class _A1, class _A2>218 requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>219[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) noexcept {220 using type = __promote_t<_A1, _A2>;221 return __builtin_isgreater((type)__x, (type)__y);222}223 224template <class _A1, class _A2>225 requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>226[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) noexcept {227 using type = __promote_t<_A1, _A2>;228 return __builtin_isgreaterequal((type)__x, (type)__y);229}230 231template <class _A1, class _A2>232 requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>233[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) noexcept {234 using type = __promote_t<_A1, _A2>;235 return __builtin_isless((type)__x, (type)__y);236}237 238template <class _A1, class _A2>239 requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>240[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) noexcept {241 using type = __promote_t<_A1, _A2>;242 return __builtin_islessequal((type)__x, (type)__y);243}244 245template <class _A1, class _A2>246 requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>247[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) noexcept {248 using type = __promote_t<_A1, _A2>;249 return __builtin_islessgreater((type)__x, (type)__y);250}251 252template <class _A1, class _A2>253 requires is_arithmetic_v<_A1> && is_arithmetic_v<_A2>254[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) noexcept {255 using type = __promote_t<_A1, _A2>;256 return __builtin_isunordered((type)__x, (type)__y);257}258} // namespace __ucrt259#endif260 261} // namespace __math262 263_LIBCPP_END_NAMESPACE_STD264 265#endif // _LIBCPP___MATH_TRAITS_H266