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
12 #include <__algorithm/max.h>
14 #include <__math/abs.h>
15 #include <__math/exponential_functions.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>
21 #include <__utility/pair.h>
24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25 # pragma GCC system_header
29 #include <__undef_macros>
31 _LIBCPP_BEGIN_NAMESPACE_STD
35 inline _LIBCPP_HIDE_FROM_ABI
float hypot(float __x
, float __y
) _NOEXCEPT
{ return __builtin_hypotf(__x
, __y
); }
37 template <class = int>
38 _LIBCPP_HIDE_FROM_ABI
double hypot(double __x
, double __y
) _NOEXCEPT
{
39 return __builtin_hypot(__x
, __y
);
42 inline _LIBCPP_HIDE_FROM_ABI
long double hypot(long double __x
, long double __y
) _NOEXCEPT
{
43 return __builtin_hypotl(__x
, __y
);
46 template <class _A1
, class _A2
, __enable_if_t
<is_arithmetic
<_A1
>::value
&& is_arithmetic
<_A2
>::value
, int> = 0>
47 inline _LIBCPP_HIDE_FROM_ABI typename __promote
<_A1
, _A2
>::type
hypot(_A1 __x
, _A2 __y
) _NOEXCEPT
{
48 using __result_type
= typename __promote
<_A1
, _A2
>::type
;
49 static_assert(!(_IsSame
<_A1
, __result_type
>::value
&& _IsSame
<_A2
, __result_type
>::value
), "");
50 return __math::hypot((__result_type
)__x
, (__result_type
)__y
);
53 #if _LIBCPP_STD_VER >= 17
54 // Computes the three-dimensional hypotenuse: `std::hypot(x,y,z)`.
55 // The naive implementation might over-/underflow which is why this implementation is more involved:
56 // If the square of an argument might run into issues, we scale the arguments appropriately.
57 // See https://github.com/llvm/llvm-project/issues/92782 for a detailed discussion and summary.
58 template <class _Real
>
59 _LIBCPP_HIDE_FROM_ABI _Real
__hypot(_Real __x
, _Real __y
, _Real __z
) {
60 // Factors needed to determine if over-/underflow might happen
61 constexpr int __exp
= std::numeric_limits
<_Real
>::max_exponent
/ 2;
62 const _Real __overflow_threshold
= __math::ldexp(_Real(1), __exp
);
63 const _Real __overflow_scale
= __math::ldexp(_Real(1), -(__exp
+ 20));
65 // Scale arguments depending on their size
66 const _Real __max_abs
= std::max(__math::fabs(__x
), std::max(__math::fabs(__y
), __math::fabs(__z
)));
68 if (__max_abs
> __overflow_threshold
) { // x*x + y*y + z*z might overflow
69 __scale
= __overflow_scale
;
70 } else if (__max_abs
< 1 / __overflow_threshold
) { // x*x + y*y + z*z might underflow
71 __scale
= 1 / __overflow_scale
;
79 // Compute hypot of scaled arguments and undo scaling
80 return __math::sqrt(__x
* __x
+ __y
* __y
+ __z
* __z
) / __scale
;
83 inline _LIBCPP_HIDE_FROM_ABI
float hypot(float __x
, float __y
, float __z
) { return __math::__hypot(__x
, __y
, __z
); }
85 inline _LIBCPP_HIDE_FROM_ABI
double hypot(double __x
, double __y
, double __z
) { return __math::__hypot(__x
, __y
, __z
); }
87 inline _LIBCPP_HIDE_FROM_ABI
long double hypot(long double __x
, long double __y
, long double __z
) {
88 return __math::__hypot(__x
, __y
, __z
);
94 std::enable_if_t
< is_arithmetic_v
<_A1
> && is_arithmetic_v
<_A2
> && is_arithmetic_v
<_A3
>, int> = 0 >
95 _LIBCPP_HIDE_FROM_ABI typename __promote
<_A1
, _A2
, _A3
>::type
hypot(_A1 __x
, _A2 __y
, _A3 __z
) _NOEXCEPT
{
96 using __result_type
= typename __promote
<_A1
, _A2
, _A3
>::type
;
98 std::is_same_v
<_A1
, __result_type
> && std::is_same_v
<_A2
, __result_type
> && std::is_same_v
<_A3
, __result_type
>));
99 return __math::__hypot(
100 static_cast<__result_type
>(__x
), static_cast<__result_type
>(__y
), static_cast<__result_type
>(__z
));
104 } // namespace __math
106 _LIBCPP_END_NAMESPACE_STD
109 #endif // _LIBCPP___MATH_HYPOT_H