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_floating_point.h> |
16 | #include <__type_traits/is_integral.h> |
17 | #include <__type_traits/is_signed.h> |
18 | #include <__type_traits/promote.h> |
19 | #include <limits> |
20 | |
21 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
22 | # pragma GCC system_header |
23 | #endif |
24 | |
25 | _LIBCPP_BEGIN_NAMESPACE_STD |
26 | |
27 | namespace __math { |
28 | |
29 | // signbit |
30 | |
31 | template <class _A1, __enable_if_t<is_floating_point<_A1>::value, int> = 0> |
32 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { |
33 | return __builtin_signbit(__x); |
34 | } |
35 | |
36 | template <class _A1, __enable_if_t<is_integral<_A1>::value && is_signed<_A1>::value, int> = 0> |
37 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1 __x) _NOEXCEPT { |
38 | return __x < 0; |
39 | } |
40 | |
41 | template <class _A1, __enable_if_t<is_integral<_A1>::value && !is_signed<_A1>::value, int> = 0> |
42 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool signbit(_A1) _NOEXCEPT { |
43 | return false; |
44 | } |
45 | |
46 | // isfinite |
47 | |
48 | template <class _A1, __enable_if_t<is_arithmetic<_A1>::value && numeric_limits<_A1>::has_infinity, int> = 0> |
49 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT { |
50 | return __builtin_isfinite((typename __promote<_A1>::type)__x); |
51 | } |
52 | |
53 | template <class _A1, __enable_if_t<is_arithmetic<_A1>::value && !numeric_limits<_A1>::has_infinity, int> = 0> |
54 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT { |
55 | return true; |
56 | } |
57 | |
58 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(float __x) _NOEXCEPT { |
59 | return __builtin_isfinite(__x); |
60 | } |
61 | |
62 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(double __x) _NOEXCEPT { |
63 | return __builtin_isfinite(__x); |
64 | } |
65 | |
66 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(long double __x) _NOEXCEPT { |
67 | return __builtin_isfinite(__x); |
68 | } |
69 | |
70 | // isinf |
71 | |
72 | template <class _A1, __enable_if_t<is_arithmetic<_A1>::value && numeric_limits<_A1>::has_infinity, int> = 0> |
73 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT { |
74 | return __builtin_isinf((typename __promote<_A1>::type)__x); |
75 | } |
76 | |
77 | template <class _A1, __enable_if_t<is_arithmetic<_A1>::value && !numeric_limits<_A1>::has_infinity, int> = 0> |
78 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1) _NOEXCEPT { |
79 | return false; |
80 | } |
81 | |
82 | #ifdef _LIBCPP_PREFERRED_OVERLOAD |
83 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { |
84 | return __builtin_isinf(__x); |
85 | } |
86 | |
87 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool |
88 | isinf(double __x) _NOEXCEPT { |
89 | return __builtin_isinf(__x); |
90 | } |
91 | |
92 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { |
93 | return __builtin_isinf(__x); |
94 | } |
95 | #endif |
96 | |
97 | // isnan |
98 | |
99 | template <class _A1, __enable_if_t<is_floating_point<_A1>::value, int> = 0> |
100 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT { |
101 | return __builtin_isnan(__x); |
102 | } |
103 | |
104 | template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0> |
105 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT { |
106 | return false; |
107 | } |
108 | |
109 | #ifdef _LIBCPP_PREFERRED_OVERLOAD |
110 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { |
111 | return __builtin_isnan(__x); |
112 | } |
113 | |
114 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool |
115 | isnan(double __x) _NOEXCEPT { |
116 | return __builtin_isnan(__x); |
117 | } |
118 | |
119 | _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { |
120 | return __builtin_isnan(__x); |
121 | } |
122 | #endif |
123 | |
124 | // isnormal |
125 | |
126 | template <class _A1, __enable_if_t<is_floating_point<_A1>::value, int> = 0> |
127 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { |
128 | return __builtin_isnormal(__x); |
129 | } |
130 | |
131 | template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0> |
132 | _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT { |
133 | return __x != 0; |
134 | } |
135 | |
136 | // isgreater |
137 | |
138 | template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> |
139 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreater(_A1 __x, _A2 __y) _NOEXCEPT { |
140 | using type = typename __promote<_A1, _A2>::type; |
141 | return __builtin_isgreater((type)__x, (type)__y); |
142 | } |
143 | |
144 | // isgreaterequal |
145 | |
146 | template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> |
147 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isgreaterequal(_A1 __x, _A2 __y) _NOEXCEPT { |
148 | using type = typename __promote<_A1, _A2>::type; |
149 | return __builtin_isgreaterequal((type)__x, (type)__y); |
150 | } |
151 | |
152 | // isless |
153 | |
154 | template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> |
155 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isless(_A1 __x, _A2 __y) _NOEXCEPT { |
156 | using type = typename __promote<_A1, _A2>::type; |
157 | return __builtin_isless((type)__x, (type)__y); |
158 | } |
159 | |
160 | // islessequal |
161 | |
162 | template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> |
163 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessequal(_A1 __x, _A2 __y) _NOEXCEPT { |
164 | using type = typename __promote<_A1, _A2>::type; |
165 | return __builtin_islessequal((type)__x, (type)__y); |
166 | } |
167 | |
168 | // islessgreater |
169 | |
170 | template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> |
171 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool islessgreater(_A1 __x, _A2 __y) _NOEXCEPT { |
172 | using type = typename __promote<_A1, _A2>::type; |
173 | return __builtin_islessgreater((type)__x, (type)__y); |
174 | } |
175 | |
176 | // isunordered |
177 | |
178 | template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0> |
179 | _LIBCPP_NODISCARD inline _LIBCPP_HIDE_FROM_ABI bool isunordered(_A1 __x, _A2 __y) _NOEXCEPT { |
180 | using type = typename __promote<_A1, _A2>::type; |
181 | return __builtin_isunordered((type)__x, (type)__y); |
182 | } |
183 | |
184 | } // namespace __math |
185 | |
186 | _LIBCPP_END_NAMESPACE_STD |
187 | |
188 | #endif // _LIBCPP___MATH_TRAITS_H |
189 | |