//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// % for signed in [False, True]: % U = '' if signed else 'U' % Self = '_Int128' if signed else '_UInt128' % Other = '_UInt128' if signed else '_Int128' /// A 128-bit ${'signed' if signed else 'unsigned'} integer type. internal struct _${U}Int128 { internal typealias High = ${U}Int64 internal typealias Low = UInt64 /// The low part of the value. internal var low: Low internal var _low: Low { low } /// The high part of the value. internal var high: High internal var _high: High { high } /// Creates a new instance from the given tuple of high and low parts. /// /// - Parameter value: The tuple to use as the source of the new instance's /// high and low parts. internal init(_ value: (high: High, low: Low)) { self.low = value.low self.high = value.high } internal init(high: High, low: Low) { self.low = low self.high = high } internal init(_low: Low, _high: High) { self.low = _low self.high = _high } internal init() { self.init(high: 0, low: 0) } internal init(bitPattern v: ${Other}) { self.init(high: High(bitPattern: v.high), low: v.low) } internal static var zero: Self { Self(high: 0, low: 0) } internal static var one: Self { Self(high: 0, low: 1) } } extension _${U}Int128: CustomStringConvertible { internal var description: String { String(self, radix: 10) } } extension _${U}Int128: CustomDebugStringConvertible { internal var debugDescription: String { description } } extension _${U}Int128: Equatable { internal static func == (_ lhs: Self, _ rhs: Self) -> Bool { return (lhs.high, lhs.low) == (rhs.high, rhs.low) } } extension _${U}Int128: Comparable { internal static func < (_ lhs: Self, _ rhs: Self) -> Bool { (lhs.high, lhs.low) < (rhs.high, rhs.low) } } extension _${U}Int128: Hashable { internal func hash(into hasher: inout Hasher) { hasher.combine(low) hasher.combine(high) } } extension _${U}Int128 { internal var components: (high: High, low: Low) { @inline(__always) get { (high, low) } @inline(__always) set { (self.high, self.low) = (newValue.high, newValue.low) } } } extension _${U}Int128: AdditiveArithmetic { internal static func - (_ lhs: Self, _ rhs: Self) -> Self { let (result, overflow) = lhs.subtractingReportingOverflow(rhs) _precondition(!overflow, "Overflow in -") return result } internal static func -= (_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.subtractingReportingOverflow(rhs) _precondition(!overflow, "Overflow in -=") lhs = result } internal static func + (_ lhs: Self, _ rhs: Self) -> Self { let (result, overflow) = lhs.addingReportingOverflow(rhs) _precondition(!overflow, "Overflow in +") return result } internal static func += (_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.addingReportingOverflow(rhs) _precondition(!overflow, "Overflow in +=") lhs = result } } extension _${U}Int128: Numeric { internal typealias Magnitude = _UInt128 internal var magnitude: Magnitude { % if signed: var result = _UInt128(bitPattern: self) guard high._isNegative else { return result } result.high = ~result.high result.low = ~result.low return result.addingReportingOverflow(.one).partialValue % else: return self % end } internal init(_ magnitude: Magnitude) { self.init(high: High(magnitude.high), low: magnitude.low) } internal init(_ source: T) { guard let result = Self(exactly: source) else { preconditionFailure("Value is outside the representable range") } self = result } internal init?(exactly source: T) { // Can't represent a negative 'source' if Self is unsigned. guard Self.isSigned || source >= 0 else { return nil } // Is 'source' entirely representable in Low? if let low = Low(exactly: source.magnitude) { self.init(source._isNegative ? (~0, low._twosComplement) : (0, low)) } else { // At this point we know source.bitWidth > High.bitWidth, or else we // would've taken the first branch. let lowInT = source & T(~0 as Low) let highInT = source >> Low.bitWidth let low = Low(lowInT) guard let high = High(exactly: highInT) else { return nil } self.init(high: high, low: low) } } internal static func * (_ lhs: Self, _ rhs: Self) -> Self { let (result, overflow) = lhs.multipliedReportingOverflow(by: rhs) _precondition(!overflow, "Overflow in *") return result } internal static func *= (_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.multipliedReportingOverflow(by: rhs) _precondition(!overflow, "Overflow in *=") lhs = result } } extension _${U}Int128 { internal struct Words { internal var _value: _${U}Int128 internal init(_ value: _${U}Int128) { self._value = value } } } extension _${U}Int128.Words: RandomAccessCollection { internal typealias Element = UInt internal typealias Index = Int internal typealias Indices = Range internal typealias SubSequence = Slice internal var count: Int { 128 / UInt.bitWidth } internal var startIndex: Int { 0 } internal var endIndex: Int { count } internal var indices: Indices { startIndex ..< endIndex } internal func index(after i: Int) -> Int { i + 1 } internal func index(before i: Int) -> Int { i - 1 } internal subscript(position: Int) -> UInt { get { _precondition(position >= 0 && position < endIndex, "Word index out of range") let shift = position &* UInt.bitWidth _internalInvariant(shift < _${U}Int128.bitWidth) let r = _wideMaskedShiftRight( _value.components, UInt64(truncatingIfNeeded: shift)) return r.low._lowWord } } } extension _${U}Int128: FixedWidthInteger { @_transparent internal var _lowWord: UInt { low._lowWord } internal var words: Words { Words(self) } internal static var isSigned: Bool { ${'true' if signed else 'false'} } internal static var max: Self { self.init(high: High.max, low: Low.max) } internal static var min: Self { self.init(high: High.min, low: Low.min) } internal static var bitWidth: Int { 128 } internal func addingReportingOverflow( _ rhs: Self ) -> (partialValue: Self, overflow: Bool) { let (r, o) = _wideAddReportingOverflow22(self.components, rhs.components) return (Self(r), o) } internal func subtractingReportingOverflow( _ rhs: Self ) -> (partialValue: Self, overflow: Bool) { let (r, o) = _wideSubtractReportingOverflow22( self.components, rhs.components) return (Self(r), o) } internal func multipliedReportingOverflow( by rhs: Self ) -> (partialValue: Self, overflow: Bool) { % if signed: let isNegative = (self._isNegative != rhs._isNegative && self != .zero && rhs != .zero) let (p, overflow) = self.magnitude.multipliedReportingOverflow( by: rhs.magnitude) let r = _Int128(bitPattern: isNegative ? p._twosComplement : p) return (r, overflow || (isNegative != r._isNegative)) % else: let h1 = self.high.multipliedReportingOverflow(by: rhs.low) let h2 = self.low.multipliedReportingOverflow(by: rhs.high) let h3 = h1.partialValue.addingReportingOverflow(h2.partialValue) let (h, l) = self.low.multipliedFullWidth(by: rhs.low) let high = h3.partialValue.addingReportingOverflow(h) let overflow = ( (self.high != 0 && rhs.high != 0) || h1.overflow || h2.overflow || h3.overflow || high.overflow) return (Self(high: high.partialValue, low: l), overflow) % end } /// Returns the product of this value and the given 64-bit value, along with a /// Boolean value indicating whether overflow occurred in the operation. internal func multipliedReportingOverflow( by other: UInt64 ) -> (partialValue: Self, overflow: Bool) { % if signed: let isNegative = self._isNegative && self != .zero && other != .zero let (p, overflow) = self.magnitude.multipliedReportingOverflow(by: other) let r = _Int128(bitPattern: isNegative ? p._twosComplement : p) return (r, overflow || (isNegative != r._isNegative)) % else: let h1 = self.high.multipliedReportingOverflow(by: other) let (h2, l) = self.low.multipliedFullWidth(by: other) let high = h1.partialValue.addingReportingOverflow(h2) let overflow = h1.overflow || high.overflow return (Self(high: high.partialValue, low: l), overflow) % end } internal func multiplied(by other: UInt64) -> Self { let r = multipliedReportingOverflow(by: other) _precondition(!r.overflow, "Overflow in multiplication") return r.partialValue } internal func quotientAndRemainder( dividingBy other: Self ) -> (quotient: Self, remainder: Self) { let (q, r) = _wideDivide22( self.magnitude.components, by: other.magnitude.components) let quotient = Self.Magnitude(q) let remainder = Self.Magnitude(r) % if signed: let isNegative = (self.high._isNegative != other.high._isNegative) let quotient_ = (isNegative ? quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient) : Self(quotient)) let remainder_ = (self.high._isNegative ? 0 - Self(remainder) : Self(remainder)) return (quotient_, remainder_) % else: return (quotient, remainder) % end } internal func dividedReportingOverflow( by other: Self ) -> (partialValue: Self, overflow: Bool) { if other == Self.zero { return (self, true) } if Self.isSigned && other == -1 && self == .min { return (self, true) } return (quotientAndRemainder(dividingBy: other).quotient, false) } internal func remainderReportingOverflow( dividingBy other: Self ) -> (partialValue: Self, overflow: Bool) { if other == Self.zero { return (self, true) } if Self.isSigned && other == -1 && self == .min { return (0, true) } return (quotientAndRemainder(dividingBy: other).remainder, false) } internal func multipliedFullWidth( by other: Self ) -> (high: Self, low: Magnitude) { let isNegative = Self.isSigned && (self._isNegative != other._isNegative) func sum(_ x: Low, _ y: Low) -> (high: Low, low: Low) { let (sum, overflow) = x.addingReportingOverflow(y) return (overflow ? 1 : 0, sum) } func sum(_ x: Low, _ y: Low, _ z: Low) -> (high: Low, low: Low) { let s1 = sum(x, y) let s2 = sum(s1.low, z) return (s1.high &+ s2.high, s2.low) } func sum( _ x0: Low, _ x1: Low, _ x2: Low, _ x3: Low ) -> (high: Low, low: Low) { let s1 = sum(x0, x1) let s2 = sum(x2, x3) let s = sum(s1.low, s2.low) return (s1.high &+ s2.high &+ s.high, s.low) } let lhs = self.magnitude let rhs = other.magnitude let a = rhs.low.multipliedFullWidth(by: lhs.low) let b = rhs.low.multipliedFullWidth(by: lhs.high) let c = rhs.high.multipliedFullWidth(by: lhs.low) let d = rhs.high.multipliedFullWidth(by: lhs.high) let mid1 = sum(a.high, b.low, c.low) let mid2 = sum(b.high, c.high, mid1.high, d.low) let high = _${U}Int128( high: High(d.high &+ mid2.high), // Note: this addition will never wrap low: mid2.low) let low = _UInt128( high: mid1.low, low: a.low) if isNegative { let (lowComplement, overflow) = (~low).addingReportingOverflow(.one) return (~high + (overflow ? 1 : 0), lowComplement) } else { return (high, low) } } internal func dividingFullWidth( _ dividend: (high: Self, low: Self.Magnitude) ) -> (quotient: Self, remainder: Self) { % if signed: let m = _wideMagnitude22(dividend) let (quotient, remainder) = self.magnitude.dividingFullWidth(m) let isNegative = (self.high._isNegative != dividend.high.high._isNegative) let quotient_ = (isNegative ? (quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient)) : Self(quotient)) let remainder_ = (dividend.high.high._isNegative ? 0 - Self(remainder) : Self(remainder)) return (quotient_, remainder_) % else: let (q, r) = _wideDivide42( (dividend.high.components, dividend.low.components), by: self.components) return (Self(q), Self(r)) % end } #if false // This triggers an unexpected type checking issue with `~0` in an // lldb test internal static prefix func ~(x: Self) -> Self { Self(high: ~x.high, low: ~x.low) } #endif internal static func &= (_ lhs: inout Self, _ rhs: Self) { lhs.low &= rhs.low lhs.high &= rhs.high } internal static func |= (_ lhs: inout Self, _ rhs: Self) { lhs.low |= rhs.low lhs.high |= rhs.high } internal static func ^= (_ lhs: inout Self, _ rhs: Self) { lhs.low ^= rhs.low lhs.high ^= rhs.high } internal static func <<= (_ lhs: inout Self, _ rhs: Self) { if Self.isSigned && rhs._isNegative { lhs >>= 0 - rhs return } // Shift is larger than this type's bit width. if rhs.high != High.zero || rhs.low >= Self.bitWidth { lhs = 0 return } lhs &<<= rhs } internal static func >>= (_ lhs: inout Self, _ rhs: Self) { if Self.isSigned && rhs._isNegative { lhs <<= 0 - rhs return } // Shift is larger than this type's bit width. if rhs.high != High.zero || rhs.low >= Self.bitWidth { lhs = lhs._isNegative ? ~0 : 0 return } lhs &>>= rhs } internal static func &<< (lhs: Self, rhs: Self) -> Self { Self(_wideMaskedShiftLeft(lhs.components, rhs.low)) } internal static func &>> (lhs: Self, rhs: Self) -> Self { Self(_wideMaskedShiftRight(lhs.components, rhs.low)) } internal static func &<<= (lhs: inout Self, rhs: Self) { _wideMaskedShiftLeft(&lhs.components, rhs.low) } internal static func &>>= (lhs: inout Self, rhs: Self) { _wideMaskedShiftRight(&lhs.components, rhs.low) } internal static func / ( _ lhs: Self, _ rhs: Self ) -> Self { var lhs = lhs lhs /= rhs return lhs } internal static func /= (_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.dividedReportingOverflow(by: rhs) _precondition(!overflow, "Overflow in /=") lhs = result } internal static func % ( _ lhs: Self, _ rhs: Self ) -> Self { var lhs = lhs lhs %= rhs return lhs } internal static func %= (_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.remainderReportingOverflow(dividingBy: rhs) _precondition(!overflow, "Overflow in %=") lhs = result } internal init(_truncatingBits bits: UInt) { low = Low(_truncatingBits: bits) high = High(_truncatingBits: bits >> UInt(Low.bitWidth)) } internal init(integerLiteral x: Int64) { self.init(x) } internal var leadingZeroBitCount: Int { (high == High.zero ? High.bitWidth + low.leadingZeroBitCount : high.leadingZeroBitCount) } internal var trailingZeroBitCount: Int { (low == Low.zero ? Low.bitWidth + high.trailingZeroBitCount : low.trailingZeroBitCount) } internal var nonzeroBitCount: Int { high.nonzeroBitCount + low.nonzeroBitCount } internal var byteSwapped: Self { Self( high: High(truncatingIfNeeded: low.byteSwapped), low: Low(truncatingIfNeeded: high.byteSwapped)) } } extension _${U}Int128: Sendable {} % end extension BinaryInteger { @inline(__always) fileprivate var _isNegative: Bool { self < Self.zero } } extension FixedWidthInteger { @inline(__always) fileprivate var _twosComplement: Self { ~self &+ 1 } } private typealias _Wide2 = (high: F, low: F.Magnitude) private typealias _Wide3 = (high: F, mid: F.Magnitude, low: F.Magnitude) private typealias _Wide4 = (high: _Wide2, low: (high: F.Magnitude, low: F.Magnitude)) private func _wideMagnitude22( _ v: _Wide2 ) -> _Wide2 { var result = (high: F.Magnitude(truncatingIfNeeded: v.high), low: v.low) guard F.isSigned && v.high._isNegative else { return result } result.high = ~result.high result.low = ~result.low return _wideAddReportingOverflow22(result, (high: 0, low: 1)).partialValue } private func _wideAddReportingOverflow22( _ lhs: _Wide2, _ rhs: _Wide2 ) -> (partialValue: _Wide2, overflow: Bool) { let (low, lowOverflow) = lhs.low.addingReportingOverflow(rhs.low) let (high, highOverflow) = lhs.high.addingReportingOverflow(rhs.high) let overflow = highOverflow || high == F.max && lowOverflow let result = (high: high &+ (lowOverflow ? 1 : 0), low: low) return (partialValue: result, overflow: overflow) } private func _wideAdd22( _ lhs: inout _Wide2, _ rhs: _Wide2 ) { let (result, overflow) = _wideAddReportingOverflow22(lhs, rhs) _precondition(!overflow, "Overflow in +") lhs = result } private func _wideAddReportingOverflow33( _ lhs: _Wide3, _ rhs: _Wide3 ) -> ( partialValue: _Wide3, overflow: Bool ) { let (low, lowOverflow) = _wideAddReportingOverflow22((lhs.mid, lhs.low), (rhs.mid, rhs.low)) let (high, highOverflow) = lhs.high.addingReportingOverflow(rhs.high) let result = (high: high &+ (lowOverflow ? 1 : 0), mid: low.high, low: low.low) let overflow = highOverflow || (high == F.max && lowOverflow) return (partialValue: result, overflow: overflow) } private func _wideSubtractReportingOverflow22( _ lhs: _Wide2, _ rhs: _Wide2 ) -> (partialValue: (high: F, low: F.Magnitude), overflow: Bool) { let (low, lowOverflow) = lhs.low.subtractingReportingOverflow(rhs.low) let (high, highOverflow) = lhs.high.subtractingReportingOverflow(rhs.high) let result = (high: high &- (lowOverflow ? 1 : 0), low: low) let overflow = highOverflow || high == F.min && lowOverflow return (partialValue: result, overflow: overflow) } private func _wideSubtract22( _ lhs: inout _Wide2, _ rhs: _Wide2 ) { let (result, overflow) = _wideSubtractReportingOverflow22(lhs, rhs) _precondition(!overflow, "Overflow in -") lhs = result } private func _wideSubtractReportingOverflow33( _ lhs: _Wide3, _ rhs: _Wide3 ) -> ( partialValue: _Wide3, overflow: Bool ) { let (low, lowOverflow) = _wideSubtractReportingOverflow22((lhs.mid, lhs.low), (rhs.mid, rhs.low)) let (high, highOverflow) = lhs.high.subtractingReportingOverflow(rhs.high) let result = (high: high &- (lowOverflow ? 1 : 0), mid: low.high, low: low.low) let overflow = highOverflow || (high == F.min && lowOverflow) return (partialValue: result, overflow: overflow) } private func _wideMaskedShiftLeft( _ lhs: _Wide2, _ rhs: F.Magnitude ) -> _Wide2 { let bitWidth = F.bitWidth + F.Magnitude.bitWidth _internalInvariant(bitWidth.nonzeroBitCount == 1) // Mask rhs by the bit width of the wide value. let rhs = rhs & F.Magnitude(bitWidth &- 1) guard rhs < F.Magnitude.bitWidth else { let s = rhs &- F.Magnitude(F.Magnitude.bitWidth) return (high: F(truncatingIfNeeded: lhs.low &<< s), low: 0) } guard rhs != F.Magnitude.zero else { return lhs } var high = lhs.high &<< F(rhs) let rollover = F.Magnitude(F.bitWidth) &- rhs high |= F(truncatingIfNeeded: lhs.low &>> rollover) let low = lhs.low &<< rhs return (high, low) } private func _wideMaskedShiftLeft( _ lhs: inout _Wide2, _ rhs: F.Magnitude ) { lhs = _wideMaskedShiftLeft(lhs, rhs) } private func _wideMaskedShiftRight( _ lhs: _Wide2, _ rhs: F.Magnitude ) -> _Wide2 { let bitWidth = F.bitWidth + F.Magnitude.bitWidth _internalInvariant(bitWidth.nonzeroBitCount == 1) // Mask rhs by the bit width of the wide value. let rhs = rhs & F.Magnitude(bitWidth &- 1) guard rhs < F.bitWidth else { let s = F(rhs &- F.Magnitude(F.bitWidth)) return ( high: lhs.high._isNegative ? ~0 : 0, low: F.Magnitude(truncatingIfNeeded: lhs.high &>> s)) } guard rhs != F.zero else { return lhs } var low = lhs.low &>> rhs let rollover = F(F.bitWidth) &- F(rhs) low |= F.Magnitude(truncatingIfNeeded: lhs.high &<< rollover) let high = lhs.high &>> rhs return (high, low) } private func _wideMaskedShiftRight( _ lhs: inout _Wide2, _ rhs: F.Magnitude ) { lhs = _wideMaskedShiftRight(lhs, rhs) } /// Returns the quotient and remainder after dividing a triple-width magnitude /// `lhs` by a double-width magnitude `rhs`. /// /// This operation is conceptually that described by Burnikel and Ziegler /// (1998). private func _wideDivide32( _ lhs: _Wide3, by rhs: _Wide2 ) -> (quotient: F, remainder: _Wide2) { // The following invariants are guaranteed to hold by dividingFullWidth or // quotientAndRemainder before this function is invoked: #if !$Embedded // TODO: Investigate why this fails to compile in embedded Swift with // assertions off _internalInvariant(lhs.high != F.zero) _internalInvariant(rhs.high.leadingZeroBitCount == 0) #endif _internalInvariant((high: lhs.high, low: lhs.mid) < rhs) // Estimate the quotient with a 2/1 division using just the top digits. var quotient = (lhs.high == rhs.high ? F.max : rhs.high.dividingFullWidth((high: lhs.high, low: lhs.mid)).quotient) // Compute quotient * rhs. // TODO: This could be performed more efficiently. let p1 = quotient.multipliedFullWidth(by: F(rhs.low)) let p2 = quotient.multipliedFullWidth(by: rhs.high) let product = _wideAddReportingOverflow33( (high: F.zero, mid: F.Magnitude(p1.high), low: p1.low), (high: p2.high, mid: p2.low, low: .zero)).partialValue // Compute the remainder after decrementing quotient as necessary. var remainder = lhs while remainder < product { quotient = quotient &- 1 remainder = _wideAddReportingOverflow33( remainder, (high: F.zero, mid: F.Magnitude(rhs.high), low: rhs.low)).partialValue } remainder = _wideSubtractReportingOverflow33(remainder, product).partialValue _internalInvariant(remainder.high == 0) return (quotient, (high: F(remainder.mid), low: remainder.low)) } /// Returns the quotient and remainder after dividing a double-width /// magnitude `lhs` by a double-width magnitude `rhs`. private func _wideDivide22( _ lhs: _Wide2, by rhs: _Wide2 ) -> (quotient: _Wide2, remainder: _Wide2) { guard _fastPath(rhs > (F.zero, F.Magnitude.zero)) else { fatalError("Division by zero") } guard rhs < lhs else { if _fastPath(rhs > lhs) { return (quotient: (0, 0), remainder: lhs) } return (quotient: (0, 1), remainder: (0, 0)) } if lhs.high == F.zero { let (quotient, remainder) = lhs.low.quotientAndRemainder(dividingBy: rhs.low) return ((0, quotient), (0, remainder)) } if rhs.high == F.zero { let (x, a) = lhs.high.quotientAndRemainder(dividingBy: F(rhs.low)) let (y, b) = (a == F.zero ? lhs.low.quotientAndRemainder(dividingBy: rhs.low) : rhs.low.dividingFullWidth((F.Magnitude(a), lhs.low))) return (quotient: (high: x, low: y), remainder: (high: 0, low: b)) } // Left shift both rhs and lhs, then divide and right shift the remainder. let shift = F.Magnitude(rhs.high.leadingZeroBitCount) let rollover = F.Magnitude(F.bitWidth + F.Magnitude.bitWidth) &- shift let rhs = _wideMaskedShiftLeft(rhs, shift) let high = _wideMaskedShiftRight(lhs, rollover).low let lhs = _wideMaskedShiftLeft(lhs, shift) let (quotient, remainder) = _wideDivide32( (F(high), F.Magnitude(lhs.high), lhs.low), by: rhs) return ( quotient: (high: 0, low: F.Magnitude(quotient)), remainder: _wideMaskedShiftRight(remainder, shift)) } /// Returns the quotient and remainder after dividing a quadruple-width /// magnitude `lhs` by a double-width magnitude `rhs`. private func _wideDivide42( _ lhs: _Wide4, by rhs: _Wide2 ) -> (quotient: _Wide2, remainder: _Wide2) { guard _fastPath(rhs > (F.zero, F.Magnitude.zero)) else { fatalError("Division by zero") } guard _fastPath(rhs >= lhs.high) else { fatalError("Division results in an overflow") } if lhs.high == (F.zero, F.Magnitude.zero) { return _wideDivide22((high: F(lhs.low.high), low: lhs.low.low), by: rhs) } if rhs.high == F.zero { let a = F.Magnitude(lhs.high.high) % rhs.low let b = (a == F.Magnitude.zero ? lhs.high.low % rhs.low : rhs.low.dividingFullWidth((a, lhs.high.low)).remainder) let (x, c) = (b == F.Magnitude.zero ? lhs.low.high.quotientAndRemainder(dividingBy: rhs.low) : rhs.low.dividingFullWidth((b, lhs.low.high))) let (y, d) = (c == F.Magnitude.zero ? lhs.low.low.quotientAndRemainder(dividingBy: rhs.low) : rhs.low.dividingFullWidth((c, lhs.low.low))) return (quotient: (high: F(x), low: y), remainder: (high: 0, low: d)) } // Left shift both rhs and lhs, then divide and right shift the remainder. let shift = F.Magnitude(rhs.high.leadingZeroBitCount) let rollover = F.Magnitude(F.bitWidth + F.Magnitude.bitWidth) &- shift let rhs = _wideMaskedShiftLeft(rhs, shift) let lh1 = _wideMaskedShiftLeft(lhs.high, shift) let lh2 = _wideMaskedShiftRight(lhs.low, rollover) let lhs = ( high: (high: lh1.high | F(lh2.high), low: lh1.low | lh2.low), low: _wideMaskedShiftLeft(lhs.low, shift)) if lhs.high.high == F.Magnitude.zero, (high: F(lhs.high.low), low: lhs.low.high) < rhs { let (quotient, remainder) = _wideDivide32( (F(lhs.high.low), lhs.low.high, lhs.low.low), by: rhs) return ( quotient: (high: 0, low: F.Magnitude(quotient)), remainder: _wideMaskedShiftRight(remainder, shift)) } let (x, a) = _wideDivide32( (lhs.high.high, lhs.high.low, lhs.low.high), by: rhs) let (y, b) = _wideDivide32((a.high, a.low, lhs.low.low), by: rhs) return ( quotient: (high: x, low: F.Magnitude(y)), remainder: _wideMaskedShiftRight(b, shift)) } extension _UInt128: UnsignedInteger {} extension _Int128: SignedNumeric, SignedInteger {} %{ # This finds the magic numbers for signed division by a constant, following # the algorithm described in [Warren 2013, page 212]. def magic(w, d): nc = (2 ** (w - 1)) // d * d - 1 for p in range(2, 2 * w): pp = 2 ** p delta = d - pp % d if pp > nc * delta: m = (pp + delta) // d overflow = m > 2 ** (w - 1) - 1 if overflow: m = m - 2 ** w w2 = w // 2 ml = m & (2 ** w2 - 1) mh = m >> w2 return (mh, ml, p - w, overflow) raise RuntimeError("No magic found") }% % for exp in [18, 15, 12, 9, 6, 3]: % d = 10 ** exp % (mh, ml, s, overflow) = magic(128, d) extension _Int128 { internal func dividedBy1e${exp}() -> (quotient: Self, remainder: Self) { let m = _Int128(high: ${mh}, low: ${ml}) var q = self.multipliedFullWidth(by: m).high % if overflow: q &+= self % end % if s > 0: q &>>= ${s} % end // Add 1 to q if self is negative q &+= _Int128(bitPattern: _UInt128(bitPattern: self) &>> 127) let r = self &- q &* (${d} as _Int128) return (q, r) } } % end