Move `_Floating_type_traits`-related functions (#4615)

Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
A. Jiang 2024-04-27 07:22:10 +08:00 коммит произвёл GitHub
Родитель 362228fcf0
Коммит 4ab1364084
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
5 изменённых файлов: 57 добавлений и 77 удалений

Просмотреть файл

@ -23,7 +23,7 @@
#endif // _HAS_CMATH_INTRINSICS
#if _HAS_CXX20
#include <xutility>
#include <type_traits>
#endif // _HAS_CXX20
#pragma pack(push, _CRT_PACKING)
@ -1505,8 +1505,13 @@ _NODISCARD constexpr _Ty _Linear_for_lerp(const _Ty _ArgA, const _Ty _ArgB, cons
auto _Abs_smaller = _Float_abs(_Smaller);
auto _Abs_larger = _Float_abs(_Larger);
if (_Abs_larger < _Abs_smaller) {
_STD swap(_Smaller, _Larger);
_STD swap(_Abs_smaller, _Abs_larger);
_Ty _Tmp = _Smaller;
_Smaller = _Larger;
_Larger = _Tmp;
_Tmp = _Abs_smaller;
_Abs_smaller = _Abs_larger;
_Abs_larger = _Tmp;
}
if (_Abs_smaller > 1) {

Просмотреть файл

@ -60,6 +60,22 @@ struct _C_ldouble_complex {
#define _IM 1
_STD_BEGIN
// TRANSITION, workaround x86 ABI
// On x86 ABI, floating-point by-value arguments and return values are passed in 80-bit x87 registers.
// When the value is a 32-bit or 64-bit signaling NaN, the conversion to/from 80-bit raises FE_INVALID
// and turns it into a quiet NaN. This behavior is undesirable if we want to test for signaling NaNs.
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_signaling_nan(const _Ty& _Xx) noexcept { // returns true if input is a signaling NaN
using _Traits = _Floating_type_traits<_Ty>;
const auto _Abs_bits = _Float_abs_bits(_Xx);
return _Abs_bits > _Traits::_Shifted_exponent_mask && ((_Abs_bits & _Traits::_Special_nan_mantissa_mask) == 0);
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_inf(const _Ty _Xx) noexcept { // constexpr isinf()
using _Traits = _Floating_type_traits<_Ty>;
return _Float_abs_bits(_Xx) == _Traits::_Shifted_exponent_mask;
}
// implements multi-precision floating-point arithmetic for numerical algorithms
#pragma float_control(precise, on, push)

Просмотреть файл

@ -13,10 +13,6 @@
#include <__msvc_bit_utils.hpp>
#endif // _HAS_CXX17
#if _HAS_CXX20
#include <cfloat>
#endif // _HAS_CXX20
#pragma pack(push, _CRT_PACKING)
#pragma warning(push, _STL_WARNING_LEVEL)
#pragma warning(disable : _STL_DISABLED_WARNINGS)
@ -645,24 +641,6 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n
#endif // _HAS_CXX17
#if _HAS_CXX20
template <class _Flt>
constexpr _Flt _Floating_max{};
template <>
inline constexpr float _Floating_max<float> = FLT_MAX;
template <>
inline constexpr double _Floating_max<double> = DBL_MAX;
template <>
inline constexpr long double _Floating_max<long double> = LDBL_MAX;
template <class _Flt>
constexpr _Flt _Floating_min{};
template <>
inline constexpr float _Floating_min<float> = FLT_MIN;
template <>
inline constexpr double _Floating_min<double> = DBL_MIN;
template <>
inline constexpr long double _Floating_min<long double> = LDBL_MIN;
_EXPORT_STD template <class _Ty, enable_if_t<is_arithmetic_v<_Ty> && !is_same_v<remove_cv_t<_Ty>, bool>, int> = 0>
_NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept {
if constexpr (is_floating_point_v<_Ty>) {
@ -681,7 +659,7 @@ _NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept {
}
}
constexpr _Ty _High_limit = _Floating_max<remove_cv_t<_Ty>> / 2;
constexpr _Ty _High_limit = _Floating_type_traits<remove_cv_t<_Ty>>::_Maximum_value / 2;
const auto _Val1_a = _Float_abs(_Val1);
const auto _Val2_a = _Float_abs(_Val2);
if (_Val1_a <= _High_limit && _Val2_a <= _High_limit) {
@ -705,7 +683,7 @@ _NODISCARD constexpr _Ty midpoint(const _Ty _Val1, const _Ty _Val2) noexcept {
// In the default rounding mode this less than one ULP difference will always be rounded away, so under
// /fp:fast we could avoid these tests if we had some means of detecting it in the caller.
constexpr _Ty _Low_limit = _Floating_min<remove_cv_t<_Ty>> * 2;
constexpr _Ty _Low_limit = _Floating_type_traits<remove_cv_t<_Ty>>::_Minimum_value * 2;
if (_Val1_a < _Low_limit) {
return _Val1 + _Val2 / 2;
}

Просмотреть файл

@ -2443,6 +2443,9 @@ struct _Floating_type_traits<float> {
static constexpr uint32_t _Special_nan_mantissa_mask = 0x00400000u; // 1u << (_Mantissa_bits - 2)
static constexpr uint32_t _Shifted_sign_mask = 0x80000000u; // 1u << _Sign_shift
static constexpr uint32_t _Shifted_exponent_mask = 0x7F800000u; // _Exponent_mask << _Exponent_shift
static constexpr float _Minimum_value = 0x1.000000p-126f; // FLT_MIN
static constexpr float _Maximum_value = 0x1.FFFFFEp+127f; // FLT_MAX
};
template <>
@ -2463,6 +2466,9 @@ struct _Floating_type_traits<double> {
static constexpr uint64_t _Special_nan_mantissa_mask = 0x0008000000000000u; // 1ULL << (_Mantissa_bits - 2)
static constexpr uint64_t _Shifted_sign_mask = 0x8000000000000000u; // 1ULL << _Sign_shift
static constexpr uint64_t _Shifted_exponent_mask = 0x7FF0000000000000u; // _Exponent_mask << _Exponent_shift
static constexpr double _Minimum_value = 0x1.0000000000000p-1022; // DBL_MIN
static constexpr double _Maximum_value = 0x1.FFFFFFFFFFFFFp+1023; // DBL_MAX
};
template <>
@ -2478,6 +2484,31 @@ _NODISCARD constexpr _To _Bit_cast(const _From& _Val) noexcept {
return __builtin_bit_cast(_To, _Val);
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr auto _Float_abs_bits(const _Ty& _Xx) noexcept {
using _Traits = _Floating_type_traits<_Ty>;
using _Uint_type = typename _Traits::_Uint_type;
const auto _Bits = _Bit_cast<_Uint_type>(_Xx);
return _Bits & ~_Traits::_Shifted_sign_mask;
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr _Ty _Float_abs(const _Ty _Xx) noexcept { // constexpr floating-point abs()
return _Bit_cast<_Ty>(_Float_abs_bits(_Xx));
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_nan(const _Ty _Xx) noexcept { // constexpr isnan()
using _Traits = _Floating_type_traits<_Ty>;
return _Float_abs_bits(_Xx) > _Traits::_Shifted_exponent_mask;
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_finite(const _Ty _Xx) noexcept { // constexpr isfinite()
using _Traits = _Floating_type_traits<_Ty>;
return _Float_abs_bits(_Xx) < _Traits::_Shifted_exponent_mask;
}
template <bool _IsConst, class _Ty>
using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>;

Просмотреть файл

@ -7354,56 +7354,6 @@ struct _CXX17_DEPRECATE_ITERATOR_BASE_CLASS iterator { // base type for iterator
using reference = _Reference;
};
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr auto _Float_abs_bits(const _Ty& _Xx) noexcept {
using _Traits = _Floating_type_traits<_Ty>;
using _Uint_type = typename _Traits::_Uint_type;
const auto _Bits = _Bit_cast<_Uint_type>(_Xx);
return _Bits & ~_Traits::_Shifted_sign_mask;
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr _Ty _Float_abs(const _Ty _Xx) noexcept { // constexpr floating-point abs()
return _Bit_cast<_Ty>(_Float_abs_bits(_Xx));
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr _Ty _Float_copysign(const _Ty _Magnitude, const _Ty _Sign) { // constexpr copysign()
using _Traits = _Floating_type_traits<_Ty>;
using _Uint_type = typename _Traits::_Uint_type;
const auto _Signbit = _Bit_cast<_Uint_type>(_Sign) & _Traits::_Shifted_sign_mask;
return _Bit_cast<_Ty>(_Float_abs_bits(_Magnitude) | _Signbit);
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_nan(const _Ty _Xx) noexcept { // constexpr isnan()
using _Traits = _Floating_type_traits<_Ty>;
return _Float_abs_bits(_Xx) > _Traits::_Shifted_exponent_mask;
}
// TRANSITION, workaround x86 ABI
// On x86 ABI, floating-point by-value arguments and return values are passed in 80-bit x87 registers.
// When the value is a 32-bit or 64-bit signaling NaN, the conversion to/from 80-bit raises FE_INVALID
// and turns it into a quiet NaN. This behavior is undesirable if we want to test for signaling NaNs.
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_signaling_nan(const _Ty& _Xx) noexcept { // returns true if input is a signaling NaN
using _Traits = _Floating_type_traits<_Ty>;
const auto _Abs_bits = _Float_abs_bits(_Xx);
return _Abs_bits > _Traits::_Shifted_exponent_mask && ((_Abs_bits & _Traits::_Special_nan_mantissa_mask) == 0);
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_inf(const _Ty _Xx) noexcept { // constexpr isinf()
using _Traits = _Floating_type_traits<_Ty>;
return _Float_abs_bits(_Xx) == _Traits::_Shifted_exponent_mask;
}
template <class _Ty, enable_if_t<is_floating_point_v<_Ty>, int> = 0>
_NODISCARD constexpr bool _Is_finite(const _Ty _Xx) noexcept { // constexpr isfinite()
using _Traits = _Floating_type_traits<_Ty>;
return _Float_abs_bits(_Xx) < _Traits::_Shifted_exponent_mask;
}
#if _HAS_CXX17
_EXPORT_STD struct monostate {};
#endif // _HAS_CXX17