@@ -393,8 +393,10 @@ extension DoubleWidth : FixedWidthInteger {
393
393
394
394
let low =
395
395
DoubleWidth<Low>(mid1.partial, a.partial)
396
+ let (sum_, overflow_) =
397
+ mid1.carry.addingReportingOverflow(mid2.partial)
396
398
let high =
397
- DoubleWidth(High(mid2.carry + d.carry), mid1.carry + mid2.partial )
399
+ DoubleWidth(High(mid2.carry + d.carry + (overflow_ ? 1 : 0)), sum_ )
398
400
399
401
if isNegative {
400
402
let (lowComplement, overflow) = (~low).addingReportingOverflow(1)
@@ -595,10 +597,14 @@ extension DoubleWidth : UnsignedInteger where Base : UnsignedInteger {
595
597
) -> (quotient: Low, remainder: Magnitude) {
596
598
// The following invariants are guaranteed to hold by dividingFullWidth or
597
599
// quotientAndRemainder before this method is invoked:
598
- assert(lhs.high != (0 as Low))
599
600
assert(rhs.leadingZeroBitCount == 0)
600
601
assert(Magnitude(lhs.high, lhs.mid) < rhs)
601
602
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
+
602
608
// Estimate the quotient.
603
609
var quotient = lhs.high == rhs.high
604
610
? Low.max
@@ -699,12 +705,13 @@ extension DoubleWidth : UnsignedInteger where Base : UnsignedInteger {
699
705
700
706
// Left shift both rhs and lhs, then divide and right shift the remainder.
701
707
let shift = rhs.leadingZeroBitCount
708
+ // Note the use of `>>` instead of `&>>` below,
709
+ // as `high` should be zero if `shift` is zero.
702
710
let high = (lhs >> (Magnitude.bitWidth &- shift)).low
703
711
let rhs = rhs &<< shift
704
712
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)
708
715
return (Magnitude(0, quotient), remainder &>> shift)
709
716
}
710
717
}
@@ -813,15 +820,27 @@ dwTests.test("Arithmetic/unsigned") {
813
820
expectEqual(lhs % rhs, 4096)
814
821
}
815
822
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))
818
825
expectEqual(String(lhs % rhs), "7997221894243298914179865336050715913")
819
826
}
820
827
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))
823
830
expectEqual(String(lhs % rhs), "52023287460685389410162512181093036559")
824
831
}
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))
825
844
}
826
845
827
846
dwTests.test("Arithmetic/signed") {
0 commit comments