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)))
     }
 }