| author | |
| committer | |
| log | e56ba4cee1040eb0ca4d94e7e4dbfe88a12c171a |
| tree | 10cb092230b65cf8bbf13c7873b937fea361cd8d |
| parent | b15e2054384ba683499138fcad0a9503f3aa9e0b |
2 files changed, 33 insertions(+), 8 deletions(-)
lib/std/math/big/int.zig+18-6| ... | ... | @@ -335,10 +335,10 @@ pub const Mutable = struct { |
| 335 | 335 | } |
| 336 | 336 | } else { |
| 337 | 337 | if (a.limbs.len >= b.limbs.len) { |
| 338 | lladd(r.limbs[0..], a.limbs[0..a.limbs.len], b.limbs[0..b.limbs.len]); | |
| 338 | lladd(r.limbs[0..], a.limbs, b.limbs); | |
| 339 | 339 | r.normalize(a.limbs.len + 1); |
| 340 | 340 | } else { |
| 341 | lladd(r.limbs[0..], b.limbs[0..b.limbs.len], a.limbs[0..a.limbs.len]); | |
| 341 | lladd(r.limbs[0..], b.limbs, a.limbs); | |
| 342 | 342 | r.normalize(b.limbs.len + 1); |
| 343 | 343 | } |
| 344 | 344 | |
| ... | ... | @@ -1685,12 +1685,14 @@ pub const Managed = struct { |
| 1685 | 1685 | |
| 1686 | 1686 | /// r = a + scalar |
| 1687 | 1687 | /// |
| 1688 | /// r and a may be aliases. | |
| 1688 | /// r and a may be aliases. If r aliases a, then caller must call | |
| 1689 | /// `r.ensureAddScalarCapacity` prior to calling `add`. | |
| 1689 | 1690 | /// scalar is a primitive integer type. |
| 1690 | 1691 | /// |
| 1691 | 1692 | /// Returns an error if memory could not be allocated. |
| 1692 | 1693 | pub fn addScalar(r: *Managed, a: Const, scalar: anytype) Allocator.Error!void { |
| 1693 | try r.ensureCapacity(math.max(a.limbs.len, calcLimbLen(scalar)) + 1); | |
| 1694 | assert((r.limbs.ptr != a.limbs.ptr) or r.limbs.len >= math.max(a.limbs.len, calcLimbLen(scalar)) + 1); | |
| 1695 | try r.ensureAddScalarCapacity(a, scalar); | |
| 1694 | 1696 | var m = r.toMutable(); |
| 1695 | 1697 | m.addScalar(a, scalar); |
| 1696 | 1698 | r.setMetadata(m.positive, m.len); |
| ... | ... | @@ -1698,11 +1700,13 @@ pub const Managed = struct { |
| 1698 | 1700 | |
| 1699 | 1701 | /// r = a + b |
| 1700 | 1702 | /// |
| 1701 | /// r, a and b may be aliases. | |
| 1703 | /// r, a and b may be aliases. If r aliases a or b, then caller must call | |
| 1704 | /// `r.ensureAddCapacity` prior to calling `add`. | |
| 1702 | 1705 | /// |
| 1703 | 1706 | /// Returns an error if memory could not be allocated. |
| 1704 | 1707 | pub fn add(r: *Managed, a: Const, b: Const) Allocator.Error!void { |
| 1705 | try r.ensureCapacity(math.max(a.limbs.len, b.limbs.len) + 1); | |
| 1708 | assert((r.limbs.ptr != a.limbs.ptr and r.limbs.ptr != b.limbs.ptr) or r.limbs.len >= math.max(a.limbs.len, b.limbs.len) + 1); | |
| 1709 | try r.ensureAddCapacity(a, b); | |
| 1706 | 1710 | var m = r.toMutable(); |
| 1707 | 1711 | m.add(a, b); |
| 1708 | 1712 | r.setMetadata(m.positive, m.len); |
| ... | ... | @@ -1748,6 +1752,14 @@ pub const Managed = struct { |
| 1748 | 1752 | rma.setMetadata(m.positive, m.len); |
| 1749 | 1753 | } |
| 1750 | 1754 | |
| 1755 | pub fn ensureAddScalarCapacity(r: *Managed, a: Const, scalar: anytype) !void { | |
| 1756 | try r.ensureCapacity(math.max(a.limbs.len, calcLimbLen(scalar)) + 1); | |
| 1757 | } | |
| 1758 | ||
| 1759 | pub fn ensureAddCapacity(r: *Managed, a: Const, b: Const) !void { | |
| 1760 | try r.ensureCapacity(math.max(a.limbs.len, b.limbs.len) + 1); | |
| 1761 | } | |
| 1762 | ||
| 1751 | 1763 | pub fn ensureMulCapacity(rma: *Managed, a: Const, b: Const) !void { |
| 1752 | 1764 | try rma.ensureCapacity(a.limbs.len + b.limbs.len + 1); |
| 1753 | 1765 | } |
lib/std/math/big/int_test.zig+15-2| ... | ... | @@ -538,6 +538,17 @@ test "big.int add sign" { |
| 538 | 538 | try testing.expect((try a.to(i32)) == -3); |
| 539 | 539 | } |
| 540 | 540 | |
| 541 | test "big.int add scalar" { | |
| 542 | var a = try Managed.initSet(testing.allocator, 50); | |
| 543 | defer a.deinit(); | |
| 544 | ||
| 545 | var b = try Managed.init(testing.allocator); | |
| 546 | defer b.deinit(); | |
| 547 | try b.addScalar(a.toConst(), 5); | |
| 548 | ||
| 549 | try testing.expect((try b.to(u32)) == 55); | |
| 550 | } | |
| 551 | ||
| 541 | 552 | test "big.int sub single-single" { |
| 542 | 553 | var a = try Managed.initSet(testing.allocator, 50); |
| 543 | 554 | defer a.deinit(); |
| ... | ... | @@ -1563,7 +1574,7 @@ test "big.int pow" { |
| 1563 | 1574 | } |
| 1564 | 1575 | } |
| 1565 | 1576 | |
| 1566 | test "bigint regression test for 1 limb overflow with alias" { | |
| 1577 | test "big.int regression test for 1 limb overflow with alias" { | |
| 1567 | 1578 | // Note these happen to be two consecutive Fibonacci sequence numbers, the |
| 1568 | 1579 | // first two whose sum exceeds 2**64. |
| 1569 | 1580 | var a = try Managed.initSet(testing.allocator, 7540113804746346429); |
| ... | ... | @@ -1571,12 +1582,13 @@ test "bigint regression test for 1 limb overflow with alias" { |
| 1571 | 1582 | var b = try Managed.initSet(testing.allocator, 12200160415121876738); |
| 1572 | 1583 | defer b.deinit(); |
| 1573 | 1584 | |
| 1585 | try a.ensureAddCapacity(a.toConst(), b.toConst()); | |
| 1574 | 1586 | try a.add(a.toConst(), b.toConst()); |
| 1575 | 1587 | |
| 1576 | 1588 | try testing.expect(a.toConst().orderAgainstScalar(19740274219868223167) == .eq); |
| 1577 | 1589 | } |
| 1578 | 1590 | |
| 1579 | test "bigint regression test for something else with alias" { | |
| 1591 | test "big.int regression test for realloc with alias" { | |
| 1580 | 1592 | // Note these happen to be two consecutive Fibonacci sequence numbers, the |
| 1581 | 1593 | // second of which is the first such number to exceed 2**192. |
| 1582 | 1594 | var a = try Managed.initSet(testing.allocator, 5611500259351924431073312796924978741056961814867751431689); |
| ... | ... | @@ -1584,6 +1596,7 @@ test "bigint regression test for something else with alias" { |
| 1584 | 1596 | var b = try Managed.initSet(testing.allocator, 9079598147510263717870894449029933369491131786514446266146); |
| 1585 | 1597 | defer b.deinit(); |
| 1586 | 1598 | |
| 1599 | try a.ensureAddCapacity(a.toConst(), b.toConst()); | |
| 1587 | 1600 | try a.add(a.toConst(), b.toConst()); |
| 1588 | 1601 | |
| 1589 | 1602 | try testing.expect(a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835) == .eq); |