Merge pull request #1213 from spevans/pr_nsnumber_fixes1
diff --git a/Foundation/NSNumber.swift b/Foundation/NSNumber.swift
index 02429d2..11e5cdc 100644
--- a/Foundation/NSNumber.swift
+++ b/Foundation/NSNumber.swift
@@ -460,6 +460,12 @@
CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
return .init(truncatingIfNeeded: value.low)
}
+
+ private var int128Value: CFSInt128Struct {
+ var value = CFSInt128Struct(high: 0, low: 0)
+ CFNumberGetValue(_cfObject, kCFNumberSInt128Type, &value)
+ return value
+ }
open var floatValue: Float {
var value: Float = 0
@@ -516,22 +522,26 @@
}
open func compare(_ otherNumber: NSNumber) -> ComparisonResult {
- switch (objCType.pointee, otherNumber.objCType.pointee) {
- case (0x66, _), (_, 0x66), (0x66, 0x66): fallthrough // 'f' float
- case (0x64, _), (_, 0x64), (0x64, 0x64): // 'd' double
+ switch (_cfNumberType(), otherNumber._cfNumberType()) {
+ case (kCFNumberFloatType, _), (_, kCFNumberFloatType): fallthrough
+ case (kCFNumberDoubleType, _), (_, kCFNumberDoubleType):
let (lhs, rhs) = (doubleValue, otherNumber.doubleValue)
+ // Apply special handling for NaN as <, >, == always return false
+ // when comparing with NaN
+ if lhs.isNaN && rhs.isNaN { return .orderedSame }
+ if lhs.isNaN { return .orderedAscending }
+ if rhs.isNaN { return .orderedDescending }
+
if lhs < rhs { return .orderedAscending }
if lhs > rhs { return .orderedDescending }
return .orderedSame
- case (0x51, _), (_, 0x51), (0x51, 0x51): // 'q' unsigned long long
- let (lhs, rhs) = (uint64Value, otherNumber.uint64Value)
- if lhs < rhs { return .orderedAscending }
- if lhs > rhs { return .orderedDescending }
- return .orderedSame
- case (_, _):
- let (lhs, rhs) = (int64Value, otherNumber.int64Value)
- if lhs < rhs { return .orderedAscending }
- if lhs > rhs { return .orderedDescending }
+
+ default: // For signed and unsigned integers expand upto S128Int
+ let (lhs, rhs) = (int128Value, otherNumber.int128Value)
+ if lhs.high < rhs.high { return .orderedAscending }
+ if lhs.high > rhs.high { return .orderedDescending }
+ if lhs.low < rhs.low { return .orderedAscending }
+ if lhs.low > rhs.low { return .orderedDescending }
return .orderedSame
}
}
diff --git a/TestFoundation/TestNSNumber.swift b/TestFoundation/TestNSNumber.swift
index 0e3ac08..b34d45c 100644
--- a/TestFoundation/TestNSNumber.swift
+++ b/TestFoundation/TestNSNumber.swift
@@ -1133,5 +1133,29 @@
XCTAssertTrue(NSNumber(value: UInt16.min) == NSNumber(value: Float(0)))
XCTAssertTrue(NSNumber(value: UInt16.max) == NSNumber(value: Double(65535)))
XCTAssertTrue(NSNumber(value: 1.1) != NSNumber(value: Int64(1)))
+ let num = NSNumber(value: Int8.min)
+ XCTAssertFalse(num == NSNumber(value: num.uint64Value))
+
+ let num1 = NSNumber(value: Float.nan)
+ XCTAssertEqual(num1.compare(num1), ComparisonResult.orderedSame)
+
+ let num2 = NSNumber(value: num1.uint8Value) // 0
+ XCTAssertFalse(num1 == num2)
+ XCTAssertFalse(num2 == num1)
+ XCTAssertEqual(num1.compare(num2), ComparisonResult.orderedAscending)
+ XCTAssertEqual(num2.compare(num1), ComparisonResult.orderedDescending)
+
+ let num3 = NSNumber(value: Double.nan)
+ XCTAssertEqual(num3.compare(num3), ComparisonResult.orderedSame)
+
+ let num4 = NSNumber(value: num3.intValue) // 0
+ XCTAssertFalse(num3 == num2)
+ XCTAssertFalse(num4 == num3)
+ XCTAssertEqual(num3.compare(num4), ComparisonResult.orderedAscending)
+ XCTAssertEqual(num4.compare(num3), ComparisonResult.orderedDescending)
+
+ XCTAssertEqual(NSNumber(value: Double.leastNonzeroMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
+ XCTAssertEqual(NSNumber(value: Double.greatestFiniteMagnitude).compare(NSNumber(value: 0)), ComparisonResult.orderedDescending)
+ XCTAssertTrue(NSNumber(value: Double(-0.0)) == NSNumber(value: Double(0.0)))
}
}