@@ -333,7 +333,7 @@ struct compare_three_way_result<_Ty1, _Ty2> {
333333struct compare_three_way {
334334 template <class _Ty1, class _Ty2>
335335 requires three_way_comparable_with<_Ty1, _Ty2> // TRANSITION, GH-489
336- constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
336+ _NODISCARD constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
337337 noexcept(noexcept(_STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right))) /* strengthened */ {
338338 return _STD forward<_Ty1>(_Left) <=> _STD forward<_Ty2>(_Right);
339339 }
@@ -396,35 +396,37 @@ namespace _Strong_order {
396396 using _Floating_type = decay_t<_Ty1>;
397397 using _Traits = _Floating_type_traits<_Floating_type>;
398398 using _Uint_type = typename _Traits::_Uint_type;
399+ using _Sint_type = make_signed_t<_Uint_type>;
399400
400- auto _Left_uint = _STD bit_cast<_Uint_type>(_Left);
401- auto _Right_uint = _STD bit_cast<_Uint_type>(_Right);
401+ const auto _Left_uint = _STD bit_cast<_Uint_type>(_Left);
402+ const auto _Right_uint = _STD bit_cast<_Uint_type>(_Right);
402403
403404 // 1. Ultra-fast path: equal representations are equal.
404405 if (_Left_uint == _Right_uint) {
405406 return strong_ordering::equal;
406407 }
407408
408409 // 2. Examine the sign bits.
409- const bool _Left_negative = ( _Left_uint & _Traits::_Shifted_sign_mask) != 0 ;
410- const bool _Right_negative = ( _Right_uint & _Traits::_Shifted_sign_mask) != 0 ;
410+ const _Uint_type _Left_shifted_sign = _Left_uint & _Traits::_Shifted_sign_mask;
411+ const _Uint_type _Right_shifted_sign = _Right_uint & _Traits::_Shifted_sign_mask;
411412
412- // 3. Fast path: any negative value is less than any positive value.
413- if (_Left_negative != _Right_negative) {
414- return _Left_negative ? strong_ordering::less : strong_ordering::greater;
415- }
413+ // 3. Interpret floating-point bit patterns as sign magnitude representations of integers,
414+ // and then transform them into ones' complement representation.
415+ // (Ones' complement representations of positive zero and negative zero are different.)
416+ const _Uint_type _Left_sign = _Left_shifted_sign >> _Traits::_Sign_shift;
417+ const _Uint_type _Right_sign = _Right_shifted_sign >> _Traits::_Sign_shift;
416418
417- // 4. Clear the (identical) sign bits. We've already stored them for use at the end.
418- _Left_uint &= ~_Traits::_Shifted_sign_mask;
419- _Right_uint &= ~_Traits::_Shifted_sign_mask;
419+ const _Uint_type _Left_xor = _Left_shifted_sign - _Left_sign;
420+ const _Uint_type _Right_xor = _Right_shifted_sign - _Right_sign;
420421
421- // 5. Perform the final comparison, reversed for negative values.
422- // (For example, 1.5 is less than 2.5, but -1.5 is greater than -2.5.)
423- if (_Left_negative) {
424- return _Right_uint <=> _Left_uint;
425- } else {
426- return _Left_uint <=> _Right_uint;
427- }
422+ const _Uint_type _Left_ones_complement_uint = _Left_uint ^ _Left_xor;
423+ const _Uint_type _Right_ones_complement_uint = _Right_uint ^ _Right_xor;
424+
425+ const auto _Left_ones_complement = static_cast<_Sint_type>(_Left_ones_complement_uint);
426+ const auto _Right_ones_complement = static_cast<_Sint_type>(_Right_ones_complement_uint);
427+
428+ // 4. Perform the final comparison.
429+ return _Left_ones_complement <=> _Right_ones_complement;
428430 } else if constexpr (_Strat == _St::_Three) {
429431 return static_cast<strong_ordering>(compare_three_way{}(_Left, _Right));
430432 } else {
@@ -498,6 +500,7 @@ namespace _Weak_order {
498500 using _Floating_type = decay_t<_Ty1>;
499501 using _Traits = _Floating_type_traits<_Floating_type>;
500502 using _Uint_type = typename _Traits::_Uint_type;
503+ using _Sint_type = make_signed_t<_Uint_type>;
501504
502505 auto _Left_uint = _STD bit_cast<_Uint_type>(_Left);
503506 auto _Right_uint = _STD bit_cast<_Uint_type>(_Right);
@@ -507,47 +510,42 @@ namespace _Weak_order {
507510 return weak_ordering::equivalent;
508511 }
509512
510- // 2. Fold negative zero into positive zero.
511- constexpr _Uint_type _Negative_zero = _Traits::_Shifted_sign_mask;
513+ // 2. Examine the sign bits.
514+ const _Uint_type _Left_shifted_sign = _Left_uint & _Traits::_Shifted_sign_mask;
515+ const _Uint_type _Right_shifted_sign = _Right_uint & _Traits::_Shifted_sign_mask;
512516
513- if (_Left_uint == _Negative_zero) {
514- _Left_uint = 0;
515- } else if (_Right_uint == _Negative_zero) { // The representations are known to be non-equal here.
516- _Right_uint = 0;
517- }
517+ // 3. Fold all NaN values together.
518+ // (The fact that _Infinity_plus_one represents a signaling NaN is irrelevant here.)
519+ constexpr _Uint_type _Infinity_plus_one = _Traits::_Shifted_exponent_mask + 1;
518520
519- // 3. Examine the sign bits.
520- const bool _Left_negative = (_Left_uint & _Traits::_Shifted_sign_mask) != 0;
521- const bool _Right_negative = (_Right_uint & _Traits::_Shifted_sign_mask) != 0;
521+ const _Uint_type _Left_magnitude = _Left_uint & ~_Traits::_Shifted_sign_mask;
522+ const _Uint_type _Right_magnitude = _Right_uint & ~_Traits::_Shifted_sign_mask;
522523
523- // 4. Fast path: after folding negative zero, any negative value is less than any positive value.
524- if (_Left_negative != _Right_negative) {
525- return _Left_negative ? weak_ordering::less : weak_ordering::greater;
524+ if (_Left_magnitude > _Infinity_plus_one) {
525+ _Left_uint = _Left_shifted_sign | _Infinity_plus_one;
526526 }
527527
528- // 5. Clear the (identical) sign bits. We've already stored them for use at the end.
529- _Left_uint &= ~_Traits::_Shifted_sign_mask ;
530- _Right_uint &= ~_Traits::_Shifted_sign_mask;
528+ if (_Right_magnitude > _Infinity_plus_one) {
529+ _Right_uint = _Right_shifted_sign | _Infinity_plus_one ;
530+ }
531531
532- // 6. Fold all NaN values together.
533- // (The fact that _Infinity_plus_one represents a signaling NaN is irrelevant here.)
534- constexpr _Uint_type _Infinity_plus_one = _Traits::_Shifted_exponent_mask + 1;
532+ // 4. Interpret floating-point bit patterns as sign magnitude representations of integers,
533+ // and then transform them into two's complement representation.
534+ // (Two's complement representations of positive zero and negative zero are the same.)
535+ const _Uint_type _Left_sign = _Left_shifted_sign >> _Traits::_Sign_shift;
536+ const _Uint_type _Right_sign = _Right_shifted_sign >> _Traits::_Sign_shift;
535537
536- if (_Left_uint > _Infinity_plus_one) {
537- _Left_uint = _Infinity_plus_one;
538- }
538+ const _Uint_type _Left_xor = _Left_shifted_sign - _Left_sign;
539+ const _Uint_type _Right_xor = _Right_shifted_sign - _Right_sign;
539540
540- if (_Right_uint > _Infinity_plus_one) {
541- _Right_uint = _Infinity_plus_one;
542- }
541+ const _Uint_type _Left_twos_complement_uint = (_Left_uint ^ _Left_xor) + _Left_sign;
542+ const _Uint_type _Right_twos_complement_uint = (_Right_uint ^ _Right_xor) + _Right_sign;
543543
544- // 7. Perform the final comparison, reversed for negative values.
545- // (For example, 1.5 is less than 2.5, but -1.5 is greater than -2.5.)
546- if (_Left_negative) {
547- return static_cast<weak_ordering>(_Right_uint <=> _Left_uint);
548- } else {
549- return static_cast<weak_ordering>(_Left_uint <=> _Right_uint);
550- }
544+ const auto _Left_twos_complement = static_cast<_Sint_type>(_Left_twos_complement_uint);
545+ const auto _Right_twos_complement = static_cast<_Sint_type>(_Right_twos_complement_uint);
546+
547+ // 5. Perform the final comparison.
548+ return static_cast<weak_ordering>(_Left_twos_complement <=> _Right_twos_complement);
551549 } else if constexpr (_Strat == _St::_Three) {
552550 return static_cast<weak_ordering>(compare_three_way{}(_Left, _Right));
553551 } else if constexpr (_Strat == _St::_Strong) {
0 commit comments