@@ -441,12 +441,39 @@ extension Decimal {
441
441
self . compact ( )
442
442
}
443
443
}
444
+
444
445
public init ( _ value: UInt64 ) {
445
- self . init ( Double ( value) )
446
+ self = Decimal ( )
447
+ if value == 0 {
448
+ return
449
+ }
450
+
451
+ var compactValue = value
452
+ var exponent : Int32 = 0
453
+ while compactValue % 10 == 0 {
454
+ compactValue = compactValue / 10
455
+ exponent = exponent + 1
456
+ }
457
+ _isCompact = 1
458
+ _exponent = exponent
459
+
460
+ let wordCount = ( ( UInt64 . bitWidth - compactValue. leadingZeroBitCount) + ( UInt16 . bitWidth - 1 ) ) / UInt16. bitWidth
461
+ _length = UInt32 ( wordCount)
462
+ _mantissa. 0 = UInt16 ( truncatingIfNeeded: compactValue >> 0 )
463
+ _mantissa. 1 = UInt16 ( truncatingIfNeeded: compactValue >> 16 )
464
+ _mantissa. 2 = UInt16 ( truncatingIfNeeded: compactValue >> 32 )
465
+ _mantissa. 3 = UInt16 ( truncatingIfNeeded: compactValue >> 48 )
446
466
}
467
+
447
468
public init ( _ value: Int64 ) {
448
- self . init ( Double ( value) )
469
+ if value < 0 {
470
+ self . init ( value == Int64 . min ? UInt64 ( Int64 . max) + 1 : UInt64 ( abs ( value) ) )
471
+ _isNegative = 1
472
+ } else {
473
+ self . init ( UInt64 ( value) )
474
+ }
449
475
}
476
+
450
477
public init ( _ value: UInt ) {
451
478
self . init ( UInt64 ( value) )
452
479
}
@@ -1164,62 +1191,60 @@ public func NSDecimalAdd(_ result: UnsafeMutablePointer<Decimal>, _ leftOperand:
1164
1191
}
1165
1192
1166
1193
fileprivate func integerAdd( _ result: inout WideDecimal , _ left: inout Decimal , _ right: inout Decimal ) -> NSDecimalNumber . CalculationError {
1167
- var i : UInt32 = 0
1168
- var carry : UInt16 = 0
1169
- var accumulator : UInt32 = 0
1170
-
1171
- let c : UInt32 = min ( left. _length, right. _length)
1194
+ var idx : UInt32 = 0
1195
+ var carry : UInt16 = 0
1196
+ let maxIndex : UInt32 = min ( left. _length, right. _length) // The highest index with bits set in both values
1172
1197
1173
- while i < c {
1174
- let li = UInt32 ( left [ i ] )
1175
- let ri = UInt32 ( right [ i ] )
1176
- accumulator = li + ri + UInt32( carry)
1177
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1178
- result [ i ] = UInt16 ( truncatingIfNeeded: accumulator )
1179
- 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
1180
1205
}
1181
1206
1182
- while i < left. _length {
1207
+ while idx < left. _length {
1183
1208
if carry != 0 {
1184
- let li = UInt32 ( left [ i ] )
1185
- accumulator = li + UInt32( carry)
1186
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1187
- result [ i ] = UInt16 ( truncatingIfNeeded: accumulator )
1188
- 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
1189
1214
} else {
1190
- while i < left. _length {
1191
- result [ i ] = left [ i ]
1192
- i += 1
1215
+ while idx < left. _length {
1216
+ result [ idx ] = left [ idx ]
1217
+ idx += 1
1193
1218
}
1194
1219
break
1195
1220
}
1196
1221
}
1197
- while i < right. _length {
1222
+ while idx < right. _length {
1198
1223
if carry != 0 {
1199
- let ri = UInt32 ( right [ i ] )
1200
- accumulator = ri + UInt32( carry)
1201
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1202
- result [ i ] = UInt16 ( truncatingIfNeeded: accumulator )
1203
- 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
1204
1229
} else {
1205
- while i < right. _length {
1206
- result [ i ] = right [ i ]
1207
- i += 1
1230
+ while idx < right. _length {
1231
+ result [ idx ] = right [ idx ]
1232
+ idx += 1
1208
1233
}
1209
1234
break
1210
1235
}
1211
1236
}
1237
+ result. _length = idx
1212
1238
1213
1239
if carry != 0 {
1214
- if result. _length < i {
1215
- result. _length = i
1216
- return . overflow
1217
- } else {
1218
- result [ i] = carry
1219
- i += 1
1220
- }
1240
+ result [ idx] = carry
1241
+ idx += 1
1242
+ result. _length = idx
1221
1243
}
1222
- result. _length = i;
1244
+ if idx > Decimal . maxSize {
1245
+ return . overflow
1246
+ }
1247
+
1223
1248
return . noError;
1224
1249
}
1225
1250
@@ -1231,49 +1256,48 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
1231
1256
// give b-a...
1232
1257
//
1233
1258
fileprivate func integerSubtract( _ result: inout Decimal , _ left: inout Decimal , _ right: inout Decimal ) -> NSDecimalNumber . CalculationError {
1234
- var i : UInt32 = 0
1235
- var carry : UInt16 = 1
1236
- var accumulator : UInt32 = 0
1237
-
1238
- let c : UInt32 = min ( left . _length , right . _length )
1239
-
1240
- while i < c {
1241
- let li = UInt32 ( left [ i ] )
1242
- let ri = UInt32 ( right [ i ] )
1243
- accumulator = 0xffff + li - ri + UInt32 ( carry )
1244
- carry = UInt16 ( truncatingIfNeeded : accumulator >> 16 )
1245
- result [ i ] = UInt16 ( truncatingIfNeeded: accumulator )
1246
- i += 1
1247
- }
1248
-
1249
- while i < left. _length {
1250
- if carry != 0 {
1251
- let li = UInt32 ( left [ i ] )
1252
- accumulator = 0xffff + li // + no carry
1253
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1254
- result [ i ] = UInt16 ( truncatingIfNeeded: accumulator )
1255
- i += 1
1259
+ var idx : UInt32 = 0
1260
+ let maxIndex : UInt32 = min ( left . _length , right . _length ) // The highest index with bits set in both values
1261
+ var borrow : UInt16 = 0
1262
+
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
1272
+ }
1273
+
1274
+ while idx < left. _length {
1275
+ if borrow != 0 {
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
1256
1281
} else {
1257
- while i < left. _length {
1258
- result [ i ] = left [ i ]
1259
- i += 1
1282
+ while idx < left. _length {
1283
+ result [ idx ] = left [ idx ]
1284
+ idx += 1
1260
1285
}
1261
1286
break
1262
1287
}
1263
1288
}
1264
- while i < right. _length {
1265
- let ri = UInt32 ( right [ i ] )
1266
- accumulator = 0xffff - ri + UInt32( carry )
1267
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1268
- result [ i ] = UInt16 ( truncatingIfNeeded: accumulator )
1269
- 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
1270
1295
}
1271
1296
1272
- if carry != 0 {
1297
+ if borrow != 0 {
1273
1298
return . overflow
1274
1299
}
1275
- result. _length = i;
1276
-
1300
+ result. _length = idx;
1277
1301
result. trimTrailingZeros ( )
1278
1302
1279
1303
return . noError;
0 commit comments