diff --git a/stdlib/public/Concurrency/Clock.cpp b/stdlib/public/Concurrency/Clock.cpp index 26542ca75f086..bbb6563d89988 100644 --- a/stdlib/public/Concurrency/Clock.cpp +++ b/stdlib/public/Concurrency/Clock.cpp @@ -127,7 +127,7 @@ switch (clock_id) { *seconds = suspending.tv_sec; *nanoseconds = suspending.tv_nsec; #elif defined(__APPLE__) && HAS_TIME - clock_gettime(CLOCK_UPTIME_RAW, &suspending); + clock_getres(CLOCK_UPTIME_RAW, &suspending); *seconds = suspending.tv_sec; *nanoseconds = suspending.tv_nsec; #elif defined(_WIN32) diff --git a/stdlib/public/core/Duration.swift b/stdlib/public/core/Duration.swift index 9e5feba6a1d89..cd3979a6697b8 100644 --- a/stdlib/public/core/Duration.swift +++ b/stdlib/public/core/Duration.swift @@ -43,13 +43,13 @@ public struct Duration: Sendable { internal var _high: Int64 @inlinable - internal init(_low: UInt64, high: Int64) { - self._low = _low - self._high = high + internal init(_high: Int64, low: UInt64) { + self._low = low + self._high = _high } internal init(_attoseconds: _Int128) { - self.init(_low: _attoseconds.low, high: _attoseconds.high) + self.init(_high: _attoseconds.high, low: _attoseconds.low) } /// Construct a `Duration` by adding attoseconds to a seconds value. @@ -86,16 +86,18 @@ public struct Duration: Sendable { internal var _attoseconds: _Int128 { _Int128(high: _high, low: _low) } +} +@available(SwiftStdlib 5.7, *) +extension Duration { /// The composite components of the `Duration`. /// /// This is intended for facilitating conversions to existing time types. The /// attoseconds value will not exceed 1e18 or be lower than -1e18. + @available(SwiftStdlib 5.7, *) public var components: (seconds: Int64, attoseconds: Int64) { - let seconds = _attoseconds / 1_000_000_000_000_000_000 - let attoseconds = - Int64((_attoseconds - seconds * 1_000_000_000_000_000_000)) - return (Int64(seconds), attoseconds) + let (seconds, attoseconds) = _attoseconds.dividedBy1e18() + return (Int64(seconds), Int64(attoseconds)) } } @@ -109,8 +111,8 @@ extension Duration { /// - Returns: A `Duration` representing a given number of seconds. @available(SwiftStdlib 5.7, *) public static func seconds(_ seconds: T) -> Duration { - return Duration(_attoseconds: _Int128(seconds) * - 1_000_000_000_000_000_000) + return Duration(_attoseconds: + _Int128(seconds).multiplied(by: 1_000_000_000_000_000_000 as UInt64)) } /// Construct a `Duration` given a number of seconds represented as a @@ -121,8 +123,7 @@ extension Duration { /// - Returns: A `Duration` representing a given number of seconds. @available(SwiftStdlib 5.7, *) public static func seconds(_ seconds: Double) -> Duration { - return Duration(_attoseconds: _Int128(seconds * - 1_000_000_000_000_000_000)) + return Duration(_attoseconds: _Int128(seconds * 1_000_000_000_000_000_000)) } /// Construct a `Duration` given a number of milliseconds represented as a @@ -135,8 +136,8 @@ extension Duration { public static func milliseconds( _ milliseconds: T ) -> Duration { - return Duration(_attoseconds: _Int128(milliseconds) * - 1_000_000_000_000_000) + return Duration(_attoseconds: + _Int128(milliseconds).multiplied(by: 1_000_000_000_000_000 as UInt64)) } /// Construct a `Duration` given a number of seconds milliseconds as a @@ -147,8 +148,8 @@ extension Duration { /// - Returns: A `Duration` representing a given number of milliseconds. @available(SwiftStdlib 5.7, *) public static func milliseconds(_ milliseconds: Double) -> Duration { - return Duration(_attoseconds: _Int128(milliseconds * - 1_000_000_000_000_000)) + return Duration(_attoseconds: + _Int128(milliseconds * 1_000_000_000_000_000)) } /// Construct a `Duration` given a number of microseconds represented as a @@ -161,8 +162,8 @@ extension Duration { public static func microseconds( _ microseconds: T ) -> Duration { - return Duration(_attoseconds: _Int128(microseconds) * - 1_000_000_000_000) + return Duration(_attoseconds: + _Int128(microseconds).multiplied(by: 1_000_000_000_000 as UInt64)) } /// Construct a `Duration` given a number of seconds microseconds as a @@ -173,8 +174,8 @@ extension Duration { /// - Returns: A `Duration` representing a given number of microseconds. @available(SwiftStdlib 5.7, *) public static func microseconds(_ microseconds: Double) -> Duration { - return Duration(_attoseconds: _Int128(microseconds * - 1_000_000_000_000)) + return Duration(_attoseconds: + _Int128(microseconds * 1_000_000_000_000)) } /// Construct a `Duration` given a number of nanoseconds represented as a @@ -187,21 +188,21 @@ extension Duration { public static func nanoseconds( _ nanoseconds: T ) -> Duration { - return Duration(_attoseconds: _Int128(nanoseconds) * - 1_000_000_000) + return Duration(_attoseconds: + _Int128(nanoseconds).multiplied(by: 1_000_000_000)) } } @available(SwiftStdlib 5.7, *) -extension Duration: Codable { +extension Duration: Codable { @available(SwiftStdlib 5.7, *) public init(from decoder: Decoder) throws { var container = try decoder.unkeyedContainer() let high = try container.decode(Int64.self) let low = try container.decode(UInt64.self) - self.init(_attoseconds: _Int128(high: high, low: low)) + self.init(_high: high, low: low) } - + @available(SwiftStdlib 5.7, *) public func encode(to encoder: Encoder) throws { var container = encoder.unkeyedContainer() @@ -211,7 +212,7 @@ extension Duration: Codable { } @available(SwiftStdlib 5.7, *) -extension Duration: Hashable { +extension Duration: Hashable { @available(SwiftStdlib 5.7, *) public func hash(into hasher: inout Hasher) { hasher.combine(_attoseconds) diff --git a/stdlib/public/core/Int128.swift.gyb b/stdlib/public/core/Int128.swift.gyb index cdad5c7fc88c2..af20fe37fc5d2 100644 --- a/stdlib/public/core/Int128.swift.gyb +++ b/stdlib/public/core/Int128.swift.gyb @@ -149,7 +149,7 @@ extension _${U}Int128: Numeric { // Is 'source' entirely representable in Low? if let low = Low(exactly: source.magnitude) { - self.init(source._isNegative ? (~0, ~low &+ 1) : (0, low)) + 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. @@ -260,7 +260,7 @@ extension _${U}Int128: FixedWidthInteger { let isNegative = (self._isNegative != rhs._isNegative) let (p, overflow) = self.magnitude.multipliedReportingOverflow( by: rhs.magnitude) - let r = _Int128(bitPattern: isNegative ? ~(p &- .one) : p) + let r = _Int128(bitPattern: isNegative ? p._twosComplement : p) return (r, overflow || (isNegative != r._isNegative)) % else: let h1 = self.high.multipliedReportingOverflow(by: rhs.low) @@ -275,6 +275,31 @@ extension _${U}Int128: FixedWidthInteger { % 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 + 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) { @@ -282,9 +307,7 @@ extension _${U}Int128: FixedWidthInteger { self.magnitude.components, by: other.magnitude.components) let quotient = Self.Magnitude(q) let remainder = Self.Magnitude(r) - guard Self.isSigned else { - return (Self(quotient), Self(remainder)) - } + % if signed: let isNegative = (self.high._isNegative != other.high._isNegative) let quotient_ = (isNegative ? quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient) @@ -293,6 +316,9 @@ extension _${U}Int128: FixedWidthInteger { ? 0 - Self(remainder) : Self(remainder)) return (quotient_, remainder_) + % else: + return (quotient, remainder) + % end } internal func dividedReportingOverflow( @@ -514,6 +540,13 @@ extension BinaryInteger { 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) @@ -725,8 +758,9 @@ private func _wideDivide22( // 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, F.Magnitude(F.bitWidth) &- shift).low + 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) @@ -798,3 +832,44 @@ private func _wideDivide42( 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