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