1111//===----------------------------------------------------------------------===//
1212
1313% 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'
1517/// A 128-bit ${'signed' if signed else 'unsigned'} integer type.
1618internal struct _${U}Int128 {
1719 internal typealias High = ${U}Int64
@@ -40,6 +42,13 @@ internal struct _${U}Int128 {
4042 internal init() {
4143 self.init(high: 0, low: 0)
4244 }
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) }
4352}
4453
4554extension _${U}Int128: CustomStringConvertible {
@@ -82,9 +91,9 @@ extension _${U}Int128 {
8291
8392extension _${U}Int128: AdditiveArithmetic {
8493 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
8897 }
8998
9099 internal static func -= (_ lhs: inout Self, _ rhs: Self) {
@@ -94,9 +103,9 @@ extension _${U}Int128: AdditiveArithmetic {
94103 }
95104
96105 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
100109 }
101110
102111 internal static func += (_ lhs: inout Self, _ rhs: Self) {
@@ -110,7 +119,15 @@ extension _${U}Int128: Numeric {
110119 internal typealias Magnitude = _UInt128
111120
112121 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
114131 }
115132
116133 internal init(_ magnitude: Magnitude) {
@@ -148,9 +165,9 @@ extension _${U}Int128: Numeric {
148165 }
149166
150167 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
154171 }
155172
156173 internal static func *= (_ lhs: inout Self, _ rhs: Self) {
@@ -160,57 +177,49 @@ extension _${U}Int128: Numeric {
160177 }
161178}
162179
163-
164- % if signed:
165- extension _Int128 {
166- internal typealias Words = _UInt128.Words
167- }
168- % else:
169- extension _UInt128 {
180+ extension _${U}Int128 {
170181 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
177183
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
185186 }
186187 }
187188}
188189
189- extension _UInt128.Words: RandomAccessCollection {
190+ extension _${U}Int128.Words: RandomAccessCollection {
191+ internal typealias Element = UInt
190192 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
207213 }
208- return high[i - low.count + high.startIndex]
209214 }
210215}
211- % end
212216
213217extension _${U}Int128: FixedWidthInteger {
218+ @_transparent
219+ internal var _lowWord: UInt {
220+ low._lowWord
221+ }
222+
214223 internal var words: Words {
215224 Words(self)
216225 }
@@ -227,9 +236,7 @@ extension _${U}Int128: FixedWidthInteger {
227236 self.init(high: High.min, low: Low.min)
228237 }
229238
230- internal static var bitWidth: Int {
231- High.bitWidth + Low.bitWidth
232- }
239+ internal static var bitWidth: Int { 128 }
233240
234241 internal func addingReportingOverflow(
235242 _ rhs: Self
@@ -249,15 +256,23 @@ extension _${U}Int128: FixedWidthInteger {
249256 internal func multipliedReportingOverflow(
250257 by rhs: Self
251258 ) -> (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
261276 }
262277
263278 internal func quotientAndRemainder(
@@ -333,7 +348,7 @@ extension _${U}Int128: FixedWidthInteger {
333348 low: mid1.high + mid2.low)
334349
335350 if isNegative {
336- let (lowComplement, overflow) = (~low).addingReportingOverflow(1 )
351+ let (lowComplement, overflow) = (~low).addingReportingOverflow(.one )
337352 return (~high + (overflow ? 1 : 0), lowComplement)
338353 } else {
339354 return (high, low)
@@ -343,15 +358,10 @@ extension _${U}Int128: FixedWidthInteger {
343358 internal func dividingFullWidth(
344359 _ dividend: (high: Self, low: Self.Magnitude)
345360 ) -> (quotient: Self, remainder: Self) {
361+ % if signed:
346362 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+
355365 let isNegative = (self.high._isNegative != dividend.high.high._isNegative)
356366 let quotient_ = (isNegative
357367 ? (quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient))
@@ -360,13 +370,20 @@ extension _${U}Int128: FixedWidthInteger {
360370 ? 0 - Self(remainder)
361371 : Self(remainder))
362372 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
363379 }
364380
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
366383 internal static prefix func ~(x: Self) -> Self {
367384 Self(high: ~x.high, low: ~x.low)
368385 }
369- */
386+ #endif
370387
371388 internal static func &= (_ lhs: inout Self, _ rhs: Self) {
372389 lhs.low &= rhs.low
@@ -413,11 +430,19 @@ extension _${U}Int128: FixedWidthInteger {
413430 lhs &>>= rhs
414431 }
415432
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) {
417442 _wideMaskedShiftLeft(&lhs.components, rhs.low)
418443 }
419444
420- internal static func &>>= (_ lhs: inout Self, _ rhs: Self) {
445+ internal static func &>>= (lhs: inout Self, rhs: Self) {
421446 _wideMaskedShiftRight(&lhs.components, rhs.low)
422447 }
423448
@@ -590,7 +615,7 @@ private func _wideMaskedShiftLeft<F: FixedWidthInteger>(
590615 var high = lhs.high &<< F(rhs)
591616 let rollover = F.Magnitude(F.bitWidth) &- rhs
592617 high |= F(truncatingIfNeeded: lhs.low &>> rollover)
593- var low = lhs.low &<< rhs
618+ let low = lhs.low &<< rhs
594619 return (high, low)
595620}
596621
0 commit comments