@@ -282,9 +282,7 @@ extension _${U}Int128: FixedWidthInteger {
282
282
self.magnitude.components, by: other.magnitude.components)
283
283
let quotient = Self.Magnitude(q)
284
284
let remainder = Self.Magnitude(r)
285
- guard Self.isSigned else {
286
- return (Self(quotient), Self(remainder))
287
- }
285
+ % if signed:
288
286
let isNegative = (self.high._isNegative != other.high._isNegative)
289
287
let quotient_ = (isNegative
290
288
? quotient == Self.min.magnitude ? Self.min : 0 - Self(quotient)
@@ -293,6 +291,9 @@ extension _${U}Int128: FixedWidthInteger {
293
291
? 0 - Self(remainder)
294
292
: Self(remainder))
295
293
return (quotient_, remainder_)
294
+ % else:
295
+ return (quotient, remainder)
296
+ % end
296
297
}
297
298
298
299
internal func dividedReportingOverflow(
@@ -799,3 +800,44 @@ private func _wideDivide42<F: FixedWidthInteger & UnsignedInteger>(
799
800
800
801
extension _UInt128: UnsignedInteger {}
801
802
extension _Int128: SignedNumeric, SignedInteger {}
803
+
804
+ %{
805
+ # This finds the magic numbers for signed division by a constant, following
806
+ # the algorithm described in [Warren 2013, page 212].
807
+ def magic(w, d):
808
+ nc = (2 ** (w - 1)) // d * d - 1
809
+ for p in range(2, 2 * w):
810
+ pp = 2 ** p
811
+ delta = d - pp % d
812
+ if pp > nc * delta:
813
+ m = (pp + delta) // d
814
+ overflow = m > 2 ** (w - 1) - 1
815
+ if overflow:
816
+ m = m - 2 ** w
817
+ w2 = w // 2
818
+ ml = m & (2 ** w2 - 1)
819
+ mh = m >> w2
820
+ return (mh, ml, p - w, overflow)
821
+ raise RuntimeError("No magic found")
822
+ }%
823
+
824
+ % for exp in [18, 15, 12, 9, 6, 3]:
825
+ % d = 10 ** exp
826
+ % (mh, ml, s, overflow) = magic(128, d)
827
+ extension _Int128 {
828
+ internal func dividedBy1e${exp}() -> (quotient: Self, remainder: Self) {
829
+ let m = _Int128(high: ${mh}, low: ${ml})
830
+ var q = self.multipliedFullWidth(by: m).high
831
+ % if overflow:
832
+ q &+= self
833
+ % end
834
+ % if s > 0:
835
+ q &>>= ${s}
836
+ % end
837
+ // Add 1 to q if self is negative
838
+ q &+= _Int128(bitPattern: _UInt128(bitPattern: self) &>> 127)
839
+ let r = self &- q &* (${d} as _Int128)
840
+ return (q, r)
841
+ }
842
+ }
843
+ % end
0 commit comments