11
11
//===----------------------------------------------------------------------===//
12
12
13
13
% for signed in [False, True]:
14
- % U = 'U' if signed else ''
14
+ % U = '' if signed else 'U'
15
+ % Self = '_Int128' if signed else '_UInt128'
16
+ % Other = '_UInt128' if signed else '_Int128'
15
17
/// A 128-bit ${'signed' if signed else 'unsigned'} integer type.
16
18
internal struct _${U}Int128 {
17
19
internal typealias High = ${U}Int64
@@ -40,6 +42,13 @@ internal struct _${U}Int128 {
40
42
internal init() {
41
43
self.init(high: 0, low: 0)
42
44
}
45
+
46
+ internal init(bitPattern v: ${Other}) {
47
+ self.init(high: High(bitPattern: v.high), low: v.low)
48
+ }
49
+
50
+ internal static var zero: Self { Self(high: 0, low: 0) }
51
+ internal static var one: Self { Self(high: 0, low: 1) }
43
52
}
44
53
45
54
extension _${U}Int128: CustomStringConvertible {
@@ -82,9 +91,9 @@ extension _${U}Int128 {
82
91
83
92
extension _${U}Int128: AdditiveArithmetic {
84
93
internal static func - (_ lhs: Self, _ rhs: Self) -> Self {
85
- var lhs = lhs
86
- lhs -= rhs
87
- return lhs
94
+ let (result, overflow) = lhs.subtractingReportingOverflow(rhs)
95
+ _precondition(!overflow, "Overflow in -")
96
+ return result
88
97
}
89
98
90
99
internal static func -= (_ lhs: inout Self, _ rhs: Self) {
@@ -94,9 +103,9 @@ extension _${U}Int128: AdditiveArithmetic {
94
103
}
95
104
96
105
internal static func + (_ lhs: Self, _ rhs: Self) -> Self {
97
- var lhs = lhs
98
- lhs += rhs
99
- return lhs
106
+ let (result, overflow) = lhs.addingReportingOverflow(rhs)
107
+ _precondition(!overflow, "Overflow in +")
108
+ return result
100
109
}
101
110
102
111
internal static func += (_ lhs: inout Self, _ rhs: Self) {
@@ -110,7 +119,15 @@ extension _${U}Int128: Numeric {
110
119
internal typealias Magnitude = _UInt128
111
120
112
121
internal var magnitude: Magnitude {
113
- Magnitude(_wideMagnitude22(self.components))
122
+ % if signed:
123
+ var result = _UInt128(bitPattern: self)
124
+ guard high._isNegative else { return result }
125
+ result.high = ~result.high
126
+ result.low = ~result.low
127
+ return result.addingReportingOverflow(.one).partialValue
128
+ % else:
129
+ return self
130
+ % end
114
131
}
115
132
116
133
internal init(_ magnitude: Magnitude) {
@@ -148,9 +165,9 @@ extension _${U}Int128: Numeric {
148
165
}
149
166
150
167
internal static func * (_ lhs: Self, _ rhs: Self) -> Self {
151
- var lhs = lhs
152
- lhs *= rhs
153
- return lhs
168
+ let (result, overflow) = lhs.multipliedReportingOverflow(by: rhs)
169
+ _precondition(!overflow, "Overflow in *")
170
+ return result
154
171
}
155
172
156
173
internal static func *= (_ lhs: inout Self, _ rhs: Self) {
@@ -160,57 +177,49 @@ extension _${U}Int128: Numeric {
160
177
}
161
178
}
162
179
163
-
164
- % if signed:
165
- extension _Int128 {
166
- internal typealias Words = _UInt128.Words
167
- }
168
- % else:
169
- extension _UInt128 {
180
+ extension _${U}Int128 {
170
181
internal struct Words {
171
- internal var high: High.Words
172
- internal var low: Low.Words
173
-
174
- internal init(_ value: _UInt128) {
175
- self.init(high: value.high.words, low: value.low.words)
176
- }
182
+ internal var _value: _${U}Int128
177
183
178
- internal init(_ value: _Int128) {
179
- self.init(_UInt128(truncatingIfNeeded: value))
180
- }
181
-
182
- internal init(high: High.Words, low: Low.Words) {
183
- self.high = high
184
- self.low = low
184
+ internal init(_ value: _${U}Int128) {
185
+ self._value = value
185
186
}
186
187
}
187
188
}
188
189
189
- extension _UInt128.Words: RandomAccessCollection {
190
+ extension _${U}Int128.Words: RandomAccessCollection {
191
+ internal typealias Element = UInt
190
192
internal typealias Index = Int
191
-
192
- internal var startIndex: Index {
193
- 0
194
- }
195
-
196
- internal var endIndex: Index {
197
- count
198
- }
199
-
200
- internal var count: Int {
201
- low.count + high.count
202
- }
203
-
204
- internal subscript(_ i: Index) -> UInt {
205
- if i < low.count {
206
- return low[i + low.startIndex]
193
+ internal typealias Indices = Range<Int>
194
+ internal typealias SubSequence = Slice<Self>
195
+
196
+ internal var count: Int { 128 / UInt.bitWidth }
197
+ internal var startIndex: Int { 0 }
198
+ internal var endIndex: Int { count }
199
+ internal var indices: Indices { startIndex ..< endIndex }
200
+ internal func index(after i: Int) -> Int { i + 1 }
201
+ internal func index(before i: Int) -> Int { i - 1 }
202
+
203
+ internal subscript(position: Int) -> UInt {
204
+ get {
205
+ _precondition(position >= 0 && position < endIndex,
206
+ "Word index out of range")
207
+ let shift = position &* UInt.bitWidth
208
+ _internalInvariant(shift < _${U}Int128.bitWidth)
209
+
210
+ let r = _wideMaskedShiftRight(
211
+ _value.components, UInt64(truncatingIfNeeded: shift))
212
+ return r.low._lowWord
207
213
}
208
- return high[i - low.count + high.startIndex]
209
214
}
210
215
}
211
- % end
212
216
213
217
extension _${U}Int128: FixedWidthInteger {
218
+ @_transparent
219
+ internal var _lowWord: UInt {
220
+ low._lowWord
221
+ }
222
+
214
223
internal var words: Words {
215
224
Words(self)
216
225
}
@@ -227,9 +236,7 @@ extension _${U}Int128: FixedWidthInteger {
227
236
self.init(high: High.min, low: Low.min)
228
237
}
229
238
230
- internal static var bitWidth: Int {
231
- High.bitWidth + Low.bitWidth
232
- }
239
+ internal static var bitWidth: Int { 128 }
233
240
234
241
internal func addingReportingOverflow(
235
242
_ rhs: Self
@@ -249,15 +256,23 @@ extension _${U}Int128: FixedWidthInteger {
249
256
internal func multipliedReportingOverflow(
250
257
by rhs: Self
251
258
) -> (partialValue: Self, overflow: Bool) {
252
- let (carry, product) = multipliedFullWidth(by: rhs)
253
- let result = Self(truncatingIfNeeded: product)
254
-
255
- let isNegative = Self.isSigned && (self._isNegative != rhs._isNegative)
256
- let didCarry = isNegative ? carry != ~Self.zero : carry != Self.zero
257
- let hadPositiveOverflow = Self.isSigned &&
258
- !isNegative && product.leadingZeroBitCount == 0
259
-
260
- return (result, didCarry || hadPositiveOverflow)
259
+ % if signed:
260
+ let isNegative = (self._isNegative != rhs._isNegative)
261
+ let (p, overflow) = self.magnitude.multipliedReportingOverflow(
262
+ by: rhs.magnitude)
263
+ let r = _Int128(bitPattern: isNegative ? ~(p &- .one) : p)
264
+ return (r, overflow || (isNegative != r._isNegative))
265
+ % else:
266
+ let h1 = self.high.multipliedReportingOverflow(by: rhs.low)
267
+ let h2 = self.low.multipliedReportingOverflow(by: rhs.high)
268
+ let h3 = h1.partialValue.addingReportingOverflow(h2.partialValue)
269
+ let (h, l) = self.low.multipliedFullWidth(by: rhs.low)
270
+ let high = h3.partialValue.addingReportingOverflow(h)
271
+ let overflow = (
272
+ (self.high != 0 && rhs.high != 0)
273
+ || h1.overflow || h2.overflow || h3.overflow || high.overflow)
274
+ return (Self(high: high.partialValue, low: l), overflow)
275
+ % end
261
276
}
262
277
263
278
internal func quotientAndRemainder(
@@ -333,7 +348,7 @@ extension _${U}Int128: FixedWidthInteger {
333
348
low: mid1.high + mid2.low)
334
349
335
350
if isNegative {
336
- let (lowComplement, overflow) = (~low).addingReportingOverflow(1 )
351
+ let (lowComplement, overflow) = (~low).addingReportingOverflow(.one )
337
352
return (~high + (overflow ? 1 : 0), lowComplement)
338
353
} else {
339
354
return (high, low)
@@ -343,15 +358,10 @@ extension _${U}Int128: FixedWidthInteger {
343
358
internal func dividingFullWidth(
344
359
_ dividend: (high: Self, low: Self.Magnitude)
345
360
) -> (quotient: Self, remainder: Self) {
361
+ % if signed:
346
362
let m = _wideMagnitude22(dividend)
347
- let (q, r) = _wideDivide42(
348
- (m.high.components, m.low.components),
349
- by: self.magnitude.components)
350
- let quotient = Self.Magnitude(q)
351
- let remainder = Self.Magnitude(r)
352
- guard Self.isSigned else {
353
- return (Self(quotient), Self(remainder))
354
- }
363
+ let (quotient, remainder) = self.magnitude.dividingFullWidth(m)
364
+
355
365
let isNegative = (self.high._isNegative != dividend.high.high._isNegative)
356
366
let quotient_ = (isNegative
357
367
? (quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient))
@@ -360,13 +370,20 @@ extension _${U}Int128: FixedWidthInteger {
360
370
? 0 - Self(remainder)
361
371
: Self(remainder))
362
372
return (quotient_, remainder_)
373
+ % else:
374
+ let (q, r) = _wideDivide42(
375
+ (dividend.high.components, dividend.low.components),
376
+ by: self.components)
377
+ return (Self(q), Self(r))
378
+ % end
363
379
}
364
380
365
- /* disabled since it causes a compile failure in LLDB
381
+ #if false // This triggers an unexpected type checking issue with `~0` in an
382
+ // lldb test
366
383
internal static prefix func ~(x: Self) -> Self {
367
384
Self(high: ~x.high, low: ~x.low)
368
385
}
369
- */
386
+ #endif
370
387
371
388
internal static func &= (_ lhs: inout Self, _ rhs: Self) {
372
389
lhs.low &= rhs.low
@@ -413,11 +430,19 @@ extension _${U}Int128: FixedWidthInteger {
413
430
lhs &>>= rhs
414
431
}
415
432
416
- internal static func &<<= (_ lhs: inout Self, _ rhs: Self) {
433
+ internal static func &<< (lhs: Self, rhs: Self) -> Self {
434
+ Self(_wideMaskedShiftLeft(lhs.components, rhs.low))
435
+ }
436
+
437
+ internal static func &>> (lhs: Self, rhs: Self) -> Self {
438
+ Self(_wideMaskedShiftRight(lhs.components, rhs.low))
439
+ }
440
+
441
+ internal static func &<<= (lhs: inout Self, rhs: Self) {
417
442
_wideMaskedShiftLeft(&lhs.components, rhs.low)
418
443
}
419
444
420
- internal static func &>>= (_ lhs: inout Self, _ rhs: Self) {
445
+ internal static func &>>= (lhs: inout Self, rhs: Self) {
421
446
_wideMaskedShiftRight(&lhs.components, rhs.low)
422
447
}
423
448
@@ -590,7 +615,7 @@ private func _wideMaskedShiftLeft<F: FixedWidthInteger>(
590
615
var high = lhs.high &<< F(rhs)
591
616
let rollover = F.Magnitude(F.bitWidth) &- rhs
592
617
high |= F(truncatingIfNeeded: lhs.low &>> rollover)
593
- var low = lhs.low &<< rhs
618
+ let low = lhs.low &<< rhs
594
619
return (high, low)
595
620
}
596
621
0 commit comments