Skip to content

Commit 376c6b2

Browse files
committed
Fix implementation of Decimal.nextUp.
1 parent aed94d4 commit 376c6b2

File tree

4 files changed

+58
-0
lines changed

4 files changed

+58
-0
lines changed

Darwin/Foundation-swiftoverlay-Tests/TestDecimal.swift

+12
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,18 @@ class TestDecimal : XCTestCase {
617617
XCTAssertNotEqual(x.nextDown, x)
618618
XCTAssertNotEqual(x.nextUp, x)
619619

620+
// For similar reasons, '3.40282366920938463463374607431768211455',
621+
// which has the same significand as 'Decimal.greatestFiniteMagnitude',
622+
// is an important value to test because the distance to the next
623+
// representable value is more than 'ulp' and instead requires
624+
// incrementing '_exponent'.
625+
x = Decimal(string: "3.40282366920938463463374607431768211455")!
626+
XCTAssertEqual(x.ulp, Decimal(string: "0.00000000000000000000000000000000000001")!)
627+
XCTAssertEqual(x.nextUp, Decimal(string: "3.4028236692093846346337460743176821146")!)
628+
x = Decimal(string: "3.4028236692093846346337460743176821146")!
629+
XCTAssertEqual(x.ulp, Decimal(string: "0.0000000000000000000000000000000000001")!)
630+
XCTAssertEqual(x.nextDown, Decimal(string: "3.40282366920938463463374607431768211455")!)
631+
620632
x = 1
621633
XCTAssertEqual(x.ulp, Decimal(string: "1e-38")!)
622634
XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-38")!)

Darwin/Foundation-swiftoverlay/Decimal.swift

+17
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,23 @@ extension Decimal {
620620
}
621621

622622
public var nextUp: Decimal {
623+
if _isNegative == 1 {
624+
if _exponent > -128
625+
&& (_mantissa.0, _mantissa.1, _mantissa.2, _mantissa.3) == (0x999a, 0x9999, 0x9999, 0x9999)
626+
&& (_mantissa.4, _mantissa.5, _mantissa.6, _mantissa.7) == (0x9999, 0x9999, 0x9999, 0x1999) {
627+
return Decimal(
628+
_exponent: _exponent &- 1, _length: 8, _isNegative: 1, _isCompact: 1,
629+
_reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff))
630+
}
631+
} else {
632+
if _exponent < 127
633+
&& (_mantissa.0, _mantissa.1, _mantissa.2, _mantissa.3) == (0xffff, 0xffff, 0xffff, 0xffff)
634+
&& (_mantissa.4, _mantissa.5, _mantissa.6, _mantissa.7) == (0xffff, 0xffff, 0xffff, 0xffff) {
635+
return Decimal(
636+
_exponent: _exponent &+ 1, _length: 8, _isNegative: 0, _isCompact: 1,
637+
_reserved: 0, _mantissa: (0x999a, 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x1999))
638+
}
639+
}
623640
return self + ulp
624641
}
625642

Sources/Foundation/Decimal.swift

+17
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,23 @@ extension Decimal {
831831
}
832832

833833
public var nextUp: Decimal {
834+
if _isNegative == 1 {
835+
if _exponent > -128
836+
&& (_mantissa.0, _mantissa.1, _mantissa.2, _mantissa.3) == (0x999a, 0x9999, 0x9999, 0x9999)
837+
&& (_mantissa.4, _mantissa.5, _mantissa.6, _mantissa.7) == (0x9999, 0x9999, 0x9999, 0x1999) {
838+
return Decimal(
839+
_exponent: _exponent &- 1, _length: 8, _isNegative: 1, _isCompact: 1,
840+
_reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff))
841+
}
842+
} else {
843+
if _exponent < 127
844+
&& (_mantissa.0, _mantissa.1, _mantissa.2, _mantissa.3) == (0xffff, 0xffff, 0xffff, 0xffff)
845+
&& (_mantissa.4, _mantissa.5, _mantissa.6, _mantissa.7) == (0xffff, 0xffff, 0xffff, 0xffff) {
846+
return Decimal(
847+
_exponent: _exponent &+ 1, _length: 8, _isNegative: 0, _isCompact: 1,
848+
_reserved: 0, _mantissa: (0x999a, 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x1999))
849+
}
850+
}
834851
return self + ulp
835852
}
836853

Tests/Foundation/Tests/TestDecimal.swift

+12
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,18 @@ class TestDecimal: XCTestCase {
869869
XCTAssertNotEqual(x.nextDown, x)
870870
XCTAssertNotEqual(x.nextUp, x)
871871

872+
// For similar reasons, '3.40282366920938463463374607431768211455',
873+
// which has the same significand as 'Decimal.greatestFiniteMagnitude',
874+
// is an important value to test because the distance to the next
875+
// representable value is more than 'ulp' and instead requires
876+
// incrementing '_exponent'.
877+
x = Decimal(string: "3.40282366920938463463374607431768211455")!
878+
XCTAssertEqual(x.ulp, Decimal(string: "0.00000000000000000000000000000000000001")!)
879+
XCTAssertEqual(x.nextUp, Decimal(string: "3.4028236692093846346337460743176821146")!)
880+
x = Decimal(string: "3.4028236692093846346337460743176821146")!
881+
XCTAssertEqual(x.ulp, Decimal(string: "0.0000000000000000000000000000000000001")!)
882+
XCTAssertEqual(x.nextDown, Decimal(string: "3.40282366920938463463374607431768211455")!)
883+
872884
x = 1
873885
XCTAssertEqual(x.ulp, Decimal(string: "1e-38")!)
874886
XCTAssertEqual(x.nextDown, x - Decimal(string: "1e-38")!)

0 commit comments

Comments
 (0)