Skip to content

Commit c00322d

Browse files
committed
[stdlib] Int128: Add direct multiplication by a single UInt64 value
1 parent 2cc1e2a commit c00322d

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

stdlib/public/core/Int128.swift.gyb

Lines changed: 34 additions & 2 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,6 +275,31 @@ 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) {
@@ -515,6 +540,13 @@ extension BinaryInteger {
515540
fileprivate var _isNegative: Bool { self < Self.zero }
516541
}
517542

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

0 commit comments

Comments
 (0)