25 #ifndef _GLIBCXX_EXPERIMENTAL_SIMD_MATH_H_ 26 #define _GLIBCXX_EXPERIMENTAL_SIMD_MATH_H_ 28 #if __cplusplus >= 201703L 33 _GLIBCXX_SIMD_BEGIN_NAMESPACE
34 template <
typename _Tp,
typename _V>
35 using _Samesize = fixed_size_simd<_Tp, _V::size()>;
38 template <
typename _DoubleR,
typename _Tp,
typename _Abi>
39 struct _Math_return_type;
41 template <
typename _DoubleR,
typename _Tp,
typename _Abi>
42 using _Math_return_type_t =
43 typename _Math_return_type<_DoubleR, _Tp, _Abi>::type;
45 template <
typename _Tp,
typename _Abi>
46 struct _Math_return_type<double, _Tp, _Abi>
47 {
using type = simd<_Tp, _Abi>; };
49 template <
typename _Tp,
typename _Abi>
50 struct _Math_return_type<bool, _Tp, _Abi>
51 {
using type = simd_mask<_Tp, _Abi>; };
53 template <
typename _DoubleR,
typename _Tp,
typename _Abi>
54 struct _Math_return_type
55 {
using type = fixed_size_simd<_DoubleR, simd_size_v<_Tp, _Abi>>; };
59 #define _GLIBCXX_SIMD_MATH_CALL_(__name) \ 60 template <typename _Tp, typename _Abi, typename..., \ 61 typename _R = _Math_return_type_t< \ 62 decltype(std::__name(declval<double>())), _Tp, _Abi>> \ 63 _GLIBCXX_SIMD_ALWAYS_INLINE \ 64 enable_if_t<is_floating_point_v<_Tp>, _R> \ 65 __name(simd<_Tp, _Abi> __x) \ 66 { return {__private_init, _Abi::_SimdImpl::_S_##__name(__data(__x))}; } 70 template <
typename _Up,
typename _Tp,
typename _Abi>
71 struct _Extra_argument_type;
73 template <
typename _Tp,
typename _Abi>
74 struct _Extra_argument_type<_Tp*, _Tp, _Abi>
76 using type = simd<_Tp, _Abi>*;
77 static constexpr
double*
declval();
78 static constexpr
bool __needs_temporary_scalar =
true;
80 _GLIBCXX_SIMD_INTRINSIC
static constexpr
auto _S_data(type __x)
81 {
return &__data(*__x); }
84 template <
typename _Up,
typename _Tp,
typename _Abi>
85 struct _Extra_argument_type<_Up*, _Tp, _Abi>
87 static_assert(is_integral_v<_Up>);
88 using type = fixed_size_simd<_Up, simd_size_v<_Tp, _Abi>>*;
89 static constexpr _Up*
declval();
90 static constexpr
bool __needs_temporary_scalar =
true;
92 _GLIBCXX_SIMD_INTRINSIC
static constexpr
auto _S_data(type __x)
93 {
return &__data(*__x); }
96 template <
typename _Tp,
typename _Abi>
97 struct _Extra_argument_type<_Tp, _Tp, _Abi>
99 using type = simd<_Tp, _Abi>;
100 static constexpr
double declval();
101 static constexpr
bool __needs_temporary_scalar =
false;
103 _GLIBCXX_SIMD_INTRINSIC
static constexpr decltype(
auto)
104 _S_data(const type& __x)
105 {
return __data(__x); }
108 template <
typename _Up,
typename _Tp,
typename _Abi>
109 struct _Extra_argument_type
111 static_assert(is_integral_v<_Up>);
112 using type = fixed_size_simd<_Up, simd_size_v<_Tp, _Abi>>;
113 static constexpr _Up
declval();
114 static constexpr
bool __needs_temporary_scalar =
false;
116 _GLIBCXX_SIMD_INTRINSIC
static constexpr decltype(
auto)
117 _S_data(const type& __x)
118 {
return __data(__x); }
123 #define _GLIBCXX_SIMD_MATH_CALL2_(__name, __arg2) \ 125 typename _Tp, typename _Abi, typename..., \ 126 typename _Arg2 = _Extra_argument_type<__arg2, _Tp, _Abi>, \ 127 typename _R = _Math_return_type_t< \ 128 decltype(std::__name(declval<double>(), _Arg2::declval())), _Tp, _Abi>> \ 129 _GLIBCXX_SIMD_ALWAYS_INLINE \ 130 enable_if_t<is_floating_point_v<_Tp>, _R> \ 131 __name(const simd<_Tp, _Abi>& __x, const typename _Arg2::type& __y) \ 133 return {__private_init, \ 134 _Abi::_SimdImpl::_S_##__name(__data(__x), _Arg2::_S_data(__y))}; \ 136 template <typename _Up, typename _Tp, typename _Abi> \ 137 _GLIBCXX_SIMD_INTRINSIC _Math_return_type_t< \ 138 decltype(std::__name( \ 140 declval<enable_if_t< \ 142 is_same<__arg2, _Tp>, \ 143 negation<is_same<__remove_cvref_t<_Up>, simd<_Tp, _Abi>>>, \ 144 is_convertible<_Up, simd<_Tp, _Abi>>, is_floating_point<_Tp>>, \ 147 __name(_Up&& __xx, const simd<_Tp, _Abi>& __yy) \ 148 { return __name(simd<_Tp, _Abi>(static_cast<_Up&&>(__xx)), __yy); } 152 #define _GLIBCXX_SIMD_MATH_CALL3_(__name, __arg2, __arg3) \ 153 template <typename _Tp, typename _Abi, typename..., \ 154 typename _Arg2 = _Extra_argument_type<__arg2, _Tp, _Abi>, \ 155 typename _Arg3 = _Extra_argument_type<__arg3, _Tp, _Abi>, \ 156 typename _R = _Math_return_type_t< \ 157 decltype(std::__name(declval<double>(), _Arg2::declval(), \ 158 _Arg3::declval())), \ 160 _GLIBCXX_SIMD_ALWAYS_INLINE \ 161 enable_if_t<is_floating_point_v<_Tp>, _R> \ 162 __name(const simd<_Tp, _Abi>& __x, const typename _Arg2::type& __y, \ 163 const typename _Arg3::type& __z) \ 165 return {__private_init, \ 166 _Abi::_SimdImpl::_S_##__name(__data(__x), _Arg2::_S_data(__y), \ 167 _Arg3::_S_data(__z))}; \ 170 typename _T0, typename _T1, typename _T2, typename..., \ 171 typename _U0 = __remove_cvref_t<_T0>, \ 172 typename _U1 = __remove_cvref_t<_T1>, \ 173 typename _U2 = __remove_cvref_t<_T2>, \ 174 typename _Simd = conditional_t<is_simd_v<_U1>, _U1, _U2>, \ 175 typename = enable_if_t<conjunction_v< \ 176 is_simd<_Simd>, is_convertible<_T0&&, _Simd>, \ 177 is_convertible<_T1&&, _Simd>, is_convertible<_T2&&, _Simd>, \ 178 negation<conjunction< \ 179 is_simd<_U0>, is_floating_point<__value_type_or_identity_t<_U0>>>>>>> \ 180 _GLIBCXX_SIMD_INTRINSIC decltype(__name(declval<const _Simd&>(), \ 181 declval<const _Simd&>(), \ 182 declval<const _Simd&>())) \ 183 __name(_T0&& __xx, _T1&& __yy, _T2&& __zz) \ 185 return __name(_Simd(static_cast<_T0&&>(__xx)), \ 186 _Simd(static_cast<_T1&&>(__yy)), \ 187 _Simd(static_cast<_T2&&>(__zz))); \ 192 template <
typename _Abi>
193 _GLIBCXX_SIMD_ALWAYS_INLINE
static simd<float, _Abi>
194 __cosSeries(
const simd<float, _Abi>& __x)
196 const simd<float, _Abi> __x2 = __x * __x;
197 simd<float, _Abi> __y;
199 __y = __y * __x2 - 0x1.6c1p-10f;
200 __y = __y * __x2 + 0x1.555556p-5f;
201 return __y * (__x2 * __x2) - .5f * __x2 + 1.f;
204 template <
typename _Abi>
205 _GLIBCXX_SIMD_ALWAYS_INLINE
static simd<double, _Abi>
206 __cosSeries(
const simd<double, _Abi>& __x)
208 const simd<double, _Abi> __x2 = __x * __x;
209 simd<double, _Abi> __y;
210 __y = 0x1.AC00000000000p-45;
211 __y = __y * __x2 - 0x1.9394000000000p-37;
212 __y = __y * __x2 + 0x1.1EED8C0000000p-29;
213 __y = __y * __x2 - 0x1.27E4FB7400000p-22;
214 __y = __y * __x2 + 0x1.A01A01A018000p-16;
215 __y = __y * __x2 - 0x1.6C16C16C16C00p-10;
216 __y = __y * __x2 + 0x1.5555555555554p-5;
217 return (__y * __x2 - .5f) * __x2 + 1.f;
222 template <
typename _Abi>
223 _GLIBCXX_SIMD_ALWAYS_INLINE
static simd<float, _Abi>
224 __sinSeries(
const simd<float, _Abi>& __x)
226 const simd<float, _Abi> __x2 = __x * __x;
227 simd<float, _Abi> __y;
228 __y = -0x1.9CC000p-13f;
229 __y = __y * __x2 + 0x1.111100p-7f;
230 __y = __y * __x2 - 0x1.555556p-3f;
231 return __y * (__x2 * __x) + __x;
234 template <
typename _Abi>
235 _GLIBCXX_SIMD_ALWAYS_INLINE
static simd<double, _Abi>
236 __sinSeries(
const simd<double, _Abi>& __x)
240 const simd<double, _Abi> __x2 = __x * __x;
241 simd<double, _Abi> __y;
242 __y = -0x1.ACF0000000000p-41;
243 __y = __y * __x2 + 0x1.6124400000000p-33;
244 __y = __y * __x2 - 0x1.AE64567000000p-26;
245 __y = __y * __x2 + 0x1.71DE3A5540000p-19;
246 __y = __y * __x2 - 0x1.A01A01A01A000p-13;
247 __y = __y * __x2 + 0x1.1111111111110p-7;
248 __y = __y * __x2 - 0x1.5555555555555p-3;
249 return __y * (__x2 * __x) + __x;
254 template <
int _Bits,
typename _Tp,
typename _Abi>
255 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi>
256 __zero_low_bits(simd<_Tp, _Abi> __x)
258 const simd<_Tp, _Abi> __bitmask
259 = __bit_cast<_Tp>(~make_unsigned_t<__int_for_sizeof_t<_Tp>>() << _Bits);
260 return {__private_init,
261 _Abi::_SimdImpl::_S_bit_and(__data(__x), __data(__bitmask))};
285 template <
typename _Tp,
typename _Abi>
288 simd<_Tp, _Abi> _M_x;
289 rebind_simd_t<int, simd<_Tp, _Abi>> _M_quadrant;
293 inline constexpr
float __pi_over_4 = 0x1.921FB6p-1f;
294 inline constexpr
float __2_over_pi = 0x1.45F306p-1f;
295 inline constexpr
float __pi_2_5bits0
297 inline constexpr
float __pi_2_5bits0_rem
301 inline constexpr
double __pi_over_4 = 0x1.921fb54442d18p-1;
302 inline constexpr
double __2_over_pi = 0x1.45F306DC9C883p-1;
303 inline constexpr
double __pi_2 = 0x1.921fb54442d18p0;
306 template <
typename _Abi>
307 _GLIBCXX_SIMD_ALWAYS_INLINE _Folded<float, _Abi>
308 __fold_input(
const simd<float, _Abi>& __x)
310 using _V = simd<float, _Abi>;
311 using _IV = rebind_simd_t<int, _V>;
313 _Folded<float, _Abi> __r;
317 constexpr
float __1_over_pi = 0x1.45F306p-2f;
318 const auto __y = (__r._M_x * __1_over_pi + 0x1.8p23f) - 0x1.8p23f;
321 constexpr
float __pi0 = 0x1.920000p1f;
322 constexpr
float __pi1 = 0x1.fb4000p-11f;
323 constexpr
float __pi2 = 0x1.444000p-23f;
324 constexpr
float __pi3 = 0x1.68c234p-38f;
325 __r._M_x - __y*__pi0 - __y*__pi1 - __y*__pi2 - __y*__pi3
327 if (_GLIBCXX_SIMD_IS_UNLIKELY(all_of(__r._M_x < __pi_over_4)))
329 else if (_GLIBCXX_SIMD_IS_LIKELY(all_of(__r._M_x < 6 * __pi_over_4)))
331 const _V __y = nearbyint(__r._M_x * __2_over_pi);
332 __r._M_quadrant = static_simd_cast<_IV>(__y) & 3;
333 __r._M_x -= __y * __pi_2_5bits0;
334 __r._M_x -= __y * __pi_2_5bits0_rem;
338 using __math_double::__2_over_pi;
339 using __math_double::__pi_2;
340 using _VD = rebind_simd_t<double, _V>;
341 _VD __xd = static_simd_cast<_VD>(__r._M_x);
342 _VD __y = nearbyint(__xd * __2_over_pi);
343 __r._M_quadrant = static_simd_cast<_IV>(__y) & 3;
344 __r._M_x = static_simd_cast<_V>(__xd - __y * __pi_2);
350 template <
typename _Abi>
351 _GLIBCXX_SIMD_ALWAYS_INLINE _Folded<double, _Abi>
352 __fold_input(
const simd<double, _Abi>& __x)
354 using _V = simd<double, _Abi>;
355 using _IV = rebind_simd_t<int, _V>;
358 _Folded<double, _Abi> __r;
360 if (_GLIBCXX_SIMD_IS_UNLIKELY(all_of(__r._M_x < __pi_over_4)))
365 const _V __y = nearbyint(__r._M_x / (2 * __pi_over_4));
366 __r._M_quadrant = static_simd_cast<_IV>(__y) & 3;
368 if (_GLIBCXX_SIMD_IS_LIKELY(all_of(__r._M_x < 1025 * __pi_over_4)))
371 __r._M_x -= __y * 0x1.921FB54443000p0;
372 __r._M_x -= __y * -0x1.73DCB3B39A000p-43;
373 __r._M_x -= __y * 0x1.45C06E0E68948p-86;
375 else if (_GLIBCXX_SIMD_IS_LIKELY(all_of(__y <= 0x1.0p30)))
378 __r._M_x -= __y * 0x1.921FB40000000p0;
379 __r._M_x -= __y * 0x1.4442D00000000p-24;
380 __r._M_x -= __y * 0x1.8469898CC5170p-48;
385 const _V __y_hi = __zero_low_bits<26>(__y);
386 const _V __y_lo = __y - __y_hi;
387 const auto __pi_2_1 = 0x1.921FB50000000p0;
388 const auto __pi_2_2 = 0x1.110B460000000p-26;
389 const auto __pi_2_3 = 0x1.1A62630000000p-54;
390 const auto __pi_2_4 = 0x1.8A2E03707344Ap-81;
391 __r._M_x = __r._M_x - __y_hi * __pi_2_1
392 - max(__y_hi * __pi_2_2, __y_lo * __pi_2_1)
393 - min(__y_hi * __pi_2_2, __y_lo * __pi_2_1)
394 - max(__y_hi * __pi_2_3, __y_lo * __pi_2_2)
395 - min(__y_hi * __pi_2_3, __y_lo * __pi_2_2)
396 - max(__y * __pi_2_4, __y_lo * __pi_2_3)
397 - min(__y * __pi_2_4, __y_lo * __pi_2_3);
404 template <
typename _Tp,
typename _Abi>
405 _GLIBCXX_SIMD_INTRINSIC
406 rebind_simd_t<int, simd<_Tp, _Abi>>
407 __extract_exponent_as_int(
const simd<_Tp, _Abi>& __v)
409 using _Vp = simd<_Tp, _Abi>;
410 using _Up = make_unsigned_t<__int_for_sizeof_t<_Tp>>;
411 using namespace std::experimental::__float_bitwise_operators;
412 using namespace std::experimental::__proposed;
413 const _Vp __exponent_mask
415 return static_simd_cast<rebind_simd_t<int, _Vp>>(
416 simd_bit_cast<rebind_simd_t<_Up, _Vp>>(__v & __exponent_mask)
417 >> (__digits_v<_Tp> - 1));
422 template <
typename ImplFun,
typename FallbackFun,
typename... _Args>
423 _GLIBCXX_SIMD_INTRINSIC
auto 424 __impl_or_fallback_dispatch(
int, ImplFun&& __impl_fun, FallbackFun&&,
426 -> decltype(__impl_fun(static_cast<_Args&&>(__args)...))
427 {
return __impl_fun(static_cast<_Args&&>(__args)...); }
429 template <
typename ImplFun,
typename FallbackFun,
typename... _Args,
430 typename = __detail::__odr_helper>
432 __impl_or_fallback_dispatch(
float, ImplFun&&, FallbackFun&& __fallback_fun,
434 -> decltype(__fallback_fun(static_cast<_Args&&>(__args)...))
435 {
return __fallback_fun(static_cast<_Args&&>(__args)...); }
437 template <
typename... _Args>
438 _GLIBCXX_SIMD_INTRINSIC
auto 439 __impl_or_fallback(_Args&&... __args)
441 return __impl_or_fallback_dispatch(
int(), static_cast<_Args&&>(__args)...);
446 _GLIBCXX_SIMD_MATH_CALL_(acos)
447 _GLIBCXX_SIMD_MATH_CALL_(asin)
448 _GLIBCXX_SIMD_MATH_CALL_(atan)
449 _GLIBCXX_SIMD_MATH_CALL2_(atan2, _Tp)
466 template <
typename _Tp,
typename _Abi,
typename = __detail::__odr_helper>
467 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>>
468 cos(
const simd<_Tp, _Abi>& __x)
470 using _V = simd<_Tp, _Abi>;
471 if constexpr (__is_scalar_abi<_Abi>() || __is_fixed_size_abi_v<_Abi>)
472 return {__private_init, _Abi::_SimdImpl::_S_cos(__data(__x))};
475 if constexpr (is_same_v<_Tp, float>)
476 if (_GLIBCXX_SIMD_IS_UNLIKELY(any_of(
abs(__x) >= 393382)))
477 return static_simd_cast<_V>(
478 cos(static_simd_cast<rebind_simd_t<double, _V>>(__x)));
480 const auto __f = __fold_input(__x);
486 using namespace std::experimental::__float_bitwise_operators;
488 = _V(-0.f) & static_simd_cast<_V>((1 + __f._M_quadrant) << 30);
490 const auto __need_cos = (__f._M_quadrant & 1) == 0;
491 if (_GLIBCXX_SIMD_IS_UNLIKELY(all_of(__need_cos)))
492 return __sign_flip ^ __cosSeries(__f._M_x);
493 else if (_GLIBCXX_SIMD_IS_UNLIKELY(none_of(__need_cos)))
494 return __sign_flip ^ __sinSeries(__f._M_x);
497 _V __r = __sinSeries(__f._M_x);
498 where(__need_cos.__cvt(), __r) = __cosSeries(__f._M_x);
499 return __r ^ __sign_flip;
504 template <
typename _Tp>
505 _GLIBCXX_SIMD_ALWAYS_INLINE
506 enable_if_t<is_floating_point<_Tp>::value, simd<_Tp, simd_abi::scalar>>
507 cos(simd<_Tp, simd_abi::scalar> __x)
512 template <
typename _Tp,
typename _Abi,
typename = __detail::__odr_helper>
513 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>>
514 sin(
const simd<_Tp, _Abi>& __x)
516 using _V = simd<_Tp, _Abi>;
517 if constexpr (__is_scalar_abi<_Abi>() || __is_fixed_size_abi_v<_Abi>)
518 return {__private_init, _Abi::_SimdImpl::_S_sin(__data(__x))};
521 if constexpr (is_same_v<_Tp, float>)
522 if (_GLIBCXX_SIMD_IS_UNLIKELY(any_of(
abs(__x) >= 527449)))
523 return static_simd_cast<_V>(
524 sin(static_simd_cast<rebind_simd_t<double, _V>>(__x)));
526 const auto __f = __fold_input(__x);
532 using namespace std::experimental::__float_bitwise_operators;
533 const auto __sign_flip
534 = (__x ^ static_simd_cast<_V>(1 - __f._M_quadrant)) & _V(_Tp(-0.));
536 const auto __need_sin = (__f._M_quadrant & 1) == 0;
537 if (_GLIBCXX_SIMD_IS_UNLIKELY(all_of(__need_sin)))
538 return __sign_flip ^ __sinSeries(__f._M_x);
539 else if (_GLIBCXX_SIMD_IS_UNLIKELY(none_of(__need_sin)))
540 return __sign_flip ^ __cosSeries(__f._M_x);
543 _V __r = __cosSeries(__f._M_x);
544 where(__need_sin.__cvt(), __r) = __sinSeries(__f._M_x);
545 return __sign_flip ^ __r;
550 template <
typename _Tp>
551 _GLIBCXX_SIMD_ALWAYS_INLINE
552 enable_if_t<is_floating_point<_Tp>::value, simd<_Tp, simd_abi::scalar>>
553 sin(simd<_Tp, simd_abi::scalar> __x)
557 _GLIBCXX_SIMD_MATH_CALL_(
tan)
558 _GLIBCXX_SIMD_MATH_CALL_(acosh)
559 _GLIBCXX_SIMD_MATH_CALL_(asinh)
560 _GLIBCXX_SIMD_MATH_CALL_(atanh)
561 _GLIBCXX_SIMD_MATH_CALL_(
cosh)
562 _GLIBCXX_SIMD_MATH_CALL_(
sinh)
563 _GLIBCXX_SIMD_MATH_CALL_(
tanh)
566 _GLIBCXX_SIMD_MATH_CALL_(
exp)
567 _GLIBCXX_SIMD_MATH_CALL_(exp2)
568 _GLIBCXX_SIMD_MATH_CALL_(expm1)
572 #if _GLIBCXX_SIMD_X86INTRIN 573 template <
typename _Tp,
size_t _Np>
574 _GLIBCXX_SIMD_INTRINSIC
575 _SimdWrapper<_Tp, _Np>
576 __getexp(_SimdWrapper<_Tp, _Np> __x)
578 if constexpr (__have_avx512vl && __is_sse_ps<_Tp, _Np>())
579 return __auto_bitcast(_mm_getexp_ps(__to_intrin(__x)));
580 else if constexpr (__have_avx512f && __is_sse_ps<_Tp, _Np>())
581 return __auto_bitcast(_mm512_getexp_ps(__auto_bitcast(__to_intrin(__x))));
582 else if constexpr (__have_avx512vl && __is_sse_pd<_Tp, _Np>())
583 return _mm_getexp_pd(__x);
584 else if constexpr (__have_avx512f && __is_sse_pd<_Tp, _Np>())
585 return __lo128(_mm512_getexp_pd(__auto_bitcast(__x)));
586 else if constexpr (__have_avx512vl && __is_avx_ps<_Tp, _Np>())
587 return _mm256_getexp_ps(__x);
588 else if constexpr (__have_avx512f && __is_avx_ps<_Tp, _Np>())
589 return __lo256(_mm512_getexp_ps(__auto_bitcast(__x)));
590 else if constexpr (__have_avx512vl && __is_avx_pd<_Tp, _Np>())
591 return _mm256_getexp_pd(__x);
592 else if constexpr (__have_avx512f && __is_avx_pd<_Tp, _Np>())
593 return __lo256(_mm512_getexp_pd(__auto_bitcast(__x)));
594 else if constexpr (__is_avx512_ps<_Tp, _Np>())
595 return _mm512_getexp_ps(__x);
596 else if constexpr (__is_avx512_pd<_Tp, _Np>())
597 return _mm512_getexp_pd(__x);
599 __assert_unreachable<_Tp>();
602 template <typename _Tp,
size_t _Np>
603 _GLIBCXX_SIMD_INTRINSIC
604 _SimdWrapper<_Tp, _Np>
605 __getmant_avx512(_SimdWrapper<_Tp, _Np> __x)
607 if constexpr (__have_avx512vl && __is_sse_ps<_Tp, _Np>())
608 return __auto_bitcast(_mm_getmant_ps(__to_intrin(__x), _MM_MANT_NORM_p5_1,
610 else if constexpr (__have_avx512f && __is_sse_ps<_Tp, _Np>())
611 return __auto_bitcast(_mm512_getmant_ps(__auto_bitcast(__to_intrin(__x)),
614 else if constexpr (__have_avx512vl && __is_sse_pd<_Tp, _Np>())
615 return _mm_getmant_pd(__x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
616 else if constexpr (__have_avx512f && __is_sse_pd<_Tp, _Np>())
617 return __lo128(_mm512_getmant_pd(__auto_bitcast(__x), _MM_MANT_NORM_p5_1,
619 else if constexpr (__have_avx512vl && __is_avx_ps<_Tp, _Np>())
620 return _mm256_getmant_ps(__x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
621 else if constexpr (__have_avx512f && __is_avx_ps<_Tp, _Np>())
622 return __lo256(_mm512_getmant_ps(__auto_bitcast(__x), _MM_MANT_NORM_p5_1,
624 else if constexpr (__have_avx512vl && __is_avx_pd<_Tp, _Np>())
625 return _mm256_getmant_pd(__x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
626 else if constexpr (__have_avx512f && __is_avx_pd<_Tp, _Np>())
627 return __lo256(_mm512_getmant_pd(__auto_bitcast(__x), _MM_MANT_NORM_p5_1,
629 else if constexpr (__is_avx512_ps<_Tp, _Np>())
630 return _mm512_getmant_ps(__x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
631 else if constexpr (__is_avx512_pd<_Tp, _Np>())
632 return _mm512_getmant_pd(__x, _MM_MANT_NORM_p5_1, _MM_MANT_SIGN_src);
634 __assert_unreachable<_Tp>();
636 #endif // _GLIBCXX_SIMD_X86INTRIN 644 template <
typename _Tp,
typename _Abi,
typename = __detail::__odr_helper>
645 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>>
646 frexp(
const simd<_Tp, _Abi>& __x, _Samesize<
int, simd<_Tp, _Abi>>* __exp)
648 if constexpr (simd_size_v<_Tp, _Abi> == 1)
651 const auto __r = std::frexp(__x[0], &__tmp);
655 else if constexpr (__is_sve_abi<_Abi>())
658 __execute_n_times<simd_size_v<_Tp, _Abi>>(
659 [&](
auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
661 const auto __ri = std::frexp(__x[__i], &__tmp);
662 (*__exp)[__i] = __tmp;
667 else if constexpr (__is_fixed_size_abi_v<_Abi>)
668 return {__private_init, _Abi::_SimdImpl::_S_frexp(__data(__x), __data(*__exp))};
669 #if _GLIBCXX_SIMD_X86INTRIN 670 else if constexpr (__have_avx512f)
672 constexpr
size_t _Np = simd_size_v<_Tp, _Abi>;
673 constexpr
size_t _NI = _Np < 4 ? 4 : _Np;
674 const auto __v = __data(__x);
675 const auto __isnonzero
676 = _Abi::_SimdImpl::_S_isnonzerovalue_mask(__v._M_data);
677 const _SimdWrapper<int, _NI> __exp_plus1
678 = 1 + __convert<_SimdWrapper<int, _NI>>(__getexp(__v))._M_data;
679 const _SimdWrapper<int, _Np> __e = __wrapper_bitcast<int, _Np>(
680 _Abi::_CommonImpl::_S_blend(_SimdWrapper<bool, _NI>(__isnonzero),
681 _SimdWrapper<int, _NI>(), __exp_plus1));
682 simd_abi::deduce_t<int, _Np>::_CommonImpl::_S_store(__e, __exp);
683 return {__private_init,
684 _Abi::_CommonImpl::_S_blend(_SimdWrapper<bool, _Np>(
686 __v, __getmant_avx512(__v))};
688 #endif // _GLIBCXX_SIMD_X86INTRIN 692 static_assert(
sizeof(_Tp) == 4 ||
sizeof(_Tp) == 8);
693 using _V = simd<_Tp, _Abi>;
694 using _IV = rebind_simd_t<int, _V>;
695 using namespace std::experimental::__proposed;
696 using namespace std::experimental::__float_bitwise_operators;
698 constexpr
int __exp_adjust =
sizeof(_Tp) == 4 ? 0x7e : 0x3fe;
699 constexpr
int __exp_offset =
sizeof(_Tp) == 4 ? 0x70 : 0x200;
700 constexpr _Tp __subnorm_scale =
sizeof(_Tp) == 4 ? 0x1p112 : 0x1p512;
701 _GLIBCXX_SIMD_USE_CONSTEXPR_API _V __exponent_mask
703 _GLIBCXX_SIMD_USE_CONSTEXPR_API _V __p5_1_exponent
704 = -(2 - __epsilon_v<_Tp>) / 2;
706 _V __mant = __p5_1_exponent & (__exponent_mask | __x);
707 const _IV __exponent_bits = __extract_exponent_as_int(__x);
708 if (_GLIBCXX_SIMD_IS_LIKELY(all_of(isnormal(__x))))
711 = simd_cast<_Samesize<int, _V>>(__exponent_bits - __exp_adjust);
715 #if __FINITE_MATH_ONLY__ 718 const auto __iszero_inf_nan = __x == 0;
720 using _Ip = __int_for_sizeof_t<_Tp>;
721 const auto __as_int = simd_bit_cast<rebind_simd_t<_Ip, _V>>(
abs(__x));
722 const auto __inf = simd_bit_cast<rebind_simd_t<_Ip, _V>>(_V(__infinity_v<_Tp>));
723 const auto __iszero_inf_nan = static_simd_cast<
typename _V::mask_type>(
724 __as_int == 0 || __as_int >= __inf);
727 const _V __scaled_subnormal = __x * __subnorm_scale;
728 const _V __mant_subnormal
729 = __p5_1_exponent & (__exponent_mask | __scaled_subnormal);
730 where(!isnormal(__x), __mant) = __mant_subnormal;
731 where(__iszero_inf_nan, __mant) = __x;
732 _IV __e = __extract_exponent_as_int(__scaled_subnormal);
734 typename conditional_t<
sizeof(
typename _V::value_type) ==
sizeof(
int),
736 const _MaskType __value_isnormal = isnormal(__x).__cvt();
737 where(__value_isnormal.__cvt(), __e) = __exponent_bits;
738 static_assert(
sizeof(_IV) ==
sizeof(__value_isnormal));
740 = (simd_bit_cast<_IV>(__value_isnormal) & _IV(__exp_adjust))
741 | (simd_bit_cast<_IV>(static_simd_cast<_MaskType>(__exponent_bits == 0)
742 & static_simd_cast<_MaskType>(__x != 0))
743 & _IV(__exp_adjust + __exp_offset));
744 *__exp = simd_cast<_Samesize<int, _V>>(__e - __offset);
750 _GLIBCXX_SIMD_MATH_CALL2_(ldexp,
int)
751 _GLIBCXX_SIMD_MATH_CALL_(ilogb)
754 _GLIBCXX_SIMD_MATH_CALL_(
log)
755 _GLIBCXX_SIMD_MATH_CALL_(
log10)
756 _GLIBCXX_SIMD_MATH_CALL_(log1p)
757 _GLIBCXX_SIMD_MATH_CALL_(log2)
761 template <
typename _Tp,
typename _Abi,
typename = __detail::__odr_helper>
762 enable_if_t<is_floating_point<_Tp>::value, simd<_Tp, _Abi>>
763 logb(
const simd<_Tp, _Abi>& __x)
765 constexpr
size_t _Np = simd_size_v<_Tp, _Abi>;
766 if constexpr (_Np == 1)
767 return
std::logb(__x[0]);
768 else if constexpr (__is_fixed_size_abi_v<_Abi>)
769 return {__private_init, _Abi::_SimdImpl::_S_logb(__data(__x))};
770 #if _GLIBCXX_SIMD_X86INTRIN // {{{ 771 else if constexpr (__have_avx512vl && __is_sse_ps<_Tp, _Np>())
772 return {__private_init,
773 __auto_bitcast(_mm_getexp_ps(__to_intrin(__as_vector(__x))))};
774 else if constexpr (__have_avx512vl && __is_sse_pd<_Tp, _Np>())
775 return {__private_init, _mm_getexp_pd(__data(__x))};
776 else if constexpr (__have_avx512vl && __is_avx_ps<_Tp, _Np>())
777 return {__private_init, _mm256_getexp_ps(__data(__x))};
778 else if constexpr (__have_avx512vl && __is_avx_pd<_Tp, _Np>())
779 return {__private_init, _mm256_getexp_pd(__data(__x))};
780 else if constexpr (__have_avx512f && __is_avx_ps<_Tp, _Np>())
781 return {__private_init,
782 __lo256(_mm512_getexp_ps(__auto_bitcast(__data(__x))))};
783 else if constexpr (__have_avx512f && __is_avx_pd<_Tp, _Np>())
784 return {__private_init,
785 __lo256(_mm512_getexp_pd(__auto_bitcast(__data(__x))))};
786 else if constexpr (__is_avx512_ps<_Tp, _Np>())
787 return {__private_init, _mm512_getexp_ps(__data(__x))};
788 else if constexpr (__is_avx512_pd<_Tp, _Np>())
789 return {__private_init, _mm512_getexp_pd(__data(__x))};
790 #endif // _GLIBCXX_SIMD_X86INTRIN }}} 793 using _V = simd<_Tp, _Abi>;
794 using namespace std::experimental::__proposed;
795 auto __is_normal = isnormal(__x);
799 const _V abs_x =
abs(__x);
803 auto&& __exponent = [](
const _V& __v) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
804 using namespace std::experimental::__proposed;
805 using _IV = rebind_simd_t<
806 conditional_t<sizeof(_Tp) == sizeof(_LLong), _LLong, int>, _V>;
807 return (simd_bit_cast<_IV>(__v) >> (__digits_v<_Tp> - 1))
808 - (__max_exponent_v<_Tp> - 1);
810 _V __r = static_simd_cast<_V>(__exponent(abs_x));
811 if (_GLIBCXX_SIMD_IS_LIKELY(all_of(__is_normal)))
815 const auto __is_zero = __x == 0;
816 const auto __is_nan = isnan(__x);
817 const auto __is_inf = isinf(__x);
818 where(__is_zero, __r) = -__infinity_v<_Tp>;
819 where(__is_nan, __r) = __x;
820 where(__is_inf, __r) = __infinity_v<_Tp>;
821 __is_normal |= __is_zero || __is_nan || __is_inf;
822 if (all_of(__is_normal))
828 const _V __scaled = abs_x * _Tp(0x1p112);
829 _V __scaled_exp = static_simd_cast<_V>(__exponent(__scaled) - 112);
830 where(__is_normal, __scaled_exp) = __r;
836 template <
typename _Tp,
typename _Abi,
typename = __detail::__odr_helper>
837 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>>
838 modf(
const simd<_Tp, _Abi>& __x, simd<_Tp, _Abi>* __iptr)
840 if constexpr (simd_size_v<_Tp, _Abi> == 1)
843 _Tp __r = std::modf(__x[0], &__tmp);
849 const auto __integral = trunc(__x);
850 *__iptr = __integral;
851 auto __r = __x - __integral;
852 #if !__FINITE_MATH_ONLY__ 853 where(isinf(__x), __r) = _Tp();
855 return copysign(__r, __x);
859 _GLIBCXX_SIMD_MATH_CALL2_(scalbn,
int)
860 _GLIBCXX_SIMD_MATH_CALL2_(scalbln,
long)
862 _GLIBCXX_SIMD_MATH_CALL_(cbrt)
864 _GLIBCXX_SIMD_MATH_CALL_(
abs)
865 _GLIBCXX_SIMD_MATH_CALL_(
fabs)
869 template <
typename _Tp,
typename _Abi>
870 _GLIBCXX_SIMD_ALWAYS_INLINE
871 enable_if_t<!is_floating_point_v<_Tp> && is_signed_v<_Tp>, simd<_Tp, _Abi>>
872 abs(
const simd<_Tp, _Abi>& __x)
873 {
return {__private_init, _Abi::_SimdImpl::_S_abs(__data(__x))}; }
875 #define _GLIBCXX_SIMD_CVTING2(_NAME) \ 876 template <typename _Tp, typename _Abi> \ 877 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 878 const simd<_Tp, _Abi>& __x, const __type_identity_t<simd<_Tp, _Abi>>& __y) \ 880 return _NAME(__x, __y); \ 883 template <typename _Tp, typename _Abi> \ 884 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 885 const __type_identity_t<simd<_Tp, _Abi>>& __x, const simd<_Tp, _Abi>& __y) \ 887 return _NAME(__x, __y); \ 890 #define _GLIBCXX_SIMD_CVTING3(_NAME) \ 891 template <typename _Tp, typename _Abi> \ 892 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 893 const __type_identity_t<simd<_Tp, _Abi>>& __x, const simd<_Tp, _Abi>& __y, \ 894 const simd<_Tp, _Abi>& __z) \ 896 return _NAME(__x, __y, __z); \ 899 template <typename _Tp, typename _Abi> \ 900 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 901 const simd<_Tp, _Abi>& __x, const __type_identity_t<simd<_Tp, _Abi>>& __y, \ 902 const simd<_Tp, _Abi>& __z) \ 904 return _NAME(__x, __y, __z); \ 907 template <typename _Tp, typename _Abi> \ 908 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 909 const simd<_Tp, _Abi>& __x, const simd<_Tp, _Abi>& __y, \ 910 const __type_identity_t<simd<_Tp, _Abi>>& __z) \ 912 return _NAME(__x, __y, __z); \ 915 template <typename _Tp, typename _Abi> \ 916 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 917 const simd<_Tp, _Abi>& __x, const __type_identity_t<simd<_Tp, _Abi>>& __y, \ 918 const __type_identity_t<simd<_Tp, _Abi>>& __z) \ 920 return _NAME(__x, __y, __z); \ 923 template <typename _Tp, typename _Abi> \ 924 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 925 const __type_identity_t<simd<_Tp, _Abi>>& __x, const simd<_Tp, _Abi>& __y, \ 926 const __type_identity_t<simd<_Tp, _Abi>>& __z) \ 928 return _NAME(__x, __y, __z); \ 931 template <typename _Tp, typename _Abi> \ 932 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> _NAME( \ 933 const __type_identity_t<simd<_Tp, _Abi>>& __x, \ 934 const __type_identity_t<simd<_Tp, _Abi>>& __y, const simd<_Tp, _Abi>& __z) \ 936 return _NAME(__x, __y, __z); \ 939 template <
typename _R,
typename _ToApply,
typename _Tp,
typename... _Tps>
940 _GLIBCXX_SIMD_INTRINSIC _R
941 __fixed_size_apply(_ToApply&& __apply,
const _Tp& __arg0,
942 const _Tps&... __args)
944 return {__private_init,
945 __data(__arg0)._M_apply_per_chunk(
946 [&](
auto __impl,
const auto&... __inner) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
947 using _V =
typename decltype(__impl)::simd_type;
948 return __data(__apply(_V(__private_init, __inner)...));
953 template <
typename _VV,
typename = __detail::__odr_helper>
954 __remove_cvref_t<_VV>
955 __hypot(_VV __x, _VV __y)
957 using _V = __remove_cvref_t<_VV>;
958 using _Tp =
typename _V::value_type;
960 return
std::hypot(_Tp(__x[0]), _Tp(__y[0]));
961 else if constexpr (__is_fixed_size_abi_v<typename _V::abi_type>)
963 return __fixed_size_apply<_V>([](
auto __a,
964 auto __b) {
return hypot(__a, __b); },
974 using namespace __float_bitwise_operators;
976 _V __absx =
abs(__x);
977 _V __absy =
abs(__y);
978 _V __hi =
max(__absx, __absy);
979 _V __lo =
min(__absy, __absx);
982 _GLIBCXX_SIMD_USE_CONSTEXPR_API _V __inf(__infinity_v<_Tp>);
984 #ifndef __FAST_MATH__ 985 if constexpr (__have_neon && !__have_neon_a32)
988 const _V __hi_exp = __hi & __inf;
989 _V __scale_back = __hi_exp;
992 where(__hi_exp > 1, __scale_back) = __hi_exp * _Tp(0.125);
994 const _V __scale = (__scale_back ^ __inf) * _Tp(.5);
995 const _V __h1 = __hi * __scale;
996 const _V __l1 = __lo * __scale;
997 _V __r = __scale_back *
sqrt(__h1 * __h1 + __l1 * __l1);
999 where(__hi == 0, __r) = 0;
1004 #ifdef __FAST_MATH__ 1010 if (_GLIBCXX_SIMD_IS_LIKELY(all_of(isnormal(__x))
1011 && all_of(isnormal(__y))))
1014 const _V __hi_exp = __hi & __inf;
1020 #ifdef __FAST_MATH__ 1021 using _Ip = __int_for_sizeof_t<_Tp>;
1022 using _IV = rebind_simd_t<_Ip, _V>;
1023 const auto __as_int = simd_bit_cast<_IV>(__hi_exp);
1025 = simd_bit_cast<_V>(2 * __bit_cast<_Ip>(_Tp(1)) - __as_int);
1027 const _V __scale = (__hi_exp ^ __inf) * _Tp(.5);
1029 _GLIBCXX_SIMD_USE_CONSTEXPR_API _V __mant_mask
1030 = __norm_min_v<_Tp> - __denorm_min_v<_Tp>;
1031 const _V __h1 = (__hi & __mant_mask) | _V(1);
1032 const _V __l1 = __lo * __scale;
1033 return __hi_exp *
sqrt(__h1 * __h1 + __l1 * __l1);
1040 _V __scale = _V(1 / __norm_min_v<_Tp>);
1044 where(__hi >= __norm_min_v<_Tp>, __scale)
1045 = ((__hi & __inf) ^ __inf) * _Tp(.5);
1047 _V __hi_exp = __norm_min_v<_Tp>;
1048 where(__hi >= __norm_min_v<_Tp>, __hi_exp)
1050 _V __h1 = __hi * __scale;
1051 _V __l1 = __lo * __scale;
1055 _V __r = __hi_exp *
sqrt(__h1 * __h1 + __l1 * __l1);
1056 #ifdef __STDC_IEC_559__ 1068 where(isunordered(__x, __y), __fixup) = __quiet_NaN_v<_Tp>;
1069 where(isinf(__absx) || isinf(__absy), __fixup) = __inf;
1070 where(!(__lo == 0 || isunordered(__x, __y)
1071 || (isinf(__absx) || isinf(__absy))),
1081 template <
typename _Tp,
typename _Abi>
1082 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi>
1083 hypot(
const simd<_Tp, _Abi>& __x,
const simd<_Tp, _Abi>& __y)
1085 return __hypot<conditional_t<__is_fixed_size_abi_v<_Abi>,
1086 const simd<_Tp, _Abi>&, simd<_Tp, _Abi>>>(__x,
1090 _GLIBCXX_SIMD_CVTING2(hypot)
1092 template <
typename _VV,
typename = __detail::__odr_helper>
1093 __remove_cvref_t<_VV>
1094 __hypot(_VV __x, _VV __y, _VV __z)
1096 using _V = __remove_cvref_t<_VV>;
1097 using _Abi =
typename _V::abi_type;
1098 using _Tp =
typename _V::value_type;
1104 if constexpr (__is_fixed_size_abi_v<_Abi> &&
_V::size() > 1)
1106 return __fixed_size_apply<simd<_Tp, _Abi>>(
1107 [](
auto __a,
auto __b,
auto __c) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA {
1108 return hypot(__a, __b, __c);
1113 using namespace __float_bitwise_operators;
1115 const _V __absx =
abs(__x);
1116 const _V __absy =
abs(__y);
1117 const _V __absz =
abs(__z);
1118 _V __hi =
max(
max(__absx, __absy), __absz);
1119 _V __l0 =
min(__absz,
max(__absx, __absy));
1120 _V __l1 =
min(__absy, __absx);
1121 if constexpr (__digits_v<_Tp> == 64 && __max_exponent_v<_Tp> == 0x4000
1122 && __min_exponent_v<_Tp> == -0x3FFD &&
_V::size() == 1)
1126 #ifdef __STDC_IEC_559__ 1128 if (isinf(__absx[0]) || isinf(__absy[0]) || isinf(__absz[0]))
1129 return __infinity_v<_Tp>;
1130 else if (isunordered(__absx[0], __absy[0] + __absz[0]))
1131 return __quiet_NaN_v<_Tp>;
1132 else if (__l0[0] == 0 && __l1[0] == 0)
1136 const _ULLong __tmp = 0x8000
'0000'0000
'0000ull; 1137 __builtin_memcpy(&__data(__hi_exp), &__tmp, 8); 1138 const _V __scale = 1 / __hi_exp; 1142 return __hi_exp * sqrt((__l0 * __l0 + __l1 * __l1) + __hi * __hi); 1146 // round __hi down to the next power-of-2: 1147 _GLIBCXX_SIMD_USE_CONSTEXPR_API _V __inf(__infinity_v<_Tp>); 1149 #ifndef __FAST_MATH__ 1150 if constexpr (_V::size() > 1 1151 && __is_neon_abi<_Abi>() && __have_neon && !__have_neon_a32) 1152 { // With ARMv7 NEON, we have no subnormals and must use slightly 1153 // different strategy 1154 const _V __hi_exp = __hi & __inf; 1155 _V __scale_back = __hi_exp; 1156 // For large exponents (max & max/2) the inversion comes too 1157 // close to subnormals. Subtract 3 from the exponent: 1158 where(__hi_exp > 1, __scale_back) = __hi_exp * _Tp(0.125); 1159 // Invert and adjust for the off-by-one error of inversion via 1161 const _V __scale = (__scale_back ^ __inf) * _Tp(.5); 1162 const _V __h1 = __hi * __scale; 1165 _V __lo = __l0 * __l0 1166 + __l1 * __l1; // add the two smaller values first 1167 asm("" : "+m"(__lo)); 1168 _V __r = __scale_back * sqrt(__h1 * __h1 + __lo); 1169 // Fix up hypot(0, 0, 0) to not be NaN: 1170 where(__hi == 0, __r) = 0; 1175 #ifdef __FAST_MATH__ 1176 // With fast-math, ignore precision of subnormals and inputs from 1177 // __finite_max_v/2 to __finite_max_v. This removes all 1178 // branching/masking. 1181 if (_GLIBCXX_SIMD_IS_LIKELY(all_of(isnormal(__x)) 1182 && all_of(isnormal(__y)) 1183 && all_of(isnormal(__z)))) 1186 const _V __hi_exp = __hi & __inf; 1187 //((__hi + __hi) & __inf) ^ __inf almost works for computing 1188 //__scale, except when (__hi + __hi) & __inf == __inf, in which 1190 // becomes 0 (should be min/2 instead) and thus loses the 1191 // information from __lo. 1192 #ifdef __FAST_MATH__ 1193 using _Ip = __int_for_sizeof_t<_Tp>; 1194 using _IV = rebind_simd_t<_Ip, _V>; 1195 const auto __as_int = simd_bit_cast<_IV>(__hi_exp); 1197 = simd_bit_cast<_V>(2 * __bit_cast<_Ip>(_Tp(1)) - __as_int); 1199 const _V __scale = (__hi_exp ^ __inf) * _Tp(.5); 1201 constexpr _Tp __mant_mask 1202 = __norm_min_v<_Tp> - __denorm_min_v<_Tp>; 1203 const _V __h1 = (__hi & _V(__mant_mask)) | _V(1); 1208 + __l1 * __l1; // add the two smaller values first 1209 return __hi_exp * sqrt(__lo + __h1 * __h1); 1213 // slower path to support subnormals 1214 // if __hi is subnormal, avoid scaling by inf & final mul by 0 1215 // (which yields NaN) by using min() 1216 _V __scale = _V(1 / __norm_min_v<_Tp>); 1217 // invert exponent w/o error and w/o using the slow divider 1218 // unit: xor inverts the exponent but off by 1. Multiplication 1219 // with .5 adjusts for the discrepancy. 1220 where(__hi >= __norm_min_v<_Tp>, __scale) 1221 = ((__hi & __inf) ^ __inf) * _Tp(.5); 1222 // adjust final exponent for subnormal inputs 1223 _V __hi_exp = __norm_min_v<_Tp>; 1224 where(__hi >= __norm_min_v<_Tp>, __hi_exp) 1225 = __hi & __inf; // no error 1226 _V __h1 = __hi * __scale; // no error 1227 __l0 *= __scale; // no error 1228 __l1 *= __scale; // no error 1229 _V __lo = __l0 * __l0 1230 + __l1 * __l1; // add the two smaller values first 1231 _V __r = __hi_exp * sqrt(__lo + __h1 * __h1); 1232 #ifdef __STDC_IEC_559__ 1233 // fixup for Annex F requirements 1234 _V __fixup = __hi; // __lo == 0 1235 // where(__lo == 0, __fixup) = __hi; 1236 where(isunordered(__x, __y + __z), __fixup) 1237 = __quiet_NaN_v<_Tp>; 1238 where(isinf(__absx) || isinf(__absy) || isinf(__absz), __fixup) 1240 // Instead of __lo == 0, the following could depend on __h1² == 1241 // __h1² + __lo (i.e. __hi is so much larger than the other two 1242 // inputs that the result is exactly __hi). While this may 1243 // improve precision, it is likely to reduce efficiency if the 1244 // ISA has FMAs (because __h1² + __lo is an FMA, but the 1246 // __h1² must be kept) 1247 where(!(__lo == 0 || isunordered(__x, __y + __z) 1248 || isinf(__absx) || isinf(__absy) || isinf(__absz)), 1259 template <typename _Tp, typename _Abi> 1260 _GLIBCXX_SIMD_INTRINSIC simd<_Tp, _Abi> 1261 hypot(const simd<_Tp, _Abi>& __x, const simd<_Tp, _Abi>& __y, 1262 const simd<_Tp, _Abi>& __z) 1264 return __hypot<conditional_t<__is_fixed_size_abi_v<_Abi>, 1265 const simd<_Tp, _Abi>&, simd<_Tp, _Abi>>>(__x, 1270 _GLIBCXX_SIMD_CVTING3(hypot) 1272 _GLIBCXX_SIMD_MATH_CALL2_(pow, _Tp) 1274 _GLIBCXX_SIMD_MATH_CALL_(sqrt) 1275 _GLIBCXX_SIMD_MATH_CALL_(erf) 1276 _GLIBCXX_SIMD_MATH_CALL_(erfc) 1277 _GLIBCXX_SIMD_MATH_CALL_(lgamma) 1278 _GLIBCXX_SIMD_MATH_CALL_(tgamma) 1279 _GLIBCXX_SIMD_MATH_CALL_(ceil) 1280 _GLIBCXX_SIMD_MATH_CALL_(floor) 1281 _GLIBCXX_SIMD_MATH_CALL_(nearbyint) 1282 _GLIBCXX_SIMD_MATH_CALL_(rint) 1283 _GLIBCXX_SIMD_MATH_CALL_(lrint) 1284 _GLIBCXX_SIMD_MATH_CALL_(llrint) 1286 _GLIBCXX_SIMD_MATH_CALL_(round) 1287 _GLIBCXX_SIMD_MATH_CALL_(lround) 1288 _GLIBCXX_SIMD_MATH_CALL_(llround) 1290 _GLIBCXX_SIMD_MATH_CALL_(trunc) 1292 _GLIBCXX_SIMD_MATH_CALL2_(fmod, _Tp) 1293 _GLIBCXX_SIMD_MATH_CALL2_(remainder, _Tp) 1294 _GLIBCXX_SIMD_MATH_CALL3_(remquo, _Tp, int*) 1296 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1297 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1298 copysign(const simd<_Tp, _Abi>& __x, const simd<_Tp, _Abi>& __y) 1300 if constexpr (simd_size_v<_Tp, _Abi> == 1) 1301 return std::copysign(__x[0], __y[0]); 1302 else if constexpr (__is_fixed_size_abi_v<_Abi>) 1303 return {__private_init, _Abi::_SimdImpl::_S_copysign(__data(__x), __data(__y))}; 1306 using _V = simd<_Tp, _Abi>; 1307 using namespace std::experimental::__float_bitwise_operators; 1308 _GLIBCXX_SIMD_USE_CONSTEXPR_API auto __signmask = _V(1) ^ _V(-1); 1309 return (__x & ~__signmask) | (__y & __signmask); 1313 _GLIBCXX_SIMD_MATH_CALL2_(nextafter, _Tp) 1314 // not covered in [parallel.simd.math]: 1315 // _GLIBCXX_SIMD_MATH_CALL2_(nexttoward, long double) 1316 _GLIBCXX_SIMD_MATH_CALL2_(fdim, _Tp) 1317 _GLIBCXX_SIMD_MATH_CALL2_(fmax, _Tp) 1318 _GLIBCXX_SIMD_MATH_CALL2_(fmin, _Tp) 1320 _GLIBCXX_SIMD_MATH_CALL3_(fma, _Tp, _Tp) 1321 _GLIBCXX_SIMD_MATH_CALL_(fpclassify) 1322 _GLIBCXX_SIMD_MATH_CALL_(isfinite) 1324 // isnan and isinf require special treatment because old glibc may declare 1325 // `int isinf(double)`. 1326 template <typename _Tp, typename _Abi, typename..., 1327 typename _R = _Math_return_type_t<bool, _Tp, _Abi>> 1328 _GLIBCXX_SIMD_ALWAYS_INLINE 1329 enable_if_t<is_floating_point_v<_Tp>, _R> 1330 isinf(simd<_Tp, _Abi> __x) 1331 { return {__private_init, _Abi::_SimdImpl::_S_isinf(__data(__x))}; } 1333 template <typename _Tp, typename _Abi, typename..., 1334 typename _R = _Math_return_type_t<bool, _Tp, _Abi>> 1335 _GLIBCXX_SIMD_ALWAYS_INLINE 1336 enable_if_t<is_floating_point_v<_Tp>, _R> 1337 isnan(simd<_Tp, _Abi> __x) 1338 { return {__private_init, _Abi::_SimdImpl::_S_isnan(__data(__x))}; } 1340 _GLIBCXX_SIMD_MATH_CALL_(isnormal) 1342 template <typename..., typename _Tp, typename _Abi> 1343 _GLIBCXX_SIMD_ALWAYS_INLINE 1344 simd_mask<_Tp, _Abi> 1345 signbit(simd<_Tp, _Abi> __x) 1347 if constexpr (is_integral_v<_Tp>) 1349 if constexpr (is_unsigned_v<_Tp>) 1350 return simd_mask<_Tp, _Abi>{}; // false 1355 return {__private_init, _Abi::_SimdImpl::_S_signbit(__data(__x))}; 1358 _GLIBCXX_SIMD_MATH_CALL2_(isgreater, _Tp) 1359 _GLIBCXX_SIMD_MATH_CALL2_(isgreaterequal, _Tp) 1360 _GLIBCXX_SIMD_MATH_CALL2_(isless, _Tp) 1361 _GLIBCXX_SIMD_MATH_CALL2_(islessequal, _Tp) 1362 _GLIBCXX_SIMD_MATH_CALL2_(islessgreater, _Tp) 1363 _GLIBCXX_SIMD_MATH_CALL2_(isunordered, _Tp) 1365 /* not covered in [parallel.simd.math] 1366 template <typename _Abi> __doublev<_Abi> nan(const char* tagp); 1367 template <typename _Abi> __floatv<_Abi> nanf(const char* tagp); 1368 template <typename _Abi> __ldoublev<_Abi> nanl(const char* tagp); 1370 template <typename _V> struct simd_div_t { 1374 template <typename _Abi> 1375 simd_div_t<_SCharv<_Abi>> div(_SCharv<_Abi> numer, 1376 _SCharv<_Abi> denom); 1377 template <typename _Abi> 1378 simd_div_t<__shortv<_Abi>> div(__shortv<_Abi> numer, 1379 __shortv<_Abi> denom); 1380 template <typename _Abi> 1381 simd_div_t<__intv<_Abi>> div(__intv<_Abi> numer, __intv<_Abi> denom); 1382 template <typename _Abi> 1383 simd_div_t<__longv<_Abi>> div(__longv<_Abi> numer, 1384 __longv<_Abi> denom); 1385 template <typename _Abi> 1386 simd_div_t<__llongv<_Abi>> div(__llongv<_Abi> numer, 1387 __llongv<_Abi> denom); 1391 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1392 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1393 assoc_laguerre(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1394 const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __m, 1395 const simd<_Tp, _Abi>& __x) 1397 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1398 return std::assoc_laguerre(__n[__i], __m[__i], __x[__i]); 1402 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1403 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1404 assoc_legendre(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1405 const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __m, 1406 const simd<_Tp, _Abi>& __x) 1408 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1409 return std::assoc_legendre(__n[__i], __m[__i], __x[__i]); 1413 _GLIBCXX_SIMD_MATH_CALL2_(beta, _Tp) 1414 _GLIBCXX_SIMD_MATH_CALL_(comp_ellint_1) 1415 _GLIBCXX_SIMD_MATH_CALL_(comp_ellint_2) 1416 _GLIBCXX_SIMD_MATH_CALL2_(comp_ellint_3, _Tp) 1417 _GLIBCXX_SIMD_MATH_CALL2_(cyl_bessel_i, _Tp) 1418 _GLIBCXX_SIMD_MATH_CALL2_(cyl_bessel_j, _Tp) 1419 _GLIBCXX_SIMD_MATH_CALL2_(cyl_bessel_k, _Tp) 1420 _GLIBCXX_SIMD_MATH_CALL2_(cyl_neumann, _Tp) 1421 _GLIBCXX_SIMD_MATH_CALL2_(ellint_1, _Tp) 1422 _GLIBCXX_SIMD_MATH_CALL2_(ellint_2, _Tp) 1423 _GLIBCXX_SIMD_MATH_CALL3_(ellint_3, _Tp, _Tp) 1424 _GLIBCXX_SIMD_MATH_CALL_(expint) 1426 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1427 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1428 hermite(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1429 const simd<_Tp, _Abi>& __x) 1431 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1432 return std::hermite(__n[__i], __x[__i]); 1436 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1437 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1438 laguerre(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1439 const simd<_Tp, _Abi>& __x) 1441 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1442 return std::laguerre(__n[__i], __x[__i]); 1446 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1447 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1448 legendre(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1449 const simd<_Tp, _Abi>& __x) 1451 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1452 return std::legendre(__n[__i], __x[__i]); 1456 _GLIBCXX_SIMD_MATH_CALL_(riemann_zeta) 1458 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1459 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1460 sph_bessel(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1461 const simd<_Tp, _Abi>& __x) 1463 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1464 return std::sph_bessel(__n[__i], __x[__i]); 1468 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1469 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1470 sph_legendre(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __l, 1471 const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __m, 1472 const simd<_Tp, _Abi>& theta) 1474 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1475 return std::assoc_legendre(__l[__i], __m[__i], theta[__i]); 1479 template <typename _Tp, typename _Abi, typename = __detail::__odr_helper> 1480 enable_if_t<is_floating_point_v<_Tp>, simd<_Tp, _Abi>> 1481 sph_neumann(const fixed_size_simd<unsigned, simd_size_v<_Tp, _Abi>>& __n, 1482 const simd<_Tp, _Abi>& __x) 1484 return simd<_Tp, _Abi>([&](auto __i) _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA { 1485 return std::sph_neumann(__n[__i], __x[__i]); 1490 #undef _GLIBCXX_SIMD_CVTING2 1491 #undef _GLIBCXX_SIMD_CVTING3 1492 #undef _GLIBCXX_SIMD_MATH_CALL_ 1493 #undef _GLIBCXX_SIMD_MATH_CALL2_ 1494 #undef _GLIBCXX_SIMD_MATH_CALL3_ 1496 _GLIBCXX_SIMD_END_NAMESPACE 1498 #endif // __cplusplus >= 201703L 1499 #endif // _GLIBCXX_EXPERIMENTAL_SIMD_MATH_H_ 1501 // vim: foldmethod=marker sw=2 ts=8 noet sts=2 ISO C++ entities toplevel namespace is std.
complex< _Tp > tan(const complex< _Tp > &)
Return complex tangent of z.
constexpr const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.
complex< _Tp > exp(const complex< _Tp > &)
Return complex base e exponential of z.
complex< _Tp > cos(const complex< _Tp > &)
Return complex cosine of z.
complex< _Tp > log10(const complex< _Tp > &)
Return complex base 10 logarithm of z.
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
complex< _Tp > cosh(const complex< _Tp > &)
Return complex hyperbolic cosine of z.
auto declval() noexcept -> decltype(__declval< _Tp >(0))
complex< _Tp > sinh(const complex< _Tp > &)
Return complex hyperbolic sine of z.
typename conditional< _Cond, _Iftrue, _Iffalse >::type conditional_t
Alias template for conditional.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
complex< _Tp > sqrt(const complex< _Tp > &)
Return complex square root of z.
_Tp fabs(const std::complex< _Tp > &)
fabs(__z) [8.1.8].
_Tp abs(const complex< _Tp > &)
Return magnitude of z.
complex< _Tp > log(const complex< _Tp > &)
Return complex natural logarithm of z.
complex< _Tp > tanh(const complex< _Tp > &)
Return complex hyperbolic tangent of z.
complex< _Tp > sin(const complex< _Tp > &)
Return complex sine of z.