| ... | @@ -534,13 +534,14 @@ pub const Int = struct { | ... | @@ -534,13 +534,14 @@ pub const Int = struct { |
| 534 | return out_stream.writeAll(str); | 534 | return out_stream.writeAll(str); |
| 535 | } | 535 | } |
| 536 | | 536 | |
| 537 | /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively. | 537 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if |a| < |b|, |a| == |
| 538 | pub fn cmpAbs(a: Int, b: Int) i8 { | 538 | /// |b| or |a| > |b| respectively. |
| | 539 | pub fn cmpAbs(a: Int, b: Int) math.Order { |
| 539 | if (a.len() < b.len()) { | 540 | if (a.len() < b.len()) { |
| 540 | return -1; | 541 | return .lt; |
| 541 | } | 542 | } |
| 542 | if (a.len() > b.len()) { | 543 | if (a.len() > b.len()) { |
| 543 | return 1; | 544 | return .gt; |
| 544 | } | 545 | } |
| 545 | | 546 | |
| 546 | var i: usize = a.len() - 1; | 547 | var i: usize = a.len() - 1; |
| ... | @@ -551,21 +552,26 @@ pub const Int = struct { | ... | @@ -551,21 +552,26 @@ pub const Int = struct { |
| 551 | } | 552 | } |
| 552 | | 553 | |
| 553 | if (a.limbs[i] < b.limbs[i]) { | 554 | if (a.limbs[i] < b.limbs[i]) { |
| 554 | return -1; | 555 | return .lt; |
| 555 | } else if (a.limbs[i] > b.limbs[i]) { | 556 | } else if (a.limbs[i] > b.limbs[i]) { |
| 556 | return 1; | 557 | return .gt; |
| 557 | } else { | 558 | } else { |
| 558 | return 0; | 559 | return .eq; |
| 559 | } | 560 | } |
| 560 | } | 561 | } |
| 561 | | 562 | |
| 562 | /// Returns -1, 0, 1 if a < b, a == b or a > b respectively. | 563 | /// Returns math.Order.lt, math.Order.eq, math.Order.gt if a < b, a == b or a |
| 563 | pub fn cmp(a: Int, b: Int) i8 { | 564 | /// > b respectively. |
| | 565 | pub fn cmp(a: Int, b: Int) math.Order { |
| 564 | if (a.isPositive() != b.isPositive()) { | 566 | if (a.isPositive() != b.isPositive()) { |
| 565 | return if (a.isPositive()) @as(i8, 1) else -1; | 567 | return if (a.isPositive()) .gt else .lt; |
| 566 | } else { | 568 | } else { |
| 567 | const r = cmpAbs(a, b); | 569 | const r = cmpAbs(a, b); |
| 568 | return if (a.isPositive()) r else -r; | 570 | return if (a.isPositive()) r else switch (r) { |
| | 571 | .lt => math.Order.gt, |
| | 572 | .eq => math.Order.eq, |
| | 573 | .gt => math.Order.lt, |
| | 574 | }; |
| 569 | } | 575 | } |
| 570 | } | 576 | } |
| 571 | | 577 | |
| ... | @@ -576,12 +582,12 @@ pub const Int = struct { | ... | @@ -576,12 +582,12 @@ pub const Int = struct { |
| 576 | | 582 | |
| 577 | /// Returns true if |a| == |b|. | 583 | /// Returns true if |a| == |b|. |
| 578 | pub fn eqAbs(a: Int, b: Int) bool { | 584 | pub fn eqAbs(a: Int, b: Int) bool { |
| 579 | return cmpAbs(a, b) == 0; | 585 | return cmpAbs(a, b) == .eq; |
| 580 | } | 586 | } |
| 581 | | 587 | |
| 582 | /// Returns true if a == b. | 588 | /// Returns true if a == b. |
| 583 | pub fn eq(a: Int, b: Int) bool { | 589 | pub fn eq(a: Int, b: Int) bool { |
| 584 | return cmp(a, b) == 0; | 590 | return cmp(a, b) == .eq; |
| 585 | } | 591 | } |
| 586 | | 592 | |
| 587 | // Normalize a possible sequence of leading zeros. | 593 | // Normalize a possible sequence of leading zeros. |
| ... | @@ -694,7 +700,7 @@ pub const Int = struct { | ... | @@ -694,7 +700,7 @@ pub const Int = struct { |
| 694 | } else { | 700 | } else { |
| 695 | if (a.isPositive()) { | 701 | if (a.isPositive()) { |
| 696 | // (a) - (b) => a - b | 702 | // (a) - (b) => a - b |
| 697 | if (a.cmp(b) >= 0) { | 703 | if (a.cmp(b) != .lt) { |
| 698 | try r.ensureCapacity(a.len() + 1); | 704 | try r.ensureCapacity(a.len() + 1); |
| 699 | llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); | 705 | llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); |
| 700 | r.normalize(a.len()); | 706 | r.normalize(a.len()); |
| ... | @@ -707,7 +713,7 @@ pub const Int = struct { | ... | @@ -707,7 +713,7 @@ pub const Int = struct { |
| 707 | } | 713 | } |
| 708 | } else { | 714 | } else { |
| 709 | // (-a) - (-b) => -(a - b) | 715 | // (-a) - (-b) => -(a - b) |
| 710 | if (a.cmp(b) < 0) { | 716 | if (a.cmp(b) == .lt) { |
| 711 | try r.ensureCapacity(a.len() + 1); | 717 | try r.ensureCapacity(a.len() + 1); |
| 712 | llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); | 718 | llsub(r.limbs[0..], a.limbs[0..a.len()], b.limbs[0..b.len()]); |
| 713 | r.normalize(a.len()); | 719 | r.normalize(a.len()); |
| ... | @@ -1010,7 +1016,7 @@ pub const Int = struct { | ... | @@ -1010,7 +1016,7 @@ pub const Int = struct { |
| 1010 | @panic("quo and rem cannot be same variable"); | 1016 | @panic("quo and rem cannot be same variable"); |
| 1011 | } | 1017 | } |
| 1012 | | 1018 | |
| 1013 | if (a.cmpAbs(b) < 0) { | 1019 | if (a.cmpAbs(b) == .lt) { |
| 1014 | // quo may alias a so handle rem first | 1020 | // quo may alias a so handle rem first |
| 1015 | try rem.copy(a); | 1021 | try rem.copy(a); |
| 1016 | rem.setSign(a.isPositive() == b.isPositive()); | 1022 | rem.setSign(a.isPositive() == b.isPositive()); |
| ... | @@ -1133,7 +1139,7 @@ pub const Int = struct { | ... | @@ -1133,7 +1139,7 @@ pub const Int = struct { |
| 1133 | | 1139 | |
| 1134 | // 2. | 1140 | // 2. |
| 1135 | try tmp.shiftLeft(y.*, Limb.bit_count * (n - t)); | 1141 | try tmp.shiftLeft(y.*, Limb.bit_count * (n - t)); |
| 1136 | while (x.cmp(tmp) >= 0) { | 1142 | while (x.cmp(tmp) != .lt) { |
| 1137 | q.limbs[n - t] += 1; | 1143 | q.limbs[n - t] += 1; |
| 1138 | try x.sub(x.*, tmp); | 1144 | try x.sub(x.*, tmp); |
| 1139 | } | 1145 | } |
| ... | @@ -1164,7 +1170,7 @@ pub const Int = struct { | ... | @@ -1164,7 +1170,7 @@ pub const Int = struct { |
| 1164 | r.limbs[2] = carry; | 1170 | r.limbs[2] = carry; |
| 1165 | r.normalize(3); | 1171 | r.normalize(3); |
| 1166 | | 1172 | |
| 1167 | if (r.cmpAbs(tmp) <= 0) { | 1173 | if (r.cmpAbs(tmp) != .gt) { |
| 1168 | break; | 1174 | break; |
| 1169 | } | 1175 | } |
| 1170 | | 1176 | |
| ... | @@ -1719,8 +1725,8 @@ test "big.int compare" { | ... | @@ -1719,8 +1725,8 @@ test "big.int compare" { |
| 1719 | var b = try Int.initSet(testing.allocator, 10); | 1725 | var b = try Int.initSet(testing.allocator, 10); |
| 1720 | defer b.deinit(); | 1726 | defer b.deinit(); |
| 1721 | | 1727 | |
| 1722 | testing.expect(a.cmpAbs(b) == 1); | 1728 | testing.expect(a.cmpAbs(b) == .gt); |
| 1723 | testing.expect(a.cmp(b) == -1); | 1729 | testing.expect(a.cmp(b) == .lt); |
| 1724 | } | 1730 | } |
| 1725 | | 1731 | |
| 1726 | test "big.int compare similar" { | 1732 | test "big.int compare similar" { |
| ... | @@ -1729,8 +1735,8 @@ test "big.int compare similar" { | ... | @@ -1729,8 +1735,8 @@ test "big.int compare similar" { |
| 1729 | var b = try Int.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeef); | 1735 | var b = try Int.initSet(testing.allocator, 0xffffffffeeeeeeeeffffffffeeeeeeef); |
| 1730 | defer b.deinit(); | 1736 | defer b.deinit(); |
| 1731 | | 1737 | |
| 1732 | testing.expect(a.cmpAbs(b) == -1); | 1738 | testing.expect(a.cmpAbs(b) == .lt); |
| 1733 | testing.expect(b.cmpAbs(a) == 1); | 1739 | testing.expect(b.cmpAbs(a) == .gt); |
| 1734 | } | 1740 | } |
| 1735 | | 1741 | |
| 1736 | test "big.int compare different limb size" { | 1742 | test "big.int compare different limb size" { |
| ... | @@ -1739,8 +1745,8 @@ test "big.int compare different limb size" { | ... | @@ -1739,8 +1745,8 @@ test "big.int compare different limb size" { |
| 1739 | var b = try Int.initSet(testing.allocator, 1); | 1745 | var b = try Int.initSet(testing.allocator, 1); |
| 1740 | defer b.deinit(); | 1746 | defer b.deinit(); |
| 1741 | | 1747 | |
| 1742 | testing.expect(a.cmpAbs(b) == 1); | 1748 | testing.expect(a.cmpAbs(b) == .gt); |
| 1743 | testing.expect(b.cmpAbs(a) == -1); | 1749 | testing.expect(b.cmpAbs(a) == .lt); |
| 1744 | } | 1750 | } |
| 1745 | | 1751 | |
| 1746 | test "big.int compare multi-limb" { | 1752 | test "big.int compare multi-limb" { |
| ... | @@ -1749,8 +1755,8 @@ test "big.int compare multi-limb" { | ... | @@ -1749,8 +1755,8 @@ test "big.int compare multi-limb" { |
| 1749 | var b = try Int.initSet(testing.allocator, 0x7777777799999999ffffeeeeffffeeeeffffeeeee); | 1755 | var b = try Int.initSet(testing.allocator, 0x7777777799999999ffffeeeeffffeeeeffffeeeee); |
| 1750 | defer b.deinit(); | 1756 | defer b.deinit(); |
| 1751 | | 1757 | |
| 1752 | testing.expect(a.cmpAbs(b) == 1); | 1758 | testing.expect(a.cmpAbs(b) == .gt); |
| 1753 | testing.expect(a.cmp(b) == -1); | 1759 | testing.expect(a.cmp(b) == .lt); |
| 1754 | } | 1760 | } |
| 1755 | | 1761 | |
| 1756 | test "big.int equality" { | 1762 | test "big.int equality" { |
| ... | @@ -2726,9 +2732,9 @@ test "big.int var args" { | ... | @@ -2726,9 +2732,9 @@ test "big.int var args" { |
| 2726 | | 2732 | |
| 2727 | const c = try Int.initSet(testing.allocator, 11); | 2733 | const c = try Int.initSet(testing.allocator, 11); |
| 2728 | defer c.deinit(); | 2734 | defer c.deinit(); |
| 2729 | testing.expect(a.cmp(c) == 0); | 2735 | testing.expect(a.cmp(c) == .eq); |
| 2730 | | 2736 | |
| 2731 | const d = try Int.initSet(testing.allocator, 14); | 2737 | const d = try Int.initSet(testing.allocator, 14); |
| 2732 | defer d.deinit(); | 2738 | defer d.deinit(); |
| 2733 | testing.expect(a.cmp(d) <= 0); | 2739 | testing.expect(a.cmp(d) != .gt); |
| 2734 | } | 2740 | } |