diff --git a/stl/inc/cmath b/stl/inc/cmath index af3714951..b979948e8 100644 --- a/stl/inc/cmath +++ b/stl/inc/cmath @@ -23,7 +23,7 @@ #endif // _HAS_CMATH_INTRINSICS #if _HAS_CXX20 -#include +#include #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) { diff --git a/stl/inc/complex b/stl/inc/complex index 28c14468c..029288392 100644 --- a/stl/inc/complex +++ b/stl/inc/complex @@ -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 , 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 , 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) diff --git a/stl/inc/numeric b/stl/inc/numeric index 6bad9695f..129fa371b 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -13,10 +13,6 @@ #include <__msvc_bit_utils.hpp> #endif // _HAS_CXX17 -#if _HAS_CXX20 -#include -#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 -constexpr _Flt _Floating_max{}; -template <> -inline constexpr float _Floating_max = FLT_MAX; -template <> -inline constexpr double _Floating_max = DBL_MAX; -template <> -inline constexpr long double _Floating_max = LDBL_MAX; - -template -constexpr _Flt _Floating_min{}; -template <> -inline constexpr float _Floating_min = FLT_MIN; -template <> -inline constexpr double _Floating_min = DBL_MIN; -template <> -inline constexpr long double _Floating_min = LDBL_MIN; - _EXPORT_STD template && !is_same_v, 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> / 2; + constexpr _Ty _High_limit = _Floating_type_traits>::_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> * 2; + constexpr _Ty _Low_limit = _Floating_type_traits>::_Minimum_value * 2; if (_Val1_a < _Low_limit) { return _Val1 + _Val2 / 2; } diff --git a/stl/inc/type_traits b/stl/inc/type_traits index a846aa1e1..cb7feb0e3 100644 --- a/stl/inc/type_traits +++ b/stl/inc/type_traits @@ -2443,6 +2443,9 @@ struct _Floating_type_traits { 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 { 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 , 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 , int> = 0> +_NODISCARD constexpr _Ty _Float_abs(const _Ty _Xx) noexcept { // constexpr floating-point abs() + return _Bit_cast<_Ty>(_Float_abs_bits(_Xx)); +} + +template , 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 , 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 using _Maybe_const = conditional_t<_IsConst, const _Ty, _Ty>; diff --git a/stl/inc/xutility b/stl/inc/xutility index c8bd9d91d..d7523937d 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -7354,56 +7354,6 @@ struct _CXX17_DEPRECATE_ITERATOR_BASE_CLASS iterator { // base type for iterator using reference = _Reference; }; -template , 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 , int> = 0> -_NODISCARD constexpr _Ty _Float_abs(const _Ty _Xx) noexcept { // constexpr floating-point abs() - return _Bit_cast<_Ty>(_Float_abs_bits(_Xx)); -} - -template , 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 , 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 , 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 , 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 , 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