Skip to content

Commit

Permalink
Move _Floating_type_traits-related functions (#4615)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
frederick-vs-ja and StephanTLavavej authored Apr 26, 2024
1 parent 362228f commit 4ab1364
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 77 deletions.
11 changes: 8 additions & 3 deletions stl/inc/cmath
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
#endif // _HAS_CMATH_INTRINSICS

#if _HAS_CXX20
#include <xutility>
#include <type_traits>
#endif // _HAS_CXX20

#pragma pack(push, _CRT_PACKING)
Expand Down Expand Up @@ -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) {
Expand Down
16 changes: 16 additions & 0 deletions stl/inc/complex
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
26 changes: 2 additions & 24 deletions stl/inc/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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>) {
Expand All @@ -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) {
Expand All @@ -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;
}
Expand Down
31 changes: 31 additions & 0 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -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 <>
Expand All @@ -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 <>
Expand All @@ -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>;

Expand Down
50 changes: 0 additions & 50 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 4ab1364

Please sign in to comment.