Skip to content

Commit 713937f

Browse files
committed
Fix NSDecimalPower(_:_:_:_:) behavior
1 parent c0cd1d1 commit 713937f

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

Sources/Foundation/Decimal.swift

+17-5
Original file line numberDiff line numberDiff line change
@@ -1801,7 +1801,7 @@ public func NSDecimalPower(_ result: UnsafeMutablePointer<Decimal>, _ number: Un
18011801
return .overflow
18021802
}
18031803
NSDecimalCopy(result,number)
1804-
return result.pointee.power(UInt(power), roundingMode:roundingMode)
1804+
return result.pointee.power(power, roundingMode:roundingMode)
18051805
}
18061806

18071807
public func NSDecimalMultiplyByPowerOf10(_ result: UnsafeMutablePointer<Decimal>, _ number: UnsafePointer<Decimal>, _ power: Int16, _ roundingMode: NSDecimalNumber.RoundingMode) -> NSDecimalNumber.CalculationError {
@@ -2242,19 +2242,19 @@ extension Decimal {
22422242
_exponent = newExponent
22432243
return .noError
22442244
}
2245-
fileprivate mutating func power(_ p:UInt, roundingMode:RoundingMode) -> CalculationError {
2245+
fileprivate mutating func power(_ p:Int, roundingMode:RoundingMode) -> CalculationError {
22462246
if isNaN {
22472247
return .overflow
22482248
}
2249-
var power = p
2249+
var power = abs(p)
22502250
if power == 0 {
22512251
_exponent = 0
22522252
_length = 1
22532253
_isNegative = 0
22542254
self[0] = 1
22552255
_isCompact = 1
22562256
return .noError
2257-
} else if power == 1 {
2257+
} else if power == 1 || isZero {
22582258
return .noError
22592259
}
22602260

@@ -2297,7 +2297,19 @@ extension Decimal {
22972297
let previousError = error
22982298
var rightOp = self
22992299
error = NSDecimalMultiply(&self, &temporary, &rightOp, roundingMode)
2300-
2300+
2301+
// if power is negative, use multiplicative inverse
2302+
if p < 0 {
2303+
rightOp = self
2304+
2305+
error = NSDecimalDivide(
2306+
&self,
2307+
&temporary,
2308+
&rightOp,
2309+
roundingMode
2310+
)
2311+
}
2312+
23012313
if previousError != .noError { // FIXME is this the intent?
23022314
error = previousError
23032315
}

Tests/Foundation/Tests/TestDecimal.swift

+5
Original file line numberDiff line numberDiff line change
@@ -398,9 +398,14 @@ class TestDecimal: XCTestCase {
398398
a = Decimal(8)
399399
XCTAssertEqual(.noError, NSDecimalPower(&result, &a, 2, .plain))
400400
XCTAssertEqual(Decimal(64), result)
401+
a = Decimal(8)
402+
XCTAssertEqual(.noError, NSDecimalPower(&result, &a, -2, .plain))
403+
XCTAssertEqual(Decimal(1/64), result)
401404
a = Decimal(-2)
402405
XCTAssertEqual(.noError, NSDecimalPower(&result, &a, 3, .plain))
403406
XCTAssertEqual(Decimal(-8), result)
407+
XCTAssertEqual(.noError, NSDecimalPower(&result, &a, -3, .plain))
408+
XCTAssertEqual(Decimal(-1/8), result)
404409
for i in -2...10 {
405410
for j in 0...5 {
406411
var actual = Decimal(i)

0 commit comments

Comments
 (0)