Skip to content

Commit d384a79

Browse files
authored
Merge pull request swiftlang#41512 from lorentey/clock-fixes
[stdlib] Some more clock adjustments
2 parents d59866f + 3680ea6 commit d384a79

File tree

3 files changed

+109
-33
lines changed

3 files changed

+109
-33
lines changed

stdlib/public/Concurrency/Clock.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ switch (clock_id) {
127127
*seconds = suspending.tv_sec;
128128
*nanoseconds = suspending.tv_nsec;
129129
#elif defined(__APPLE__) && HAS_TIME
130-
clock_gettime(CLOCK_UPTIME_RAW, &suspending);
130+
clock_getres(CLOCK_UPTIME_RAW, &suspending);
131131
*seconds = suspending.tv_sec;
132132
*nanoseconds = suspending.tv_nsec;
133133
#elif defined(_WIN32)

stdlib/public/core/Duration.swift

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ public struct Duration: Sendable {
4343
internal var _high: Int64
4444

4545
@inlinable
46-
internal init(_low: UInt64, high: Int64) {
47-
self._low = _low
48-
self._high = high
46+
internal init(_high: Int64, low: UInt64) {
47+
self._low = low
48+
self._high = _high
4949
}
5050

5151
internal init(_attoseconds: _Int128) {
52-
self.init(_low: _attoseconds.low, high: _attoseconds.high)
52+
self.init(_high: _attoseconds.high, low: _attoseconds.low)
5353
}
5454

5555
/// Construct a `Duration` by adding attoseconds to a seconds value.
@@ -86,16 +86,18 @@ public struct Duration: Sendable {
8686
internal var _attoseconds: _Int128 {
8787
_Int128(high: _high, low: _low)
8888
}
89+
}
8990

91+
@available(SwiftStdlib 5.7, *)
92+
extension Duration {
9093
/// The composite components of the `Duration`.
9194
///
9295
/// This is intended for facilitating conversions to existing time types. The
9396
/// attoseconds value will not exceed 1e18 or be lower than -1e18.
97+
@available(SwiftStdlib 5.7, *)
9498
public var components: (seconds: Int64, attoseconds: Int64) {
95-
let seconds = _attoseconds / 1_000_000_000_000_000_000
96-
let attoseconds =
97-
Int64((_attoseconds - seconds * 1_000_000_000_000_000_000))
98-
return (Int64(seconds), attoseconds)
99+
let (seconds, attoseconds) = _attoseconds.dividedBy1e18()
100+
return (Int64(seconds), Int64(attoseconds))
99101
}
100102
}
101103

@@ -109,8 +111,8 @@ extension Duration {
109111
/// - Returns: A `Duration` representing a given number of seconds.
110112
@available(SwiftStdlib 5.7, *)
111113
public static func seconds<T: BinaryInteger>(_ seconds: T) -> Duration {
112-
return Duration(_attoseconds: _Int128(seconds) *
113-
1_000_000_000_000_000_000)
114+
return Duration(_attoseconds:
115+
_Int128(seconds).multiplied(by: 1_000_000_000_000_000_000 as UInt64))
114116
}
115117

116118
/// Construct a `Duration` given a number of seconds represented as a
@@ -121,8 +123,7 @@ extension Duration {
121123
/// - Returns: A `Duration` representing a given number of seconds.
122124
@available(SwiftStdlib 5.7, *)
123125
public static func seconds(_ seconds: Double) -> Duration {
124-
return Duration(_attoseconds: _Int128(seconds *
125-
1_000_000_000_000_000_000))
126+
return Duration(_attoseconds: _Int128(seconds * 1_000_000_000_000_000_000))
126127
}
127128

128129
/// Construct a `Duration` given a number of milliseconds represented as a
@@ -135,8 +136,8 @@ extension Duration {
135136
public static func milliseconds<T: BinaryInteger>(
136137
_ milliseconds: T
137138
) -> Duration {
138-
return Duration(_attoseconds: _Int128(milliseconds) *
139-
1_000_000_000_000_000)
139+
return Duration(_attoseconds:
140+
_Int128(milliseconds).multiplied(by: 1_000_000_000_000_000 as UInt64))
140141
}
141142

142143
/// Construct a `Duration` given a number of seconds milliseconds as a
@@ -147,8 +148,8 @@ extension Duration {
147148
/// - Returns: A `Duration` representing a given number of milliseconds.
148149
@available(SwiftStdlib 5.7, *)
149150
public static func milliseconds(_ milliseconds: Double) -> Duration {
150-
return Duration(_attoseconds: _Int128(milliseconds *
151-
1_000_000_000_000_000))
151+
return Duration(_attoseconds:
152+
_Int128(milliseconds * 1_000_000_000_000_000))
152153
}
153154

154155
/// Construct a `Duration` given a number of microseconds represented as a
@@ -161,8 +162,8 @@ extension Duration {
161162
public static func microseconds<T: BinaryInteger>(
162163
_ microseconds: T
163164
) -> Duration {
164-
return Duration(_attoseconds: _Int128(microseconds) *
165-
1_000_000_000_000)
165+
return Duration(_attoseconds:
166+
_Int128(microseconds).multiplied(by: 1_000_000_000_000 as UInt64))
166167
}
167168

168169
/// Construct a `Duration` given a number of seconds microseconds as a
@@ -173,8 +174,8 @@ extension Duration {
173174
/// - Returns: A `Duration` representing a given number of microseconds.
174175
@available(SwiftStdlib 5.7, *)
175176
public static func microseconds(_ microseconds: Double) -> Duration {
176-
return Duration(_attoseconds: _Int128(microseconds *
177-
1_000_000_000_000))
177+
return Duration(_attoseconds:
178+
_Int128(microseconds * 1_000_000_000_000))
178179
}
179180

180181
/// Construct a `Duration` given a number of nanoseconds represented as a
@@ -187,21 +188,21 @@ extension Duration {
187188
public static func nanoseconds<T: BinaryInteger>(
188189
_ nanoseconds: T
189190
) -> Duration {
190-
return Duration(_attoseconds: _Int128(nanoseconds) *
191-
1_000_000_000)
191+
return Duration(_attoseconds:
192+
_Int128(nanoseconds).multiplied(by: 1_000_000_000))
192193
}
193194
}
194195

195196
@available(SwiftStdlib 5.7, *)
196-
extension Duration: Codable {
197+
extension Duration: Codable {
197198
@available(SwiftStdlib 5.7, *)
198199
public init(from decoder: Decoder) throws {
199200
var container = try decoder.unkeyedContainer()
200201
let high = try container.decode(Int64.self)
201202
let low = try container.decode(UInt64.self)
202-
self.init(_attoseconds: _Int128(high: high, low: low))
203+
self.init(_high: high, low: low)
203204
}
204-
205+
205206
@available(SwiftStdlib 5.7, *)
206207
public func encode(to encoder: Encoder) throws {
207208
var container = encoder.unkeyedContainer()
@@ -211,7 +212,7 @@ extension Duration: Codable {
211212
}
212213

213214
@available(SwiftStdlib 5.7, *)
214-
extension Duration: Hashable {
215+
extension Duration: Hashable {
215216
@available(SwiftStdlib 5.7, *)
216217
public func hash(into hasher: inout Hasher) {
217218
hasher.combine(_attoseconds)

stdlib/public/core/Int128.swift.gyb

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ extension _${U}Int128: Numeric {
149149

150150
// Is 'source' entirely representable in Low?
151151
if let low = Low(exactly: source.magnitude) {
152-
self.init(source._isNegative ? (~0, ~low &+ 1) : (0, low))
152+
self.init(source._isNegative ? (~0, low._twosComplement) : (0, low))
153153
} else {
154154
// At this point we know source.bitWidth > High.bitWidth, or else we
155155
// would've taken the first branch.
@@ -260,7 +260,7 @@ extension _${U}Int128: FixedWidthInteger {
260260
let isNegative = (self._isNegative != rhs._isNegative)
261261
let (p, overflow) = self.magnitude.multipliedReportingOverflow(
262262
by: rhs.magnitude)
263-
let r = _Int128(bitPattern: isNegative ? ~(p &- .one) : p)
263+
let r = _Int128(bitPattern: isNegative ? p._twosComplement : p)
264264
return (r, overflow || (isNegative != r._isNegative))
265265
% else:
266266
let h1 = self.high.multipliedReportingOverflow(by: rhs.low)
@@ -275,16 +275,39 @@ extension _${U}Int128: FixedWidthInteger {
275275
% end
276276
}
277277

278+
/// Returns the product of this value and the given 64-bit value, along with a
279+
/// Boolean value indicating whether overflow occurred in the operation.
280+
internal func multipliedReportingOverflow(
281+
by other: UInt64
282+
) -> (partialValue: Self, overflow: Bool) {
283+
% if signed:
284+
let isNegative = self._isNegative
285+
let (p, overflow) = self.magnitude.multipliedReportingOverflow(by: other)
286+
let r = _Int128(bitPattern: isNegative ? p._twosComplement : p)
287+
return (r, overflow || (isNegative != r._isNegative))
288+
% else:
289+
let h1 = self.high.multipliedReportingOverflow(by: other)
290+
let (h2, l) = self.low.multipliedFullWidth(by: other)
291+
let high = h1.partialValue.addingReportingOverflow(h2)
292+
let overflow = h1.overflow || high.overflow
293+
return (Self(high: high.partialValue, low: l), overflow)
294+
% end
295+
}
296+
297+
internal func multiplied(by other: UInt64) -> Self {
298+
let r = multipliedReportingOverflow(by: other)
299+
_precondition(!r.overflow, "Overflow in multiplication")
300+
return r.partialValue
301+
}
302+
278303
internal func quotientAndRemainder(
279304
dividingBy other: Self
280305
) -> (quotient: Self, remainder: Self) {
281306
let (q, r) = _wideDivide22(
282307
self.magnitude.components, by: other.magnitude.components)
283308
let quotient = Self.Magnitude(q)
284309
let remainder = Self.Magnitude(r)
285-
guard Self.isSigned else {
286-
return (Self(quotient), Self(remainder))
287-
}
310+
% if signed:
288311
let isNegative = (self.high._isNegative != other.high._isNegative)
289312
let quotient_ = (isNegative
290313
? quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient)
@@ -293,6 +316,9 @@ extension _${U}Int128: FixedWidthInteger {
293316
? 0 - Self(remainder)
294317
: Self(remainder))
295318
return (quotient_, remainder_)
319+
% else:
320+
return (quotient, remainder)
321+
% end
296322
}
297323

298324
internal func dividedReportingOverflow(
@@ -514,6 +540,13 @@ extension BinaryInteger {
514540
fileprivate var _isNegative: Bool { self < Self.zero }
515541
}
516542

543+
extension FixedWidthInteger {
544+
@inline(__always)
545+
fileprivate var _twosComplement: Self {
546+
~self &+ 1
547+
}
548+
}
549+
517550
private typealias _Wide2<F: FixedWidthInteger> =
518551
(high: F, low: F.Magnitude)
519552

@@ -725,8 +758,9 @@ private func _wideDivide22<F: FixedWidthInteger & UnsignedInteger>(
725758

726759
// Left shift both rhs and lhs, then divide and right shift the remainder.
727760
let shift = F.Magnitude(rhs.high.leadingZeroBitCount)
761+
let rollover = F.Magnitude(F.bitWidth + F.Magnitude.bitWidth) &- shift
728762
let rhs = _wideMaskedShiftLeft(rhs, shift)
729-
let high = _wideMaskedShiftRight(lhs, F.Magnitude(F.bitWidth) &- shift).low
763+
let high = _wideMaskedShiftRight(lhs, rollover).low
730764
let lhs = _wideMaskedShiftLeft(lhs, shift)
731765
let (quotient, remainder) = _wideDivide32(
732766
(F(high), F.Magnitude(lhs.high), lhs.low), by: rhs)
@@ -798,3 +832,44 @@ private func _wideDivide42<F: FixedWidthInteger & UnsignedInteger>(
798832

799833
extension _UInt128: UnsignedInteger {}
800834
extension _Int128: SignedNumeric, SignedInteger {}
835+
836+
%{
837+
# This finds the magic numbers for signed division by a constant, following
838+
# the algorithm described in [Warren 2013, page 212].
839+
def magic(w, d):
840+
nc = (2 ** (w - 1)) // d * d - 1
841+
for p in range(2, 2 * w):
842+
pp = 2 ** p
843+
delta = d - pp % d
844+
if pp > nc * delta:
845+
m = (pp + delta) // d
846+
overflow = m > 2 ** (w - 1) - 1
847+
if overflow:
848+
m = m - 2 ** w
849+
w2 = w // 2
850+
ml = m & (2 ** w2 - 1)
851+
mh = m >> w2
852+
return (mh, ml, p - w, overflow)
853+
raise RuntimeError("No magic found")
854+
}%
855+
856+
% for exp in [18, 15, 12, 9, 6, 3]:
857+
% d = 10 ** exp
858+
% (mh, ml, s, overflow) = magic(128, d)
859+
extension _Int128 {
860+
internal func dividedBy1e${exp}() -> (quotient: Self, remainder: Self) {
861+
let m = _Int128(high: ${mh}, low: ${ml})
862+
var q = self.multipliedFullWidth(by: m).high
863+
% if overflow:
864+
q &+= self
865+
% end
866+
% if s > 0:
867+
q &>>= ${s}
868+
% end
869+
// Add 1 to q if self is negative
870+
q &+= _Int128(bitPattern: _UInt128(bitPattern: self) &>> 127)
871+
let r = self &- q &* (${d} as _Int128)
872+
return (q, r)
873+
}
874+
}
875+
% end

0 commit comments

Comments
 (0)