@@ -1658,32 +1658,26 @@ extension BinaryInteger {
1658
1658
public static func == <
1659
1659
Other: BinaryInteger
1660
1660
> ( lhs: Self , rhs: Other ) -> Bool {
1661
- let rhs_ = Self ( truncatingIfNeeded: rhs)
1662
- // Is `rhs` representable as a value of `Self` type? In other words, does
1663
- // the bit pattern conversion above preserve the value of `rhs`?
1664
- //
1665
- // To find out the answer, we see if the value roundtrips by bit pattern
1666
- // conversion back to `Self` [1], and we also check that the original bit
1667
- // pattern conversion doesn't change the sign [2].
1668
- if Other ( truncatingIfNeeded: rhs_) == rhs /* [1] */
1669
- && ( rhs < ( 0 as Other ) ) == ( rhs_ < ( 0 as Self ) ) /* [2] */ {
1670
- return lhs == rhs_
1661
+ // Use bit pattern conversion to widen the comparand with smaller bit width.
1662
+ if Self . isSigned == Other . isSigned {
1663
+ return lhs. bitWidth >= rhs. bitWidth ?
1664
+ lhs == Self ( truncatingIfNeeded: rhs) :
1665
+ Other ( truncatingIfNeeded: lhs) == rhs
1671
1666
}
1672
-
1673
- let lhs_ = Other ( truncatingIfNeeded: lhs)
1674
- // Is `lhs` representable as a value of `Other` type?
1675
- if Self ( truncatingIfNeeded: lhs_) == lhs
1676
- && ( lhs < ( 0 as Self ) ) == ( lhs_ < ( 0 as Other ) ) {
1677
- return lhs_ == rhs
1667
+ // If `Self` is signed but `Other` is unsigned, then we have to
1668
+ // be a little more careful about widening, since:
1669
+ // (1) a fixed-width signed type can't represent the largest values of
1670
+ // a fixed-width unsigned type of equal bit width; and
1671
+ // (2) an unsigned type (obviously) can't represent a negative value.
1672
+ if Self . isSigned {
1673
+ return lhs. bitWidth > rhs. bitWidth ? // (1)
1674
+ lhs == Self ( truncatingIfNeeded: rhs) :
1675
+ lhs < ( 0 as Self ) ? false : Other ( truncatingIfNeeded: lhs) == rhs // (2)
1678
1676
}
1679
-
1680
- // If we're here, then either:
1681
- // - `Self` is signed and fixed-width, `Other` is unsigned,
1682
- // `lhs` is negative, and `rhs` is greater than `Self.max`; or
1683
- // - `Other` is signed and fixed-width, `Self` is unsigned,
1684
- // `rhs` is negative, and `lhs` is greater than `Other.max`.
1685
- // Thus, `lhs != rhs`.
1686
- return false
1677
+ // Analogous reasoning applies if `Other` is signed but `Self` is not.
1678
+ return lhs. bitWidth < rhs. bitWidth ?
1679
+ Other ( truncatingIfNeeded: lhs) == rhs :
1680
+ rhs < ( 0 as Other ) ? false : lhs == Self ( truncatingIfNeeded: rhs)
1687
1681
}
1688
1682
1689
1683
/// Returns a Boolean value indicating whether the two given values are not
@@ -1723,32 +1717,26 @@ extension BinaryInteger {
1723
1717
/// - rhs: Another integer to compare.
1724
1718
@_transparent
1725
1719
public static func < < Other: BinaryInteger > ( lhs: Self , rhs: Other ) -> Bool {
1726
- let rhs_ = Self ( truncatingIfNeeded: rhs)
1727
- // Is `rhs` representable as a value of `Self` type? In other words, does
1728
- // the bitcast operation above preserve the value of `rhs`?
1729
- //
1730
- // To find out the answer, we see if the value roundtrips by bitcasting back
1731
- // to `Self` [1], and we also check that bitcasting doesn't change the sign
1732
- // [2].
1733
- if Other ( truncatingIfNeeded: rhs_) == rhs /* [1] */
1734
- && ( rhs < ( 0 as Other ) ) == ( rhs_ < ( 0 as Self ) ) /* [2] */ {
1735
- return lhs < rhs_
1720
+ // Use bit pattern conversion to widen the comparand with smaller bit width.
1721
+ if Self . isSigned == Other . isSigned {
1722
+ return lhs. bitWidth >= rhs. bitWidth ?
1723
+ lhs < Self ( truncatingIfNeeded: rhs) :
1724
+ Other ( truncatingIfNeeded: lhs) < rhs
1736
1725
}
1737
-
1738
- let lhs_ = Other ( truncatingIfNeeded: lhs)
1739
- // Is `lhs` representable as a value of `Other` type?
1740
- if Self ( truncatingIfNeeded: lhs_) == lhs
1741
- && ( lhs < ( 0 as Self ) ) == ( lhs_ < ( 0 as Other ) ) {
1742
- return lhs_ < rhs
1726
+ // If `Self` is signed but `Other` is unsigned, then we have to
1727
+ // be a little more careful about widening, since:
1728
+ // (1) a fixed-width signed type can't represent the largest values of
1729
+ // a fixed-width unsigned type of equal bit width; and
1730
+ // (2) an unsigned type (obviously) can't represent a negative value.
1731
+ if Self . isSigned {
1732
+ return lhs. bitWidth > rhs. bitWidth ? // (1)
1733
+ lhs < Self ( truncatingIfNeeded: rhs) :
1734
+ lhs < ( 0 as Self ) ? true : Other ( truncatingIfNeeded: lhs) < rhs // (2)
1743
1735
}
1744
-
1745
- // If we're here, then either:
1746
- // - `Self` is signed and fixed-width, `Other` is unsigned,
1747
- // `lhs` is negative, and `rhs` is greater than `Self.max`; or
1748
- // - `Other` is signed and fixed-width, `Self` is unsigned,
1749
- // `rhs` is negative, and `lhs` is greater than `Other.max`.
1750
- // Thus, `lhs < rhs` if and only if `Self.isSigned`.
1751
- return Self . isSigned
1736
+ // Analogous reasoning applies if `Other` is signed but `Self` is not.
1737
+ return lhs. bitWidth < rhs. bitWidth ?
1738
+ Other ( truncatingIfNeeded: lhs) < rhs :
1739
+ rhs < ( 0 as Other ) ? false : lhs < Self ( truncatingIfNeeded: rhs)
1752
1740
}
1753
1741
1754
1742
/// Returns a Boolean value indicating whether the value of the first
0 commit comments