| author | |
| committer | |
| log | ae442e2c2906f768098de307f3388ef0e8d47e5b |
| tree | 177ff5c8be5d31f88bcf0cb5142f43e6f31ce630 |
| parent | adee3ee9a2c679069a15bd5476860d45f05b356b |
| signature |
3 files changed, 44 insertions(+), 5 deletions(-)
lib/std/math/big/int.zig+15-4| ... | ... | @@ -76,9 +76,18 @@ pub fn calcSqrtLimbsBufferLen(a_bit_count: usize) usize { |
| 76 | 76 | return a_limb_count + 3 * u_s_rem_limb_count + calcDivLimbsBufferLen(a_limb_count, u_s_rem_limb_count); |
| 77 | 77 | } |
| 78 | 78 | |
| 79 | // Compute the number of limbs required to store a 2s-complement number of `bit_count` bits. | |
| 79 | /// Compute the number of limbs required to store a 2s-complement number of `bit_count` bits. | |
| 80 | pub fn calcNonZeroTwosCompLimbCount(bit_count: usize) usize { | |
| 81 | assert(bit_count != 0); | |
| 82 | return calcTwosCompLimbCount(bit_count); | |
| 83 | } | |
| 84 | ||
| 85 | /// Compute the number of limbs required to store a 2s-complement number of `bit_count` bits. | |
| 86 | /// | |
| 87 | /// Special cases `bit_count == 0` to return 1. Zero-bit integers can only store the value zero | |
| 88 | /// and this big integer implementation stores zero using one limb. | |
| 80 | 89 | pub fn calcTwosCompLimbCount(bit_count: usize) usize { |
| 81 | return std.math.divCeil(usize, bit_count, @bitSizeOf(Limb)) catch unreachable; | |
| 90 | return @max(std.math.divCeil(usize, bit_count, @bitSizeOf(Limb)) catch unreachable, 1); | |
| 82 | 91 | } |
| 83 | 92 | |
| 84 | 93 | /// a + b * c + *carry, sets carry to the overflow bits |
| ... | ... | @@ -188,8 +197,10 @@ pub const Mutable = struct { |
| 188 | 197 | if (self.limbs.ptr != other.limbs.ptr) { |
| 189 | 198 | @memcpy(self.limbs[0..other.limbs.len], other.limbs[0..other.limbs.len]); |
| 190 | 199 | } |
| 191 | self.positive = other.positive; | |
| 192 | self.len = other.limbs.len; | |
| 200 | // Normalize before setting `positive` so the `eqlZero` doesn't need to iterate | |
| 201 | // over the extra zero limbs. | |
| 202 | self.normalize(other.limbs.len); | |
| 203 | self.positive = other.positive or other.eqlZero(); | |
| 193 | 204 | } |
| 194 | 205 | |
| 195 | 206 | /// Efficiently swap an Mutable with another. This swaps the limb pointers and a full copy is not |
lib/std/math/big/int_test.zig+28| ... | ... | @@ -726,6 +726,34 @@ test "subWrap single-multi, signed, limb aligned" { |
| 726 | 726 | try testing.expect((try a.toInt(SignedDoubleLimb)) == maxInt(SignedDoubleLimb)); |
| 727 | 727 | } |
| 728 | 728 | |
| 729 | test "addWrap returns normalized result" { | |
| 730 | var x = try Managed.initSet(testing.allocator, 0); | |
| 731 | defer x.deinit(); | |
| 732 | var y = try Managed.initSet(testing.allocator, 0); | |
| 733 | defer y.deinit(); | |
| 734 | ||
| 735 | // make them both non normalized "-0" | |
| 736 | x.setMetadata(false, 1); | |
| 737 | y.setMetadata(false, 1); | |
| 738 | ||
| 739 | var r = try Managed.init(testing.allocator); | |
| 740 | defer r.deinit(); | |
| 741 | try testing.expect(!(try r.addWrap(&x, &y, .unsigned, 64))); | |
| 742 | try testing.expect(r.isPositive() and r.len() == 1 and r.limbs[0] == 0); | |
| 743 | } | |
| 744 | ||
| 745 | test "subWrap returns normalized result" { | |
| 746 | var x = try Managed.initSet(testing.allocator, 0); | |
| 747 | defer x.deinit(); | |
| 748 | var y = try Managed.initSet(testing.allocator, 0); | |
| 749 | defer y.deinit(); | |
| 750 | ||
| 751 | var r = try Managed.init(testing.allocator); | |
| 752 | defer r.deinit(); | |
| 753 | try testing.expect(!(try r.subWrap(&x, &y, .unsigned, 64))); | |
| 754 | try testing.expect(r.isPositive() and r.len() == 1 and r.limbs[0] == 0); | |
| 755 | } | |
| 756 | ||
| 729 | 757 | test "addSat single-single, unsigned" { |
| 730 | 758 | var a = try Managed.initSet(testing.allocator, maxInt(u17) - 5); |
| 731 | 759 | defer a.deinit(); |
src/Value.zig+1-1| ... | ... | @@ -2223,7 +2223,7 @@ pub fn shlSatScalar( |
| 2223 | 2223 | const shift: usize = @intCast(rhs.toUnsignedInt(zcu)); |
| 2224 | 2224 | const limbs = try arena.alloc( |
| 2225 | 2225 | std.math.big.Limb, |
| 2226 | std.math.big.int.calcTwosCompLimbCount(info.bits) + 1, | |
| 2226 | std.math.big.int.calcTwosCompLimbCount(info.bits), | |
| 2227 | 2227 | ); |
| 2228 | 2228 | var result_bigint = BigIntMutable{ |
| 2229 | 2229 | .limbs = limbs, |