| ... | @@ -1669,7 +1669,7 @@ pub const Value = extern union { | ... | @@ -1669,7 +1669,7 @@ pub const Value = extern union { |
| 1669 | const rhs_bigint = rhs.toBigInt(&rhs_space); | 1669 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1670 | const limbs = try arena.alloc( | 1670 | const limbs = try arena.alloc( |
| 1671 | std.math.big.Limb, | 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 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 1674 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1675 | result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 1675 | result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | @@ -1701,7 +1701,7 @@ pub const Value = extern union { | ... | @@ -1701,7 +1701,7 @@ pub const Value = extern union { |
| 1701 | const rhs_bigint = rhs.toBigInt(&rhs_space); | 1701 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1702 | const limbs = try arena.alloc( | 1702 | const limbs = try arena.alloc( |
| 1703 | std.math.big.Limb, | 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 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 1706 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1707 | result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 1707 | result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | @@ -1736,7 +1736,7 @@ pub const Value = extern union { | ... | @@ -1736,7 +1736,7 @@ pub const Value = extern union { |
| 1736 | const rhs_bigint = rhs.toBigInt(&rhs_space); | 1736 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1737 | const limbs = try arena.alloc( | 1737 | const limbs = try arena.alloc( |
| 1738 | std.math.big.Limb, | 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 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 1741 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1742 | result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 1742 | result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | @@ -1768,7 +1768,7 @@ pub const Value = extern union { | ... | @@ -1768,7 +1768,7 @@ pub const Value = extern union { |
| 1768 | const rhs_bigint = rhs.toBigInt(&rhs_space); | 1768 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 1769 | const limbs = try arena.alloc( | 1769 | const limbs = try arena.alloc( |
| 1770 | std.math.big.Limb, | 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 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 1773 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 1774 | result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits); | 1774 | result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits); |
| ... | @@ -1794,19 +1794,31 @@ pub const Value = extern union { | ... | @@ -1794,19 +1794,31 @@ pub const Value = extern union { |
| 1794 | if (ty.isAnyFloat()) { | 1794 | if (ty.isAnyFloat()) { |
| 1795 | return floatMul(lhs, rhs, ty, arena); | 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); | 1798 | const info = ty.intInfo(target); |
| 1800 | if (compare(result, .gt, max, ty)) { | | |
| 1801 | @panic("TODO comptime wrapping integer multiplication"); | | |
| 1802 | } | | |
| 1803 | | 1799 | |
| 1804 | const min = try ty.minInt(arena, target); | 1800 | var lhs_space: Value.BigIntSpace = undefined; |
| 1805 | if (compare(result, .lt, min, ty)) { | 1801 | var rhs_space: Value.BigIntSpace = undefined; |
| 1806 | @panic("TODO comptime wrapping integer multiplication"); | 1802 | const lhs_bigint = lhs.toBigInt(&lhs_space); |
| 1807 | } | 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 | /// Supports integers only; asserts neither operand is undefined. | 1824 | /// Supports integers only; asserts neither operand is undefined. |
| ... | @@ -1820,19 +1832,35 @@ pub const Value = extern union { | ... | @@ -1820,19 +1832,35 @@ pub const Value = extern union { |
| 1820 | assert(!lhs.isUndef()); | 1832 | assert(!lhs.isUndef()); |
| 1821 | assert(!rhs.isUndef()); | 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); | 1837 | var lhs_space: Value.BigIntSpace = undefined; |
| 1826 | if (compare(result, .gt, max, ty)) { | 1838 | var rhs_space: Value.BigIntSpace = undefined; |
| 1827 | return max; | 1839 | const lhs_bigint = lhs.toBigInt(&lhs_space); |
| 1828 | } | 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); | 1859 | if (result_bigint.positive) { |
| 1831 | if (compare(result, .lt, min, ty)) { | 1860 | return Value.Tag.int_big_positive.create(arena, result_limbs); |
| 1832 | return min; | 1861 | } else { |
| | 1862 | return Value.Tag.int_big_negative.create(arena, result_limbs); |
| 1833 | } | 1863 | } |
| 1834 | | | |
| 1835 | return result; | | |
| 1836 | } | 1864 | } |
| 1837 | | 1865 | |
| 1838 | /// Supports both floats and ints; handles undefined. | 1866 | /// Supports both floats and ints; handles undefined. |
| ... | @@ -2144,7 +2172,7 @@ pub const Value = extern union { | ... | @@ -2144,7 +2172,7 @@ pub const Value = extern union { |
| 2144 | const rhs_bigint = rhs.toBigInt(&rhs_space); | 2172 | const rhs_bigint = rhs.toBigInt(&rhs_space); |
| 2145 | const limbs = try allocator.alloc( | 2173 | const limbs = try allocator.alloc( |
| 2146 | std.math.big.Limb, | 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 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; | 2177 | var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined }; |
| 2150 | var limbs_buffer = try allocator.alloc( | 2178 | var limbs_buffer = try allocator.alloc( |