@@ -441,12 +441,39 @@ extension Decimal {
441441 self . compact ( )
442442 }
443443 }
444+
444445 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 )
446466 }
467+
447468 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+ }
449475 }
476+
450477 public init ( _ value: UInt ) {
451478 self . init ( UInt64 ( value) )
452479 }
@@ -1164,16 +1191,14 @@ public func NSDecimalAdd(_ result: UnsafeMutablePointer<Decimal>, _ leftOperand:
11641191}
11651192
11661193fileprivate 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)
11721197
11731198 while i < c {
11741199 let li = UInt32 ( left [ i] )
11751200 let ri = UInt32 ( right [ i] )
1176- accumulator = li + ri + UInt32( carry)
1201+ let accumulator = li + ri + UInt32( carry)
11771202 carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
11781203 result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
11791204 i += 1
@@ -1182,7 +1207,7 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
11821207 while i < left. _length {
11831208 if carry != 0 {
11841209 let li = UInt32 ( left [ i] )
1185- accumulator = li + UInt32( carry)
1210+ let accumulator = li + UInt32( carry)
11861211 carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
11871212 result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
11881213 i += 1
@@ -1197,7 +1222,7 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
11971222 while i < right. _length {
11981223 if carry != 0 {
11991224 let ri = UInt32 ( right [ i] )
1200- accumulator = ri + UInt32( carry)
1225+ let accumulator = ri + UInt32( carry)
12011226 carry = UInt16 ( truncatingIfNeeded: accumulator >> 16 )
12021227 result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
12031228 i += 1
@@ -1209,17 +1234,17 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
12091234 break
12101235 }
12111236 }
1237+ result. _length = i
12121238
12131239 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
12211243 }
1222- result. _length = i;
1244+ if i > Decimal . maxSize {
1245+ return . overflow
1246+ }
1247+
12231248 return . noError;
12241249}
12251250
@@ -1231,26 +1256,24 @@ fileprivate func integerAdd(_ result: inout WideDecimal, _ left: inout Decimal,
12311256// give b-a...
12321257//
12331258fileprivate 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)
12391262
12401263 while i < c {
12411264 let li = UInt32 ( left [ i] )
12421265 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
12451267 result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
1268+ borrow = 1 - UInt16( truncatingIfNeeded: accumulator >> 16 )
12461269 i += 1
12471270 }
12481271
12491272 while i < left. _length {
1250- if carry != 0 {
1273+ if borrow != 0 {
12511274 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 )
12541277 result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
12551278 i += 1
12561279 } else {
@@ -1263,17 +1286,16 @@ fileprivate func integerSubtract(_ result: inout Decimal, _ left: inout Decimal,
12631286 }
12641287 while i < right. _length {
12651288 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 )
12681291 result [ i] = UInt16 ( truncatingIfNeeded: accumulator)
12691292 i += 1
12701293 }
12711294
1272- if carry != 0 {
1295+ if borrow != 0 {
12731296 return . overflow
12741297 }
12751298 result. _length = i;
1276-
12771299 result. trimTrailingZeros ( )
12781300
12791301 return . noError;
0 commit comments