Skip to content

Commit 40f392b

Browse files
committed
NSNumber: More Darwin compatibility fixes
- When comparing signed/unsigned integers, always compare both as SInt128. - Add special handling for comparing values with Float.nan and Double.nan.
1 parent e6fb426 commit 40f392b

File tree

2 files changed

+46
-12
lines changed

2 files changed

+46
-12
lines changed

Foundation/NSNumber.swift

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,12 @@ open class NSNumber : NSValue {
460460
CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
461461
return .init(truncatingIfNeeded: value.low)
462462
}
463+
464+
private var int128Value: CFSInt128Struct {
465+
var value = CFSInt128Struct(high: 0, low: 0)
466+
CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
467+
return value
468+
}
463469

464470
open var floatValue: Float {
465471
var value: Float = 0
@@ -516,22 +522,26 @@ open class NSNumber : NSValue {
516522
}
517523

518524
open func compare(_ otherNumber: NSNumber) -> ComparisonResult {
519-
switch (objCType.pointee, otherNumber.objCType.pointee) {
520-
case (0x66, _), (_, 0x66), (0x66, 0x66): fallthrough // 'f' float
521-
case (0x64, _), (_, 0x64), (0x64, 0x64): // 'd' double
525+
switch (_cfNumberType(), otherNumber._cfNumberType()) {
526+
case (kCFNumberFloatType, _), (_, kCFNumberFloatType): fallthrough
527+
case (kCFNumberDoubleType, _), (_, kCFNumberDoubleType):
522528
let (lhs, rhs) = (doubleValue, otherNumber.doubleValue)
529+
// Apply special handling for NaN as <, >, == always return false
530+
// when comparing with NaN
531+
if lhs.isNaN && rhs.isNaN { return .orderedSame }
532+
if lhs.isNaN { return .orderedAscending }
533+
if rhs.isNaN { return .orderedDescending }
534+
523535
if lhs < rhs { return .orderedAscending }
524536
if lhs > rhs { return .orderedDescending }
525537
return .orderedSame
526-
case (0x51, _), (_, 0x51), (0x51, 0x51): // 'q' unsigned long long
527-
let (lhs, rhs) = (uint64Value, otherNumber.uint64Value)
528-
if lhs < rhs { return .orderedAscending }
529-
if lhs > rhs { return .orderedDescending }
530-
return .orderedSame
531-
case (_, _):
532-
let (lhs, rhs) = (int64Value, otherNumber.int64Value)
533-
if lhs < rhs { return .orderedAscending }
534-
if lhs > rhs { return .orderedDescending }
538+
539+
default: // For signed and unsigned integers expand upto S128Int
540+
let (lhs, rhs) = (int128Value, otherNumber.int128Value)
541+
if lhs.high < rhs.high { return .orderedAscending }
542+
if lhs.high > rhs.high { return .orderedDescending }
543+
if lhs.low < rhs.low { return .orderedAscending }
544+
if lhs.low > rhs.low { return .orderedDescending }
535545
return .orderedSame
536546
}
537547
}

TestFoundation/TestNSNumber.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,5 +1133,29 @@ class TestNSNumber : XCTestCase {
11331133
XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: Float(0)))
11341134
XCTAssertTrue(NSNumber(value: UInt16.max) == NSNumber(value: Double(65535)))
11351135
XCTAssertTrue(NSNumber(value: 1.1) != NSNumber(value: Int64(1)))
1136+
let num = NSNumber(value: Int8.min)
1137+
XCTAssertFalse(num == NSNumber(value: num.uint64Value))
1138+
1139+
let num1 = NSNumber(value: Float.nan)
1140+
XCTAssertEqual(num1.compare(num1), ComparisonResult.orderedSame)
1141+
1142+
let num2 = NSNumber(value: num1.uint8Value) // 0
1143+
XCTAssertFalse(num1 == num2)
1144+
XCTAssertFalse(num2 == num1)
1145+
XCTAssertEqual(num1.compare(num2), ComparisonResult.orderedAscending)
1146+
XCTAssertEqual(num2.compare(num1), ComparisonResult.orderedDescending)
1147+
1148+
let num3 = NSNumber(value: Double.nan)
1149+
XCTAssertEqual(num3.compare(num3), ComparisonResult.orderedSame)
1150+
1151+
let num4 = NSNumber(value: num3.intValue) // 0
1152+
XCTAssertFalse(num3 == num2)
1153+
XCTAssertFalse(num4 == num3)
1154+
XCTAssertEqual(num3.compare(num4), ComparisonResult.orderedAscending)
1155+
XCTAssertEqual(num4.compare(num3), ComparisonResult.orderedDescending)
1156+
1157+
XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
1158+
XCTAssertEqual(NSNumber(value: Double.greatestFiniteMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
1159+
XCTAssertTrue(NSNumber(value: Double(-0.0)) == NSNumber(value: Double(0.0)))
11361160
}
11371161
}

0 commit comments

Comments
 (0)