@@ -393,8 +393,10 @@ extension DoubleWidth : FixedWidthInteger {
393393
394394 let low =
395395 DoubleWidth<Low>(mid1.partial, a.partial)
396+ let (sum_, overflow_) =
397+ mid1.carry.addingReportingOverflow(mid2.partial)
396398 let high =
397- DoubleWidth(High(mid2.carry + d.carry), mid1.carry + mid2.partial )
399+ DoubleWidth(High(mid2.carry + d.carry + (overflow_ ? 1 : 0)), sum_ )
398400
399401 if isNegative {
400402 let (lowComplement, overflow) = (~low).addingReportingOverflow(1)
@@ -595,10 +597,14 @@ extension DoubleWidth : UnsignedInteger where Base : UnsignedInteger {
595597 ) -> (quotient: Low, remainder: Magnitude) {
596598 // The following invariants are guaranteed to hold by dividingFullWidth or
597599 // quotientAndRemainder before this method is invoked:
598- assert(lhs.high != (0 as Low))
599600 assert(rhs.leadingZeroBitCount == 0)
600601 assert(Magnitude(lhs.high, lhs.mid) < rhs)
601602
603+ guard lhs.high != (0 as Low) else {
604+ let lhs_ = Magnitude(lhs.mid, lhs.low)
605+ return lhs_ < rhs ? (0, lhs_) : (1, lhs_ &- rhs)
606+ }
607+
602608 // Estimate the quotient.
603609 var quotient = lhs.high == rhs.high
604610 ? Low.max
@@ -699,12 +705,13 @@ extension DoubleWidth : UnsignedInteger where Base : UnsignedInteger {
699705
700706 // Left shift both rhs and lhs, then divide and right shift the remainder.
701707 let shift = rhs.leadingZeroBitCount
708+ // Note the use of `>>` instead of `&>>` below,
709+ // as `high` should be zero if `shift` is zero.
702710 let high = (lhs >> (Magnitude.bitWidth &- shift)).low
703711 let rhs = rhs &<< shift
704712 let lhs = lhs &<< shift
705- let (quotient, remainder) = high == (0 as Low)
706- ? (1, lhs &- rhs)
707- : Magnitude._divide((high, lhs.high, lhs.low), by: rhs)
713+ let (quotient, remainder) =
714+ Magnitude._divide((high, lhs.high, lhs.low), by: rhs)
708715 return (Magnitude(0, quotient), remainder &>> shift)
709716 }
710717}
@@ -813,15 +820,27 @@ dwTests.test("Arithmetic/unsigned") {
813820 expectEqual(lhs % rhs, 4096)
814821 }
815822 do {
816- let lhs = DoubleWidth<UInt64> ((high: 0xa0c7d7165cf01386, low: 0xbf3f66a93056143f))
817- let rhs = DoubleWidth<UInt64> ((high: 0x9ac3a19b1e7d6b83, low: 0x513929792d588736))
823+ let lhs = UInt128 ((high: 0xa0c7d7165cf01386, low: 0xbf3f66a93056143f))
824+ let rhs = UInt128 ((high: 0x9ac3a19b1e7d6b83, low: 0x513929792d588736))
818825 expectEqual(String(lhs % rhs), "7997221894243298914179865336050715913")
819826 }
820827 do {
821- let lhs = DoubleWidth<UInt64> ((high: 0xea8a9116b7af33b7, low: 0x3d9d6779ddd22ca3))
822- let rhs = DoubleWidth<UInt64> ((high: 0xc3673efc7f1f37cc, low: 0x312f661057d0ba94))
828+ let lhs = UInt128 ((high: 0xea8a9116b7af33b7, low: 0x3d9d6779ddd22ca3))
829+ let rhs = UInt128 ((high: 0xc3673efc7f1f37cc, low: 0x312f661057d0ba94))
823830 expectEqual(String(lhs % rhs), "52023287460685389410162512181093036559")
824831 }
832+ do {
833+ let lhs = UInt256("2369676578372158364766242369061213561181961479062237766620")!
834+ let rhs = UInt256("102797312405202436815976773795958969482")!
835+ expectEqual(String(lhs / rhs), "23051931251193218442")
836+ }
837+ do {
838+ let lhs = UInt256("96467201117289166187766181030232879447148862859323917044548749804018359008044")!
839+ let rhs = UInt256("4646260627574879223760172113656436161581617773435991717024")!
840+ expectEqual(String(lhs / rhs), "20762331011904583253")
841+ }
842+
843+ expectTrue((0xff01 as DoubleWidth<UInt8>).multipliedFullWidth(by: 0x101) == (high: 256, low: 1))
825844}
826845
827846dwTests.test("Arithmetic/signed") {
0 commit comments