@@ -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,16 +1191,14 @@ 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 i : UInt32 = 0
1195
+ var carry : UInt16 = 0
1196
+ let c : UInt32 = min ( left. _length, right. _length)
1172
1197
1173
1198
while i < c {
1174
1199
let li = UInt32 ( left [ i] )
1175
1200
let ri = UInt32 ( right [ i] )
1176
- accumulator = li + ri + UInt32( carry)
1201
+ let accumulator = li + ri + UInt32( carry)
1177
1202
carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1178
1203
result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1179
1204
i += 1
@@ -1182,7 +1207,7 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
1182
1207
while i < left. _length {
1183
1208
if carry != 0 {
1184
1209
let li = UInt32 ( left [ i] )
1185
- accumulator = li + UInt32( carry)
1210
+ let accumulator = li + UInt32( carry)
1186
1211
carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1187
1212
result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1188
1213
i += 1
@@ -1197,7 +1222,7 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
1197
1222
while i < right. _length {
1198
1223
if carry != 0 {
1199
1224
let ri = UInt32 ( right [ i] )
1200
- accumulator = ri + UInt32( carry)
1225
+ let accumulator = ri + UInt32( carry)
1201
1226
carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1202
1227
result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1203
1228
i += 1
@@ -1209,17 +1234,17 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
1209
1234
break
1210
1235
}
1211
1236
}
1237
+ result. _length = i
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 [ i] = carry
1241
+ i += 1
1242
+ result. _length = i
1221
1243
}
1222
- result. _length = i;
1244
+ if i > Decimal . maxSize {
1245
+ return . overflow
1246
+ }
1247
+
1223
1248
return . noError;
1224
1249
}
1225
1250
@@ -1231,26 +1256,24 @@ 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)
1259
+ var i : UInt32 = 0
1260
+ var borrow : UInt16 = 0
1261
+ let c : UInt32 = min ( left. _length, right. _length)
1239
1262
1240
1263
while i < c {
1241
1264
let li = UInt32 ( left [ i] )
1242
1265
let ri = UInt32 ( right [ i] )
1243
- accumulator = 0xffff + li - ri + UInt32( carry)
1244
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1266
+ let accumulator : UInt32 = ( 0x10000 + li) - UInt32( borrow) - ri
1245
1267
result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1268
+ borrow = 1 - UInt16( truncatingIfNeeded: accumulator >> 16 )
1246
1269
i += 1
1247
1270
}
1248
1271
1249
1272
while i < left. _length {
1250
- if carry != 0 {
1273
+ if borrow != 0 {
1251
1274
let li = UInt32 ( left [ i] )
1252
- accumulator = 0xffff + li // + no carry
1253
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1275
+ let accumulator = 0xffff + li // + no carry
1276
+ borrow = 1 - UInt16( truncatingIfNeeded: accumulator >> 16 )
1254
1277
result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1255
1278
i += 1
1256
1279
} else {
@@ -1263,17 +1286,16 @@ fileprivate func integerSubtract(_ result: inout Decimal, _ left: inout Decimal,
1263
1286
}
1264
1287
while i < right. _length {
1265
1288
let ri = UInt32 ( right [ i] )
1266
- accumulator = 0xffff - ri + UInt32( carry )
1267
- carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
1289
+ let accumulator = 0xffff - ri + UInt32( borrow )
1290
+ borrow = 1 - UInt16( truncatingIfNeeded: accumulator >> 16 )
1268
1291
result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1269
1292
i += 1
1270
1293
}
1271
1294
1272
- if carry != 0 {
1295
+ if borrow != 0 {
1273
1296
return . overflow
1274
1297
}
1275
1298
result. _length = i;
1276
-
1277
1299
result. trimTrailingZeros ( )
1278
1300
1279
1301
return . noError;
0 commit comments