| 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,10 +335,10 @@ pub const Mutable = struct { |
| 335 | } | 335 | } |
| 336 | } else { | 336 | } else { |
| 337 | if (a.limbs.len >= b.limbs.len) { | 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 | r.normalize(a.limbs.len + 1); | 339 | r.normalize(a.limbs.len + 1); |
| 340 | } else { | 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 | r.normalize(b.limbs.len + 1); | 342 | r.normalize(b.limbs.len + 1); |
| 343 | } | 343 | } |
| 344 | 344 | ||
| ... | @@ -1685,12 +1685,14 @@ pub const Managed = struct { | ... | @@ -1685,12 +1685,14 @@ pub const Managed = struct { |
| 1685 | 1685 | ||
| 1686 | /// r = a + scalar | 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 | /// scalar is a primitive integer type. | 1690 | /// scalar is a primitive integer type. |
| 1690 | /// | 1691 | /// |
| 1691 | /// Returns an error if memory could not be allocated. | 1692 | /// Returns an error if memory could not be allocated. |
| 1692 | pub fn addScalar(r: *Managed, a: Const, scalar: anytype) Allocator.Error!void { | 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 | var m = r.toMutable(); | 1696 | var m = r.toMutable(); |
| 1695 | m.addScalar(a, scalar); | 1697 | m.addScalar(a, scalar); |
| 1696 | r.setMetadata(m.positive, m.len); | 1698 | r.setMetadata(m.positive, m.len); |
| ... | @@ -1698,11 +1700,13 @@ pub const Managed = struct { | ... | @@ -1698,11 +1700,13 @@ pub const Managed = struct { |
| 1698 | 1700 | ||
| 1699 | /// r = a + b | 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 | /// Returns an error if memory could not be allocated. | 1706 | /// Returns an error if memory could not be allocated. |
| 1704 | pub fn add(r: *Managed, a: Const, b: Const) Allocator.Error!void { | 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 | var m = r.toMutable(); | 1710 | var m = r.toMutable(); |
| 1707 | m.add(a, b); | 1711 | m.add(a, b); |
| 1708 | r.setMetadata(m.positive, m.len); | 1712 | r.setMetadata(m.positive, m.len); |
| ... | @@ -1748,6 +1752,14 @@ pub const Managed = struct { | ... | @@ -1748,6 +1752,14 @@ pub const Managed = struct { |
| 1748 | rma.setMetadata(m.positive, m.len); | 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 | pub fn ensureMulCapacity(rma: *Managed, a: Const, b: Const) !void { | 1763 | pub fn ensureMulCapacity(rma: *Managed, a: Const, b: Const) !void { |
| 1752 | try rma.ensureCapacity(a.limbs.len + b.limbs.len + 1); | 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,6 +538,17 @@ test "big.int add sign" { |
| 538 | try testing.expect((try a.to(i32)) == -3); | 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 | test "big.int sub single-single" { | 552 | test "big.int sub single-single" { |
| 542 | var a = try Managed.initSet(testing.allocator, 50); | 553 | var a = try Managed.initSet(testing.allocator, 50); |
| 543 | defer a.deinit(); | 554 | defer a.deinit(); |
| ... | @@ -1563,7 +1574,7 @@ test "big.int pow" { | ... | @@ -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 | // Note these happen to be two consecutive Fibonacci sequence numbers, the | 1578 | // Note these happen to be two consecutive Fibonacci sequence numbers, the |
| 1568 | // first two whose sum exceeds 2**64. | 1579 | // first two whose sum exceeds 2**64. |
| 1569 | var a = try Managed.initSet(testing.allocator, 7540113804746346429); | 1580 | var a = try Managed.initSet(testing.allocator, 7540113804746346429); |
| ... | @@ -1571,12 +1582,13 @@ test "bigint regression test for 1 limb overflow with alias" { | ... | @@ -1571,12 +1582,13 @@ test "bigint regression test for 1 limb overflow with alias" { |
| 1571 | var b = try Managed.initSet(testing.allocator, 12200160415121876738); | 1582 | var b = try Managed.initSet(testing.allocator, 12200160415121876738); |
| 1572 | defer b.deinit(); | 1583 | defer b.deinit(); |
| 1573 | 1584 | ||
| 1585 | try a.ensureAddCapacity(a.toConst(), b.toConst()); | ||
| 1574 | try a.add(a.toConst(), b.toConst()); | 1586 | try a.add(a.toConst(), b.toConst()); |
| 1575 | 1587 | ||
| 1576 | try testing.expect(a.toConst().orderAgainstScalar(19740274219868223167) == .eq); | 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 | // Note these happen to be two consecutive Fibonacci sequence numbers, the | 1592 | // Note these happen to be two consecutive Fibonacci sequence numbers, the |
| 1581 | // second of which is the first such number to exceed 2**192. | 1593 | // second of which is the first such number to exceed 2**192. |
| 1582 | var a = try Managed.initSet(testing.allocator, 5611500259351924431073312796924978741056961814867751431689); | 1594 | var a = try Managed.initSet(testing.allocator, 5611500259351924431073312796924978741056961814867751431689); |
| ... | @@ -1584,6 +1596,7 @@ test "bigint regression test for something else with alias" { | ... | @@ -1584,6 +1596,7 @@ test "bigint regression test for something else with alias" { |
| 1584 | var b = try Managed.initSet(testing.allocator, 9079598147510263717870894449029933369491131786514446266146); | 1596 | var b = try Managed.initSet(testing.allocator, 9079598147510263717870894449029933369491131786514446266146); |
| 1585 | defer b.deinit(); | 1597 | defer b.deinit(); |
| 1586 | 1598 | ||
| 1599 | try a.ensureAddCapacity(a.toConst(), b.toConst()); | ||
| 1587 | try a.add(a.toConst(), b.toConst()); | 1600 | try a.add(a.toConst(), b.toConst()); |
| 1588 | 1601 | ||
| 1589 | try testing.expect(a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835) == .eq); | 1602 | try testing.expect(a.toConst().orderAgainstScalar(14691098406862188148944207245954912110548093601382197697835) == .eq); |