mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
895 lines
27 KiB
Swift
895 lines
27 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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
|
|
|
|
/// The high part of the value.
|
|
internal var 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() {
|
|
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<T: BinaryInteger>(_ source: T) {
|
|
guard let result = Self(exactly: source) else {
|
|
preconditionFailure("Value is outside the representable range")
|
|
}
|
|
self = result
|
|
}
|
|
|
|
internal init?<T: BinaryInteger>(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<Int>
|
|
internal typealias SubSequence = Slice<Self>
|
|
|
|
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<F: FixedWidthInteger> =
|
|
(high: F, low: F.Magnitude)
|
|
|
|
private typealias _Wide3<F: FixedWidthInteger> =
|
|
(high: F, mid: F.Magnitude, low: F.Magnitude)
|
|
|
|
private typealias _Wide4<F: FixedWidthInteger> =
|
|
(high: _Wide2<F>, low: (high: F.Magnitude, low: F.Magnitude))
|
|
|
|
private func _wideMagnitude22<F: FixedWidthInteger>(
|
|
_ v: _Wide2<F>
|
|
) -> _Wide2<F.Magnitude> {
|
|
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<F: FixedWidthInteger>(
|
|
_ lhs: _Wide2<F>, _ rhs: _Wide2<F>
|
|
) -> (partialValue: _Wide2<F>, 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<F: FixedWidthInteger>(
|
|
_ lhs: inout _Wide2<F>, _ rhs: _Wide2<F>
|
|
) {
|
|
let (result, overflow) = _wideAddReportingOverflow22(lhs, rhs)
|
|
_precondition(!overflow, "Overflow in +")
|
|
lhs = result
|
|
}
|
|
|
|
private func _wideAddReportingOverflow33<F: FixedWidthInteger>(
|
|
_ lhs: _Wide3<F>, _ rhs: _Wide3<F>
|
|
) -> (
|
|
partialValue: _Wide3<F>,
|
|
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<F: FixedWidthInteger>(
|
|
_ lhs: _Wide2<F>, _ rhs: _Wide2<F>
|
|
) -> (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<F: FixedWidthInteger>(
|
|
_ lhs: inout _Wide2<F>, _ rhs: _Wide2<F>
|
|
) {
|
|
let (result, overflow) = _wideSubtractReportingOverflow22(lhs, rhs)
|
|
_precondition(!overflow, "Overflow in -")
|
|
lhs = result
|
|
}
|
|
|
|
private func _wideSubtractReportingOverflow33<F: FixedWidthInteger>(
|
|
_ lhs: _Wide3<F>, _ rhs: _Wide3<F>
|
|
) -> (
|
|
partialValue: _Wide3<F>,
|
|
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<F: FixedWidthInteger>(
|
|
_ lhs: _Wide2<F>, _ rhs: F.Magnitude
|
|
) -> _Wide2<F> {
|
|
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<F: FixedWidthInteger>(
|
|
_ lhs: inout _Wide2<F>, _ rhs: F.Magnitude
|
|
) {
|
|
lhs = _wideMaskedShiftLeft(lhs, rhs)
|
|
}
|
|
|
|
private func _wideMaskedShiftRight<F: FixedWidthInteger>(
|
|
_ lhs: _Wide2<F>, _ rhs: F.Magnitude
|
|
) -> _Wide2<F> {
|
|
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<F: FixedWidthInteger>(
|
|
_ lhs: inout _Wide2<F>, _ 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<F: FixedWidthInteger & UnsignedInteger>(
|
|
_ lhs: _Wide3<F>, by rhs: _Wide2<F>
|
|
) -> (quotient: F, remainder: _Wide2<F>) {
|
|
// 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<F: FixedWidthInteger & UnsignedInteger>(
|
|
_ lhs: _Wide2<F>, by rhs: _Wide2<F>
|
|
) -> (quotient: _Wide2<F>, remainder: _Wide2<F>) {
|
|
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<F: FixedWidthInteger & UnsignedInteger>(
|
|
_ lhs: _Wide4<F>, by rhs: _Wide2<F>
|
|
) -> (quotient: _Wide2<F>, remainder: _Wide2<F>) {
|
|
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
|