Skip to content

Commit b17435d

Browse files
committed
Decimal: Add more tests for addition and subtraction
- integerAdd(), integerSubtract(): Use more meaningful variable names.
1 parent 139a14b commit b17435d

File tree

2 files changed

+72
-60
lines changed

2 files changed

+72
-60
lines changed

Foundation/Decimal.swift

Lines changed: 59 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,57 +1191,57 @@ public func NSDecimalAdd(_ result: UnsafeMutablePointer<Decimal>, _ leftOperand:
11911191
}
11921192

11931193
fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal, _ right: inout Decimal) -> NSDecimalNumber.CalculationError {
1194-
var i: UInt32 = 0
1194+
var idx: UInt32 = 0
11951195
var carry: UInt16 = 0
1196-
let c: UInt32 = min(left._length, right._length)
1196+
let maxIndex: UInt32 = min(left._length, right._length) // The highest index with bits set in both values
11971197

1198-
while i < c {
1199-
let li = UInt32(left[i])
1200-
let ri = UInt32(right[i])
1201-
let accumulator = li + ri + UInt32(carry)
1202-
carry = UInt16(truncatingIfNeeded:accumulator >> 16)
1203-
result[i] = UInt16(truncatingIfNeeded:accumulator)
1204-
i += 1
1198+
while idx < maxIndex {
1199+
let li = UInt32(left[idx])
1200+
let ri = UInt32(right[idx])
1201+
let sum = li + ri + UInt32(carry)
1202+
carry = UInt16(truncatingIfNeeded: sum >> 16)
1203+
result[idx] = UInt16(truncatingIfNeeded: sum)
1204+
idx += 1
12051205
}
12061206

1207-
while i < left._length {
1207+
while idx < left._length {
12081208
if carry != 0 {
1209-
let li = UInt32(left[i])
1210-
let accumulator = li + UInt32(carry)
1211-
carry = UInt16(truncatingIfNeeded:accumulator >> 16)
1212-
result[i] = UInt16(truncatingIfNeeded:accumulator)
1213-
i += 1
1209+
let li = UInt32(left[idx])
1210+
let sum = li + UInt32(carry)
1211+
carry = UInt16(truncatingIfNeeded: sum >> 16)
1212+
result[idx] = UInt16(truncatingIfNeeded: sum)
1213+
idx += 1
12141214
} else {
1215-
while i < left._length {
1216-
result[i] = left[i]
1217-
i += 1
1215+
while idx < left._length {
1216+
result[idx] = left[idx]
1217+
idx += 1
12181218
}
12191219
break
12201220
}
12211221
}
1222-
while i < right._length {
1222+
while idx < right._length {
12231223
if carry != 0 {
1224-
let ri = UInt32(right[i])
1225-
let accumulator = ri + UInt32(carry)
1226-
carry = UInt16(truncatingIfNeeded:accumulator >> 16)
1227-
result[i] = UInt16(truncatingIfNeeded:accumulator)
1228-
i += 1
1224+
let ri = UInt32(right[idx])
1225+
let sum = ri + UInt32(carry)
1226+
carry = UInt16(truncatingIfNeeded: sum >> 16)
1227+
result[idx] = UInt16(truncatingIfNeeded: sum)
1228+
idx += 1
12291229
} else {
1230-
while i < right._length {
1231-
result[i] = right[i]
1232-
i += 1
1230+
while idx < right._length {
1231+
result[idx] = right[idx]
1232+
idx += 1
12331233
}
12341234
break
12351235
}
12361236
}
1237-
result._length = i
1237+
result._length = idx
12381238

12391239
if carry != 0 {
1240-
result[i] = carry
1241-
i += 1
1242-
result._length = i
1240+
result[idx] = carry
1241+
idx += 1
1242+
result._length = idx
12431243
}
1244-
if i > Decimal.maxSize {
1244+
if idx > Decimal.maxSize {
12451245
return .overflow
12461246
}
12471247

@@ -1256,46 +1256,48 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
12561256
// give b-a...
12571257
//
12581258
fileprivate func integerSubtract(_ result: inout Decimal, _ left: inout Decimal, _ right: inout Decimal) -> NSDecimalNumber.CalculationError {
1259-
var i: UInt32 = 0
1259+
var idx: UInt32 = 0
1260+
let maxIndex: UInt32 = min(left._length, right._length) // The highest index with bits set in both values
12601261
var borrow: UInt16 = 0
1261-
let c: UInt32 = min(left._length, right._length)
12621262

1263-
while i < c {
1264-
let li = UInt32(left[i])
1265-
let ri = UInt32(right[i])
1266-
let accumulator: UInt32 = (0x10000 + li) - UInt32(borrow) - ri
1267-
result[i] = UInt16(truncatingIfNeeded:accumulator)
1268-
borrow = 1 - UInt16(truncatingIfNeeded:accumulator >> 16)
1269-
i += 1
1263+
while idx < maxIndex {
1264+
let li = UInt32(left[idx])
1265+
let ri = UInt32(right[idx])
1266+
// 0x10000 is to borrow in advance to avoid underflow.
1267+
let difference: UInt32 = (0x10000 + li) - UInt32(borrow) - ri
1268+
result[idx] = UInt16(truncatingIfNeeded: difference)
1269+
// borrow = 1 if the borrow was used.
1270+
borrow = 1 - UInt16(truncatingIfNeeded: difference >> 16)
1271+
idx += 1
12701272
}
12711273

1272-
while i < left._length {
1274+
while idx < left._length {
12731275
if borrow != 0 {
1274-
let li = UInt32(left[i])
1275-
let accumulator = 0xffff + li // + no carry
1276-
borrow = 1 - UInt16(truncatingIfNeeded:accumulator >> 16)
1277-
result[i] = UInt16(truncatingIfNeeded:accumulator)
1278-
i += 1
1276+
let li = UInt32(left[idx])
1277+
let sum = 0xffff + li // + no carry
1278+
borrow = 1 - UInt16(truncatingIfNeeded: sum >> 16)
1279+
result[idx] = UInt16(truncatingIfNeeded: sum)
1280+
idx += 1
12791281
} else {
1280-
while i < left._length {
1281-
result[i] = left[i]
1282-
i += 1
1282+
while idx < left._length {
1283+
result[idx] = left[idx]
1284+
idx += 1
12831285
}
12841286
break
12851287
}
12861288
}
1287-
while i < right._length {
1288-
let ri = UInt32(right[i])
1289-
let accumulator = 0xffff - ri + UInt32(borrow)
1290-
borrow = 1 - UInt16(truncatingIfNeeded:accumulator >> 16)
1291-
result[i] = UInt16(truncatingIfNeeded:accumulator)
1292-
i += 1
1289+
while idx < right._length {
1290+
let ri = UInt32(right[idx])
1291+
let difference = 0xffff - ri + UInt32(borrow)
1292+
borrow = 1 - UInt16(truncatingIfNeeded: difference >> 16)
1293+
result[idx] = UInt16(truncatingIfNeeded: difference)
1294+
idx += 1
12931295
}
12941296

12951297
if borrow != 0 {
12961298
return .overflow
12971299
}
1298-
result._length = i;
1300+
result._length = idx;
12991301
result.trimTrailingZeros()
13001302

13011303
return .noError;

TestFoundation/TestDecimal.swift

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,18 +288,28 @@ class TestDecimal: XCTestCase {
288288

289289
XCTAssertEqual(Decimal(186243 * 15673 as Int64), Decimal(186243) * Decimal(15673))
290290

291-
XCTAssertEqual(Decimal(5538) + Decimal(2880.4), Decimal(5538 + 2880.4))
291+
XCTAssertEqual(Decimal(string: "5538")! + Decimal(string: "2880.4")!, Decimal(string: "8418.4")!)
292292
XCTAssertEqual(NSDecimalNumber(floatLiteral: 5538).adding(NSDecimalNumber(floatLiteral: 2880.4)), NSDecimalNumber(floatLiteral: 5538 + 2880.4))
293293

294-
XCTAssertEqual(Decimal(5538) - Decimal(2880.4), Decimal(5538 - 2880.4))
295-
XCTAssertEqual(Decimal(2880.4) - Decimal(5538), Decimal(2880.4 - 5538))
294+
XCTAssertEqual(Decimal(string: "5538.0")! - Decimal(string: "2880.4")!, Decimal(string: "2657.6")!)
295+
XCTAssertEqual(Decimal(string: "2880.4")! - Decimal(5538), Decimal(string: "-2657.6")!)
296296
XCTAssertEqual(Decimal(0x10000) - Decimal(0x1000), Decimal(0xf000))
297297
XCTAssertEqual(Decimal(0x1_0000_0000) - Decimal(0x1000), Decimal(0xFFFFF000))
298298
XCTAssertEqual(Decimal(0x1_0000_0000_0000) - Decimal(0x1000), Decimal(0xFFFFFFFFF000))
299299
XCTAssertEqual(Decimal(1234_5678_9012_3456_7899 as UInt64) - Decimal(1234_5678_9012_3456_7890 as UInt64), Decimal(9))
300300
XCTAssertEqual(Decimal(0xffdd_bb00_8866_4422 as UInt64) - Decimal(0x7777_7777), Decimal(0xFFDD_BB00_10EE_CCAB as UInt64))
301301
XCTAssertEqual(NSDecimalNumber(floatLiteral: 5538).subtracting(NSDecimalNumber(floatLiteral: 2880.4)), NSDecimalNumber(floatLiteral: 5538 - 2880.4))
302302
XCTAssertEqual(NSDecimalNumber(floatLiteral: 2880.4).subtracting(NSDecimalNumber(floatLiteral: 5538)), NSDecimalNumber(floatLiteral: 2880.4 - 5538))
303+
304+
XCTAssertEqual(Decimal.greatestFiniteMagnitude - Decimal.greatestFiniteMagnitude, Decimal(0))
305+
XCTAssertEqual(Decimal.leastFiniteMagnitude - Decimal(1), Decimal.leastFiniteMagnitude)
306+
let overflowed = Decimal.greatestFiniteMagnitude + Decimal.greatestFiniteMagnitude
307+
XCTAssertTrue(overflowed.isNaN)
308+
309+
let highBit = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x8000))
310+
let otherBits = Decimal(_exponent: 0, _length: 8, _isNegative: 0, _isCompact: 1, _reserved: 0, _mantissa: (0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x7fff))
311+
XCTAssertEqual(highBit - otherBits, Decimal(1))
312+
XCTAssertEqual(otherBits + Decimal(1), highBit)
303313
}
304314

305315
func test_Misc() {

0 commit comments

Comments
 (0)