1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___MATH_HYPOT_H
10 #define _LIBCPP___MATH_HYPOT_H
13 #include <__math/abs.h>
14 #include <__math/exponential_functions.h>
15 #include <__math/min_max.h>
16 #include <__math/roots.h>
17 #include <__type_traits/enable_if.h>
18 #include <__type_traits/is_arithmetic.h>
19 #include <__type_traits/is_same.h>
20 #include <__type_traits/promote.h>
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 # pragma GCC system_header
28 #include <__undef_macros>
30 _LIBCPP_BEGIN_NAMESPACE_STD
34 inline _LIBCPP_HIDE_FROM_ABI
float hypot(float __x
, float __y
) _NOEXCEPT
{ return __builtin_hypotf(__x
, __y
); }
36 template <class = int>
37 _LIBCPP_HIDE_FROM_ABI
double hypot(double __x
, double __y
) _NOEXCEPT
{
38 return __builtin_hypot(__x
, __y
);
41 inline _LIBCPP_HIDE_FROM_ABI
long double hypot(long double __x
, long double __y
) _NOEXCEPT
{
42 return __builtin_hypotl(__x
, __y
);
45 template <class _A1
, class _A2
, __enable_if_t
<is_arithmetic
<_A1
>::value
&& is_arithmetic
<_A2
>::value
, int> = 0>
46 inline _LIBCPP_HIDE_FROM_ABI typename __promote
<_A1
, _A2
>::type
hypot(_A1 __x
, _A2 __y
) _NOEXCEPT
{
47 using __result_type
= typename __promote
<_A1
, _A2
>::type
;
48 static_assert(!(_IsSame
<_A1
, __result_type
>::value
&& _IsSame
<_A2
, __result_type
>::value
), "");
49 return __math::hypot((__result_type
)__x
, (__result_type
)__y
);
52 #if _LIBCPP_STD_VER >= 17
53 // Computes the three-dimensional hypotenuse: `std::hypot(x,y,z)`.
54 // The naive implementation might over-/underflow which is why this implementation is more involved:
55 // If the square of an argument might run into issues, we scale the arguments appropriately.
56 // See https://github.com/llvm/llvm-project/issues/92782 for a detailed discussion and summary.
57 template <class _Real
>
58 _LIBCPP_HIDE_FROM_ABI _Real
__hypot(_Real __x
, _Real __y
, _Real __z
) {
59 // Factors needed to determine if over-/underflow might happen
60 constexpr int __exp
= std::numeric_limits
<_Real
>::max_exponent
/ 2;
61 const _Real __overflow_threshold
= __math::ldexp(_Real(1), __exp
);
62 const _Real __overflow_scale
= __math::ldexp(_Real(1), -(__exp
+ 20));
64 // Scale arguments depending on their size
65 const _Real __max_abs
= __math::fmax(__math::fabs(__x
), __math::fmax(__math::fabs(__y
), __math::fabs(__z
)));
67 if (__max_abs
> __overflow_threshold
) { // x*x + y*y + z*z might overflow
68 __scale
= __overflow_scale
;
69 } else if (__max_abs
< 1 / __overflow_threshold
) { // x*x + y*y + z*z might underflow
70 __scale
= 1 / __overflow_scale
;
78 // Compute hypot of scaled arguments and undo scaling
79 return __math::sqrt(__x
* __x
+ __y
* __y
+ __z
* __z
) / __scale
;
82 inline _LIBCPP_HIDE_FROM_ABI
float hypot(float __x
, float __y
, float __z
) { return __math::__hypot(__x
, __y
, __z
); }
84 inline _LIBCPP_HIDE_FROM_ABI
double hypot(double __x
, double __y
, double __z
) { return __math::__hypot(__x
, __y
, __z
); }
86 inline _LIBCPP_HIDE_FROM_ABI
long double hypot(long double __x
, long double __y
, long double __z
) {
87 return __math::__hypot(__x
, __y
, __z
);
93 std::enable_if_t
< is_arithmetic_v
<_A1
> && is_arithmetic_v
<_A2
> && is_arithmetic_v
<_A3
>, int> = 0 >
94 _LIBCPP_HIDE_FROM_ABI typename __promote
<_A1
, _A2
, _A3
>::type
hypot(_A1 __x
, _A2 __y
, _A3 __z
) _NOEXCEPT
{
95 using __result_type
= typename __promote
<_A1
, _A2
, _A3
>::type
;
97 std::is_same_v
<_A1
, __result_type
> && std::is_same_v
<_A2
, __result_type
> && std::is_same_v
<_A3
, __result_type
>));
98 return __math::__hypot(
99 static_cast<__result_type
>(__x
), static_cast<__result_type
>(__y
), static_cast<__result_type
>(__z
));
103 } // namespace __math
105 _LIBCPP_END_NAMESPACE_STD
108 #endif // _LIBCPP___MATH_HYPOT_H