authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 18:54:30-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-07-19 18:54:30-04:00
log046df9b7d001120a0142ea29c86cfb3b9ae4eadf
tree219a4b90de182927ea2d687c2066015dce37d66d
parent6fab6c3e4696d11c2040ed2ea381ada01e74c6b9
parent3e667fd2925274c674bddfd2d3f67f6edd1bf72b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #12131 from hnakamur/fix_big_int_Managed_mul_sqr_capacity_too_large

Fix std.math.big.int.Managed capacity after mul and sqr

2 files changed, 42 insertions(+), 10 deletions(-)

lib/std/math/big/int.zig+10-10
...@@ -2719,7 +2719,7 @@ pub const Managed = struct {...@@ -2719,7 +2719,7 @@ pub const Managed = struct {
2719 ///2719 ///
2720 /// Returns an error if memory could not be allocated.2720 /// Returns an error if memory could not be allocated.
2721 pub fn sub(r: *Managed, a: *const Managed, b: *const Managed) !void {2721 pub fn sub(r: *Managed, a: *const Managed, b: *const Managed) !void {
2722 try r.ensureCapacity(math.max(a.limbs.len, b.limbs.len) + 1);2722 try r.ensureCapacity(math.max(a.len(), b.len()) + 1);
2723 var m = r.toMutable();2723 var m = r.toMutable();
2724 m.sub(a.toConst(), b.toConst());2724 m.sub(a.toConst(), b.toConst());
2725 r.setMetadata(m.positive, m.len);2725 r.setMetadata(m.positive, m.len);
...@@ -2780,7 +2780,7 @@ pub const Managed = struct {...@@ -2780,7 +2780,7 @@ pub const Managed = struct {
2780 if (alias_count == 0) {2780 if (alias_count == 0) {
2781 m.mulNoAlias(a.toConst(), b.toConst(), rma.allocator);2781 m.mulNoAlias(a.toConst(), b.toConst(), rma.allocator);
2782 } else {2782 } else {
2783 const limb_count = calcMulLimbsBufferLen(a.limbs.len, b.limbs.len, alias_count);2783 const limb_count = calcMulLimbsBufferLen(a.len(), b.len(), alias_count);
2784 const limbs_buffer = try rma.allocator.alloc(Limb, limb_count);2784 const limbs_buffer = try rma.allocator.alloc(Limb, limb_count);
2785 defer rma.allocator.free(limbs_buffer);2785 defer rma.allocator.free(limbs_buffer);
2786 m.mul(a.toConst(), b.toConst(), limbs_buffer, rma.allocator);2786 m.mul(a.toConst(), b.toConst(), limbs_buffer, rma.allocator);
...@@ -2813,7 +2813,7 @@ pub const Managed = struct {...@@ -2813,7 +2813,7 @@ pub const Managed = struct {
2813 if (alias_count == 0) {2813 if (alias_count == 0) {
2814 m.mulWrapNoAlias(a.toConst(), b.toConst(), signedness, bit_count, rma.allocator);2814 m.mulWrapNoAlias(a.toConst(), b.toConst(), signedness, bit_count, rma.allocator);
2815 } else {2815 } else {
2816 const limb_count = calcMulWrapLimbsBufferLen(bit_count, a.limbs.len, b.limbs.len, alias_count);2816 const limb_count = calcMulWrapLimbsBufferLen(bit_count, a.len(), b.len(), alias_count);
2817 const limbs_buffer = try rma.allocator.alloc(Limb, limb_count);2817 const limbs_buffer = try rma.allocator.alloc(Limb, limb_count);
2818 defer rma.allocator.free(limbs_buffer);2818 defer rma.allocator.free(limbs_buffer);
2819 m.mulWrap(a.toConst(), b.toConst(), signedness, bit_count, limbs_buffer, rma.allocator);2819 m.mulWrap(a.toConst(), b.toConst(), signedness, bit_count, limbs_buffer, rma.allocator);
...@@ -2843,11 +2843,11 @@ pub const Managed = struct {...@@ -2843,11 +2843,11 @@ pub const Managed = struct {
2843 ///2843 ///
2844 /// Returns an error if memory could not be allocated.2844 /// Returns an error if memory could not be allocated.
2845 pub fn divFloor(q: *Managed, r: *Managed, a: *const Managed, b: *const Managed) !void {2845 pub fn divFloor(q: *Managed, r: *Managed, a: *const Managed, b: *const Managed) !void {
2846 try q.ensureCapacity(a.limbs.len);2846 try q.ensureCapacity(a.len());
2847 try r.ensureCapacity(b.limbs.len);2847 try r.ensureCapacity(b.len());
2848 var mq = q.toMutable();2848 var mq = q.toMutable();
2849 var mr = r.toMutable();2849 var mr = r.toMutable();
2850 const limbs_buffer = try q.allocator.alloc(Limb, calcDivLimbsBufferLen(a.limbs.len, b.limbs.len));2850 const limbs_buffer = try q.allocator.alloc(Limb, calcDivLimbsBufferLen(a.len(), b.len()));
2851 defer q.allocator.free(limbs_buffer);2851 defer q.allocator.free(limbs_buffer);
2852 mq.divFloor(&mr, a.toConst(), b.toConst(), limbs_buffer);2852 mq.divFloor(&mr, a.toConst(), b.toConst(), limbs_buffer);
2853 q.setMetadata(mq.positive, mq.len);2853 q.setMetadata(mq.positive, mq.len);
...@@ -2860,11 +2860,11 @@ pub const Managed = struct {...@@ -2860,11 +2860,11 @@ pub const Managed = struct {
2860 ///2860 ///
2861 /// Returns an error if memory could not be allocated.2861 /// Returns an error if memory could not be allocated.
2862 pub fn divTrunc(q: *Managed, r: *Managed, a: *const Managed, b: *const Managed) !void {2862 pub fn divTrunc(q: *Managed, r: *Managed, a: *const Managed, b: *const Managed) !void {
2863 try q.ensureCapacity(a.limbs.len);2863 try q.ensureCapacity(a.len());
2864 try r.ensureCapacity(b.limbs.len);2864 try r.ensureCapacity(b.len());
2865 var mq = q.toMutable();2865 var mq = q.toMutable();
2866 var mr = r.toMutable();2866 var mr = r.toMutable();
2867 const limbs_buffer = try q.allocator.alloc(Limb, calcDivLimbsBufferLen(a.limbs.len, b.limbs.len));2867 const limbs_buffer = try q.allocator.alloc(Limb, calcDivLimbsBufferLen(a.len(), b.len()));
2868 defer q.allocator.free(limbs_buffer);2868 defer q.allocator.free(limbs_buffer);
2869 mq.divTrunc(&mr, a.toConst(), b.toConst(), limbs_buffer);2869 mq.divTrunc(&mr, a.toConst(), b.toConst(), limbs_buffer);
2870 q.setMetadata(mq.positive, mq.len);2870 q.setMetadata(mq.positive, mq.len);
...@@ -2960,7 +2960,7 @@ pub const Managed = struct {...@@ -2960,7 +2960,7 @@ pub const Managed = struct {
29602960
2961 /// r = a * a2961 /// r = a * a
2962 pub fn sqr(rma: *Managed, a: *const Managed) !void {2962 pub fn sqr(rma: *Managed, a: *const Managed) !void {
2963 const needed_limbs = 2 * a.limbs.len + 1;2963 const needed_limbs = 2 * a.len() + 1;
29642964
2965 if (rma.limbs.ptr == a.limbs.ptr) {2965 if (rma.limbs.ptr == a.limbs.ptr) {
2966 var m = try Managed.initCapacity(rma.allocator, needed_limbs);2966 var m = try Managed.initCapacity(rma.allocator, needed_limbs);
lib/std/math/big/int_test.zig+32
...@@ -2883,3 +2883,35 @@ test "big int byte swap" {...@@ -2883,3 +2883,35 @@ test "big int byte swap" {
2883 try byteSwapTest(i32, 0x123456f8, @bitCast(i32, @as(u32, 0xf8563412)));2883 try byteSwapTest(i32, 0x123456f8, @bitCast(i32, @as(u32, 0xf8563412)));
2884 try byteSwapTest(i48, 0x123456789abc, @bitCast(i48, @as(u48, 0xbc9a78563412)));2884 try byteSwapTest(i48, 0x123456789abc, @bitCast(i48, @as(u48, 0xbc9a78563412)));
2885}2885}
2886
2887test "big.int mul multi-multi alias r with a and b" {
2888 var a = try Managed.initSet(testing.allocator, 2 * maxInt(Limb));
2889 defer a.deinit();
2890
2891 try a.mul(&a, &a);
2892
2893 var want = try Managed.initSet(testing.allocator, 4 * maxInt(Limb) * maxInt(Limb));
2894 defer want.deinit();
2895
2896 try testing.expect(a.eq(want));
2897
2898 if (@typeInfo(Limb).Int.bits == 64) {
2899 try testing.expectEqual(@as(usize, 5), a.limbs.len);
2900 }
2901}
2902
2903test "big.int sqr multi alias r with a" {
2904 var a = try Managed.initSet(testing.allocator, 2 * maxInt(Limb));
2905 defer a.deinit();
2906
2907 try a.sqr(&a);
2908
2909 var want = try Managed.initSet(testing.allocator, 4 * maxInt(Limb) * maxInt(Limb));
2910 defer want.deinit();
2911
2912 try testing.expect(a.eq(want));
2913
2914 if (@typeInfo(Limb).Int.bits == 64) {
2915 try testing.expectEqual(@as(usize, 5), a.limbs.len);
2916 }
2917}