| ... | ... | @@ -1669,7 +1669,7 @@ pub const Value = extern union { |
| 1669 | 1669 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1670 | 1670 | const limbs = try arena.alloc( |
| 1671 | 1671 | std.math.big.Limb, |
| 1672 | | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), |
| 1672 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 1673 | 1673 | ); |
| 1674 | 1674 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1675 | 1675 | result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | ... | @@ -1701,7 +1701,7 @@ pub const Value = extern union { |
| 1701 | 1701 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1702 | 1702 | const limbs = try arena.alloc( |
| 1703 | 1703 | std.math.big.Limb, |
| 1704 | | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), |
| 1704 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 1705 | 1705 | ); |
| 1706 | 1706 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1707 | 1707 | result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | ... | @@ -1736,7 +1736,7 @@ pub const Value = extern union { |
| 1736 | 1736 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1737 | 1737 | const limbs = try arena.alloc( |
| 1738 | 1738 | std.math.big.Limb, |
| 1739 | | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), |
| 1739 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 1740 | 1740 | ); |
| 1741 | 1741 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1742 | 1742 | result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | ... | @@ -1768,7 +1768,7 @@ pub const Value = extern union { |
| 1768 | 1768 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1769 | 1769 | const limbs = try arena.alloc( |
| 1770 | 1770 | std.math.big.Limb, |
| 1771 | | std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len), |
| 1771 | std.math.big.int.calcTwosCompLimbCount(info.bits), |
| 1772 | 1772 | ); |
| 1773 | 1773 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1774 | 1774 | result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | ... | @@ -1794,19 +1794,31 @@ pub const Value = extern union { |
| 1794 | 1794 | if (ty.isAnyFloat()) { |
| 1795 | 1795 | return floatMul(lhs, rhs, ty, arena); |
| 1796 | 1796 | } |
| 1797 | | const result = try intMul(lhs, rhs, arena); |
| 1798 | 1797 | |
| 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); |
| 1803 | 1799 | |
| 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]; |
| 1808 | 1816 | |
| 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 | } |
| 1810 | 1822 | } |
| 1811 | 1823 | |
| 1812 | 1824 | /// Supports integers only; asserts neither operand is undefined. |
| ... | ... | @@ -1820,19 +1832,35 @@ pub const Value = extern union { |
| 1820 | 1832 | assert(!lhs.isUndef()); |
| 1821 | 1833 | assert(!rhs.isUndef()); |
| 1822 | 1834 | |
| 1823 | | const result = try intMul(lhs, rhs, arena); |
| 1835 | const info = ty.intInfo(target); |
| 1824 | 1836 | |
| 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]; |
| 1829 | 1858 | |
| 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); |
| 1833 | 1863 | } |
| 1834 | | |
| 1835 | | return result; |
| 1836 | 1864 | } |
| 1837 | 1865 | |
| 1838 | 1866 | /// Supports both floats and ints; handles undefined. |
| ... | ... | @@ -2144,7 +2172,7 @@ pub const Value = extern union { |
| 2144 | 2172 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 2145 | 2173 | const limbs = try allocator.alloc( |
| 2146 | 2174 | std.math.big.Limb, |
| 2147 | | lhs_bigint.limbs.len + rhs_bigint.limbs.len + 1, |
| 2175 | lhs_bigint.limbs.len + rhs_bigint.limbs.len, |
| 2148 | 2176 | ); |
| 2149 | 2177 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 2150 | 2178 | var limbs_buffer = try allocator.alloc( |