diff --git a/Sources/FoundationEssentials/Decimal/Decimal+Conformances.swift b/Sources/FoundationEssentials/Decimal/Decimal+Conformances.swift index deef13c0a..440482841 100644 --- a/Sources/FoundationEssentials/Decimal/Decimal+Conformances.swift +++ b/Sources/FoundationEssentials/Decimal/Decimal+Conformances.swift @@ -458,28 +458,6 @@ extension Decimal: Hashable { } } - internal var doubleValue: Double { - if _length == 0 { - return _isNegative == 1 ? Double.nan : 0 - } - - var d = 0.0 - for idx in (0.. 20 { + return 0 + } + if self._length == 0 || self.isZero || self.magnitude < (0 as Decimal) { + return 0 + } + var value = self.significand + + for _ in 0 ..< abs(self._exponent) { + if self._exponent < 0 { + if let result = try? value._divide(by: 10) { + value = result.result + } + } else { + if let result = try? value._multiply(byShort: 10) { + value = result + } + } + } + return UInt64(value._mantissa.3) << 48 | UInt64(value._mantissa.2) << 32 | UInt64(value._mantissa.1) << 16 | UInt64(value._mantissa.0) + } + + internal var int64Value: Int64 { + let uint64Value = self._unsignedInt64Value + if self._isNegative > 0 { + if uint64Value == Int64.max.magnitude + 1 { + return Int64.min + } + if uint64Value <= Int64.max.magnitude { + var value = Int64(uint64Value) + value.negate() + return value + } + } + return Int64(bitPattern: uint64Value) + } + + internal var uint64Value: UInt64 { + let value = self._unsignedInt64Value + if self._isNegative == 0 { + return value + } + if value == Int64.max.magnitude + 1 { + return UInt64(bitPattern: Int64.min) + } + if value <= Int64.max.magnitude { + var value = Int64(value) + value.negate() + return UInt64(bitPattern: value) + } + return value + } +} + // MARK: - Integer Mathmatics extension Decimal { typealias VariableLengthInteger = [UInt16] diff --git a/Tests/FoundationEssentialsTests/DecimalTests.swift b/Tests/FoundationEssentialsTests/DecimalTests.swift index 6239b2768..440c75e8d 100644 --- a/Tests/FoundationEssentialsTests/DecimalTests.swift +++ b/Tests/FoundationEssentialsTests/DecimalTests.swift @@ -1025,4 +1025,27 @@ final class DecimalTests : XCTestCase { XCTAssertNotEqual(x.nextDown, x) XCTAssertNotEqual(x.nextUp, x) } + + func test_int64Value() { + XCTAssertEqual(Decimal(-1).int64Value, -1) + XCTAssertEqual(Decimal(0).int64Value, 0) + XCTAssertEqual(Decimal(1).int64Value, 1) + XCTAssertEqual(Decimal.nan.int64Value, 0) + XCTAssertEqual(Decimal(1e50).int64Value, 0) + XCTAssertEqual(Decimal(1e-50).int64Value, 0) + + XCTAssertEqual(Decimal(UInt64.max).uint64Value, UInt64.max) + XCTAssertEqual((Decimal(UInt64.max) + 1).uint64Value, 0) + XCTAssertEqual(Decimal(Int64.max).int64Value, Int64.max) + XCTAssertEqual((Decimal(Int64.max) + 1 ).int64Value, Int64.min) + XCTAssertEqual((Decimal(Int64.max) + 1 ).uint64Value, UInt64(Int64.max) + 1) + XCTAssertEqual(Decimal(Int64.min).int64Value, Int64.min) + + XCTAssertEqual(Decimal(Int.min).int64Value, Int64(Int.min)) + + let div3 = Decimal(10) / 3 + XCTAssertEqual(div3.int64Value, 3) + let pi = Decimal(Double.pi) + XCTAssertEqual(pi.int64Value, 3) + } }