@@ -1658,39 +1658,26 @@ extension BinaryInteger {
1658
1658
public static func == <
1659
1659
Other: BinaryInteger
1660
1660
> ( lhs: Self , rhs: Other ) -> Bool {
1661
- let lhsNegative = Self . isSigned && lhs < ( 0 as Self )
1662
- let rhsNegative = Other . isSigned && rhs < ( 0 as Other )
1663
-
1664
- if lhsNegative != rhsNegative { return false }
1665
-
1666
- // Here we know the values are of the same sign.
1667
- //
1668
- // There are a few possible scenarios from here:
1669
- //
1670
- // 1. Both values are negative
1671
- // - If one value is strictly wider than the other, then it is safe to
1672
- // convert to the wider type.
1673
- // - If the values are of the same width, it does not matter which type we
1674
- // choose to convert to as the values are already negative, and thus
1675
- // include the sign bit if two's complement representation already.
1676
- // 2. Both values are non-negative
1677
- // - If one value is strictly wider than the other, then it is safe to
1678
- // convert to the wider type.
1679
- // - If the values are of the same width, than signedness matters, as not
1680
- // unsigned types are 'wider' in a sense they don't need to 'waste' the
1681
- // sign bit. Therefore it is safe to convert to the unsigned type.
1682
-
1683
- if lhs. bitWidth < rhs. bitWidth {
1684
- return Other ( truncatingIfNeeded: lhs) == rhs
1685
- }
1686
- if lhs. bitWidth > rhs. bitWidth {
1687
- return lhs == Self ( truncatingIfNeeded: 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
1688
1666
}
1689
-
1690
- if Self . isSigned {
1691
- return Other ( truncatingIfNeeded: 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 ) && Other ( truncatingIfNeeded: lhs) == rhs) // (2)
1692
1676
}
1693
- return lhs == Self ( truncatingIfNeeded: rhs)
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 ) && lhs == Self ( truncatingIfNeeded: rhs) )
1694
1681
}
1695
1682
1696
1683
/// Returns a Boolean value indicating whether the two given values are not
@@ -1730,34 +1717,26 @@ extension BinaryInteger {
1730
1717
/// - rhs: Another integer to compare.
1731
1718
@_transparent
1732
1719
public static func < < Other: BinaryInteger > ( lhs: Self , rhs: Other ) -> Bool {
1733
- let lhsNegative = Self . isSigned && lhs < ( 0 as Self )
1734
- let rhsNegative = Other . isSigned && rhs < ( 0 as Other )
1735
- if lhsNegative != rhsNegative { return lhsNegative }
1736
-
1737
- if lhs == ( 0 as Self ) && rhs == ( 0 as Other ) { return false }
1738
-
1739
- // if we get here, lhs and rhs have the same sign. If they're negative,
1740
- // then Self and Other are both signed types, and one of them can represent
1741
- // values of the other type. Otherwise, lhs and rhs are positive, and one
1742
- // of Self, Other may be signed and the other unsigned.
1743
-
1744
- let rhsAsSelf = Self ( truncatingIfNeeded: rhs)
1745
- let rhsAsSelfNegative = rhsAsSelf < ( 0 as Self )
1746
-
1747
-
1748
- // Can we round-trip rhs through Other?
1749
- if Other ( truncatingIfNeeded: rhsAsSelf) == rhs &&
1750
- // This additional check covers the `Int8.max < (128 as UInt8)` case.
1751
- // Since the types are of the same width, init(truncatingIfNeeded:)
1752
- // will result in a simple bitcast, so that rhsAsSelf would be -128, and
1753
- // `lhs < rhsAsSelf` will return false.
1754
- // We basically guard against that bitcast by requiring rhs and rhsAsSelf
1755
- // to be the same sign.
1756
- rhsNegative == rhsAsSelfNegative {
1757
- return lhs < rhsAsSelf
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
1758
1725
}
1759
-
1760
- return Other ( truncatingIfNeeded: 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 ) || Other ( truncatingIfNeeded: lhs) < rhs) // (2)
1735
+ }
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 ) && lhs < Self ( truncatingIfNeeded: rhs) )
1761
1740
}
1762
1741
1763
1742
/// Returns a Boolean value indicating whether the value of the first
0 commit comments