Nikolas Klauser 34d4f0c136
[libc++][NFC] Use llvm.org/PR to link to bug reports (#156288)
We've built up quite a few links directly to github within the code
base. We should instead use `llvm.org/PR<issue-number>` to link to bugs,
since that is resilient to the bug tracker changing in the future. This
is especially relevant for tests linking to bugs, since they will
probably be there for decades to come. A nice side effect is that these
links are significantly shorter than the GH links, making them much less
of an eyesore.

This patch also replaces a few links that linked to the old bugzilla
instance on llvm.org.
2025-09-04 09:20:02 +02:00

109 lines
4.1 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___MATH_HYPOT_H
#define _LIBCPP___MATH_HYPOT_H
#include <__config>
#include <__math/abs.h>
#include <__math/exponential_functions.h>
#include <__math/min_max.h>
#include <__math/roots.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_arithmetic.h>
#include <__type_traits/is_same.h>
#include <__type_traits/promote.h>
#include <limits>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_PUSH_MACROS
#include <__undef_macros>
_LIBCPP_BEGIN_NAMESPACE_STD
namespace __math {
inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y) _NOEXCEPT { return __builtin_hypotf(__x, __y); }
template <class = int>
_LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y) _NOEXCEPT {
return __builtin_hypot(__x, __y);
}
inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y) _NOEXCEPT {
return __builtin_hypotl(__x, __y);
}
template <class _A1, class _A2, __enable_if_t<is_arithmetic<_A1>::value && is_arithmetic<_A2>::value, int> = 0>
inline _LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2> hypot(_A1 __x, _A2 __y) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2>;
static_assert(!(_IsSame<_A1, __result_type>::value && _IsSame<_A2, __result_type>::value), "");
return __math::hypot((__result_type)__x, (__result_type)__y);
}
#if _LIBCPP_STD_VER >= 17
// Computes the three-dimensional hypotenuse: `std::hypot(x,y,z)`.
// The naive implementation might over-/underflow which is why this implementation is more involved:
// If the square of an argument might run into issues, we scale the arguments appropriately.
// See https://llvm.org/PR92782 for a detailed discussion and summary.
template <class _Real>
_LIBCPP_HIDE_FROM_ABI _Real __hypot(_Real __x, _Real __y, _Real __z) {
// Factors needed to determine if over-/underflow might happen
constexpr int __exp = std::numeric_limits<_Real>::max_exponent / 2;
const _Real __overflow_threshold = __math::ldexp(_Real(1), __exp);
const _Real __overflow_scale = __math::ldexp(_Real(1), -(__exp + 20));
// Scale arguments depending on their size
const _Real __max_abs = __math::fmax(__math::fabs(__x), __math::fmax(__math::fabs(__y), __math::fabs(__z)));
_Real __scale;
if (__max_abs > __overflow_threshold) { // x*x + y*y + z*z might overflow
__scale = __overflow_scale;
} else if (__max_abs < 1 / __overflow_threshold) { // x*x + y*y + z*z might underflow
__scale = 1 / __overflow_scale;
} else {
__scale = 1;
}
__x *= __scale;
__y *= __scale;
__z *= __scale;
// Compute hypot of scaled arguments and undo scaling
return __math::sqrt(__x * __x + __y * __y + __z * __z) / __scale;
}
inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y, float __z) { return __math::__hypot(__x, __y, __z); }
inline _LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y, double __z) { return __math::__hypot(__x, __y, __z); }
inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y, long double __z) {
return __math::__hypot(__x, __y, __z);
}
template <class _A1,
class _A2,
class _A3,
std::enable_if_t< is_arithmetic_v<_A1> && is_arithmetic_v<_A2> && is_arithmetic_v<_A3>, int> = 0 >
_LIBCPP_HIDE_FROM_ABI __promote_t<_A1, _A2, _A3> hypot(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT {
using __result_type = __promote_t<_A1, _A2, _A3>;
static_assert(!(
std::is_same_v<_A1, __result_type> && std::is_same_v<_A2, __result_type> && std::is_same_v<_A3, __result_type>));
return __math::__hypot(
static_cast<__result_type>(__x), static_cast<__result_type>(__y), static_cast<__result_type>(__z));
}
#endif
} // namespace __math
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___MATH_HYPOT_H