authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-04 00:22:03+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-10-04 11:25:29+02:00
log3dc47b8161f681baef2be776056fa9cc23a8811d
tree688aca01a6cdb4e7318bca81b20e449e8e8f0330
parenta62ce87f1f8874cf9c6bcf197afc638e8321f692

Apply new big int wrap/saturate to Value.zig


2 files changed, 54 insertions(+), 26 deletions(-)

lib/std/math/big/int.zig+1-1
......@@ -2738,7 +2738,7 @@ pub fn llcmp(a: []const Limb, b: []const Limb) i8 {
27382738/// The result is computed modulo `r.len`. When `r.len >= a.len + b.len`, no overflow occurs.
27392739fn llmulaccLong(comptime op: AccOp, r: []Limb, a: []const Limb, b: []const Limb) void {
27402740 @setRuntimeSafety(debug_safety);
2741 assert(r.len >= a.len + b.len);
2741 assert(r.len >= a.len);
27422742 assert(a.len >= b.len);
27432743
27442744 var i: usize = 0;
src/value.zig+53-25
......@@ -1669,7 +1669,7 @@ pub const Value = extern union {
16691669 const rhs_bigint = rhs.toBigInt(&rhs_space);
16701670 const limbs = try arena.alloc(
16711671 std.math.big.Limb,
1672 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
1672 std.math.big.int.calcTwosCompLimbCount(info.bits),
16731673 );
16741674 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
16751675 result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
......@@ -1701,7 +1701,7 @@ pub const Value = extern union {
17011701 const rhs_bigint = rhs.toBigInt(&rhs_space);
17021702 const limbs = try arena.alloc(
17031703 std.math.big.Limb,
1704 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
1704 std.math.big.int.calcTwosCompLimbCount(info.bits),
17051705 );
17061706 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
17071707 result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
......@@ -1736,7 +1736,7 @@ pub const Value = extern union {
17361736 const rhs_bigint = rhs.toBigInt(&rhs_space);
17371737 const limbs = try arena.alloc(
17381738 std.math.big.Limb,
1739 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
1739 std.math.big.int.calcTwosCompLimbCount(info.bits),
17401740 );
17411741 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
17421742 result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
......@@ -1768,7 +1768,7 @@ pub const Value = extern union {
17681768 const rhs_bigint = rhs.toBigInt(&rhs_space);
17691769 const limbs = try arena.alloc(
17701770 std.math.big.Limb,
1771 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
1771 std.math.big.int.calcTwosCompLimbCount(info.bits),
17721772 );
17731773 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
17741774 result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
......@@ -1794,19 +1794,31 @@ pub const Value = extern union {
17941794 if (ty.isAnyFloat()) {
17951795 return floatMul(lhs, rhs, ty, arena);
17961796 }
1797 const result = try intMul(lhs, rhs, arena);
17981797
1799 const max = try ty.maxInt(arena, target);
1800 if (compare(result, .gt, max, ty)) {
1801 @panic("TODO comptime wrapping integer multiplication");
1802 }
1798 const info = ty.intInfo(target);
18031799
1804 const min = try ty.minInt(arena, target);
1805 if (compare(result, .lt, min, ty)) {
1806 @panic("TODO comptime wrapping integer multiplication");
1807 }
1800 var lhs_space: Value.BigIntSpace = undefined;
1801 var rhs_space: Value.BigIntSpace = undefined;
1802 const lhs_bigint = lhs.toBigInt(&lhs_space);
1803 const rhs_bigint = rhs.toBigInt(&rhs_space);
1804 const limbs = try arena.alloc(
1805 std.math.big.Limb,
1806 std.math.big.int.calcTwosCompLimbCount(info.bits),
1807 );
1808 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
1809 var limbs_buffer = try arena.alloc(
1810 std.math.big.Limb,
1811 std.math.big.int.calcMulWrapLimbsBufferLen(info.bits, lhs_bigint.limbs.len, rhs_bigint.limbs.len, 1),
1812 );
1813 defer arena.free(limbs_buffer);
1814 result_bigint.mulWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits, limbs_buffer, arena);
1815 const result_limbs = result_bigint.limbs[0..result_bigint.len];
18081816
1809 return result;
1817 if (result_bigint.positive) {
1818 return Value.Tag.int_big_positive.create(arena, result_limbs);
1819 } else {
1820 return Value.Tag.int_big_negative.create(arena, result_limbs);
1821 }
18101822 }
18111823
18121824 /// Supports integers only; asserts neither operand is undefined.
......@@ -1820,19 +1832,35 @@ pub const Value = extern union {
18201832 assert(!lhs.isUndef());
18211833 assert(!rhs.isUndef());
18221834
1823 const result = try intMul(lhs, rhs, arena);
1835 const info = ty.intInfo(target);
18241836
1825 const max = try ty.maxInt(arena, target);
1826 if (compare(result, .gt, max, ty)) {
1827 return max;
1828 }
1837 var lhs_space: Value.BigIntSpace = undefined;
1838 var rhs_space: Value.BigIntSpace = undefined;
1839 const lhs_bigint = lhs.toBigInt(&lhs_space);
1840 const rhs_bigint = rhs.toBigInt(&rhs_space);
1841 const limbs = try arena.alloc(
1842 std.math.big.Limb,
1843 std.math.max(
1844 // For the saturate
1845 std.math.big.int.calcTwosCompLimbCount(info.bits),
1846 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
1847 ),
1848 );
1849 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
1850 var limbs_buffer = try arena.alloc(
1851 std.math.big.Limb,
1852 std.math.big.int.calcMulLimbsBufferLen(lhs_bigint.limbs.len, rhs_bigint.limbs.len, 1),
1853 );
1854 defer arena.free(limbs_buffer);
1855 result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);
1856 result_bigint.saturate(result_bigint.toConst(), info.signedness, info.bits);
1857 const result_limbs = result_bigint.limbs[0..result_bigint.len];
18291858
1830 const min = try ty.minInt(arena, target);
1831 if (compare(result, .lt, min, ty)) {
1832 return min;
1859 if (result_bigint.positive) {
1860 return Value.Tag.int_big_positive.create(arena, result_limbs);
1861 } else {
1862 return Value.Tag.int_big_negative.create(arena, result_limbs);
18331863 }
1834
1835 return result;
18361864 }
18371865
18381866 /// Supports both floats and ints; handles undefined.
......@@ -2144,7 +2172,7 @@ pub const Value = extern union {
21442172 const rhs_bigint = rhs.toBigInt(&rhs_space);
21452173 const limbs = try allocator.alloc(
21462174 std.math.big.Limb,
2147 lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1,
2175 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
21482176 );
21492177 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
21502178 var limbs_buffer = try allocator.alloc(