| ... | @@ -50,7 +50,7 @@ size_t bigint_bits_needed(const BigInt *op) { | ... | @@ -50,7 +50,7 @@ size_t bigint_bits_needed(const BigInt *op) { |
| 50 | size_t full_bits = op->digit_count * 64; | 50 | size_t full_bits = op->digit_count * 64; |
| 51 | size_t leading_zero_count = bigint_clz(op, full_bits); | 51 | size_t leading_zero_count = bigint_clz(op, full_bits); |
| 52 | size_t bits_needed = full_bits - leading_zero_count; | 52 | size_t bits_needed = full_bits - leading_zero_count; |
| 53 | return bits_needed; | 53 | return bits_needed + op->is_negative; |
| 54 | } | 54 | } |
| 55 | | 55 | |
| 56 | static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) { | 56 | static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) { |
| ... | @@ -1188,7 +1188,6 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -1188,7 +1188,6 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1188 | return bigint_init_bigint(dest, op1); | 1188 | return bigint_init_bigint(dest, op1); |
| 1189 | } | 1189 | } |
| 1190 | if (op1->is_negative || op2->is_negative) { | 1190 | if (op1->is_negative || op2->is_negative) { |
| 1191 | // TODO this code path is untested | | |
| 1192 | size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2)); | 1191 | size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2)); |
| 1193 | | 1192 | |
| 1194 | BigInt twos_comp_op1 = {0}; | 1193 | BigInt twos_comp_op1 = {0}; |
| ... | @@ -1211,13 +1210,9 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -1211,13 +1210,9 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1211 | bigint_normalize(dest); | 1210 | bigint_normalize(dest); |
| 1212 | return; | 1211 | return; |
| 1213 | } | 1212 | } |
| 1214 | // TODO this code path is untested | | |
| 1215 | uint64_t first_digit = dest->data.digit; | | |
| 1216 | dest->digit_count = max(op1->digit_count, op2->digit_count); | 1213 | dest->digit_count = max(op1->digit_count, op2->digit_count); |
| 1217 | dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count); | 1214 | dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count); |
| 1218 | dest->data.digits[0] = first_digit; | 1215 | for (size_t i = 0; i < dest->digit_count; i += 1) { |
| 1219 | size_t i = 1; | | |
| 1220 | for (; i < dest->digit_count; i += 1) { | | |
| 1221 | uint64_t digit = 0; | 1216 | uint64_t digit = 0; |
| 1222 | if (i < op1->digit_count) { | 1217 | if (i < op1->digit_count) { |
| 1223 | digit |= op1_digits[i]; | 1218 | digit |= op1_digits[i]; |
| ... | @@ -1236,7 +1231,6 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -1236,7 +1231,6 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1236 | return bigint_init_unsigned(dest, 0); | 1231 | return bigint_init_unsigned(dest, 0); |
| 1237 | } | 1232 | } |
| 1238 | if (op1->is_negative || op2->is_negative) { | 1233 | if (op1->is_negative || op2->is_negative) { |
| 1239 | // TODO this code path is untested | | |
| 1240 | size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2)); | 1234 | size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2)); |
| 1241 | | 1235 | |
| 1242 | BigInt twos_comp_op1 = {0}; | 1236 | BigInt twos_comp_op1 = {0}; |
| ... | @@ -1282,7 +1276,6 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -1282,7 +1276,6 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1282 | return bigint_init_bigint(dest, op1); | 1276 | return bigint_init_bigint(dest, op1); |
| 1283 | } | 1277 | } |
| 1284 | if (op1->is_negative || op2->is_negative) { | 1278 | if (op1->is_negative || op2->is_negative) { |
| 1285 | // TODO this code path is untested | | |
| 1286 | size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2)); | 1279 | size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2)); |
| 1287 | | 1280 | |
| 1288 | BigInt twos_comp_op1 = {0}; | 1281 | BigInt twos_comp_op1 = {0}; |
| ... | @@ -1301,27 +1294,25 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) { | ... | @@ -1301,27 +1294,25 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 1301 | const uint64_t *op2_digits = bigint_ptr(op2); | 1294 | const uint64_t *op2_digits = bigint_ptr(op2); |
| 1302 | | 1295 | |
| 1303 | assert(op1->digit_count > 0 && op2->digit_count > 0); | 1296 | assert(op1->digit_count > 0 && op2->digit_count > 0); |
| 1304 | uint64_t first_digit = op1_digits[0] ^ op2_digits[0]; | | |
| 1305 | if (op1->digit_count == 1 && op2->digit_count == 1) { | 1297 | if (op1->digit_count == 1 && op2->digit_count == 1) { |
| 1306 | dest->digit_count = 1; | 1298 | dest->digit_count = 1; |
| 1307 | dest->data.digit = first_digit; | 1299 | dest->data.digit = op1_digits[0] ^ op2_digits[0]; |
| 1308 | bigint_normalize(dest); | 1300 | bigint_normalize(dest); |
| 1309 | return; | 1301 | return; |
| 1310 | } | 1302 | } |
| 1311 | // TODO this code path is untested | | |
| 1312 | dest->digit_count = max(op1->digit_count, op2->digit_count); | 1303 | dest->digit_count = max(op1->digit_count, op2->digit_count); |
| 1313 | dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count); | 1304 | dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count); |
| 1314 | dest->data.digits[0] = first_digit; | 1305 | size_t i = 0; |
| 1315 | size_t i = 1; | | |
| 1316 | for (; i < op1->digit_count && i < op2->digit_count; i += 1) { | 1306 | for (; i < op1->digit_count && i < op2->digit_count; i += 1) { |
| 1317 | dest->data.digits[i] = op1_digits[i] ^ op2_digits[i]; | 1307 | dest->data.digits[i] = op1_digits[i] ^ op2_digits[i]; |
| 1318 | } | 1308 | } |
| 1319 | for (; i < dest->digit_count; i += 1) { | 1309 | for (; i < dest->digit_count; i += 1) { |
| 1320 | if (i < op1->digit_count) { | 1310 | if (i < op1->digit_count) { |
| 1321 | dest->data.digits[i] = op1_digits[i]; | 1311 | dest->data.digits[i] = op1_digits[i]; |
| 1322 | } | 1312 | } else if (i < op2->digit_count) { |
| 1323 | if (i < op2->digit_count) { | | |
| 1324 | dest->data.digits[i] = op2_digits[i]; | 1313 | dest->data.digits[i] = op2_digits[i]; |
| | 1314 | } else { |
| | 1315 | zig_unreachable(); |
| 1325 | } | 1316 | } |
| 1326 | } | 1317 | } |
| 1327 | bigint_normalize(dest); | 1318 | bigint_normalize(dest); |
| ... | @@ -1485,8 +1476,7 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed | ... | @@ -1485,8 +1476,7 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed |
| 1485 | bigint_normalize(dest); | 1476 | bigint_normalize(dest); |
| 1486 | return; | 1477 | return; |
| 1487 | } | 1478 | } |
| 1488 | // TODO this code path is untested | 1479 | dest->digit_count = (bit_count + 63) / 64; |
| 1489 | dest->digit_count = bit_count / 64; | | |
| 1490 | assert(dest->digit_count >= op->digit_count); | 1480 | assert(dest->digit_count >= op->digit_count); |
| 1491 | dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count); | 1481 | dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count); |
| 1492 | size_t i = 0; | 1482 | size_t i = 0; |
| ... | @@ -1496,9 +1486,9 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed | ... | @@ -1496,9 +1486,9 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed |
| 1496 | for (; i < dest->digit_count; i += 1) { | 1486 | for (; i < dest->digit_count; i += 1) { |
| 1497 | dest->data.digits[i] = 0xffffffffffffffffULL; | 1487 | dest->data.digits[i] = 0xffffffffffffffffULL; |
| 1498 | } | 1488 | } |
| 1499 | size_t digit_index = dest->digit_count - (bit_count / 64) - 1; | 1489 | size_t digit_index = dest->digit_count - 1; |
| 1500 | size_t digit_bit_index = bit_count % 64; | 1490 | size_t digit_bit_index = bit_count % 64; |
| 1501 | if (digit_index < dest->digit_count) { | 1491 | if (digit_bit_index != 0) { |
| 1502 | uint64_t mask = (1ULL << digit_bit_index) - 1; | 1492 | uint64_t mask = (1ULL << digit_bit_index) - 1; |
| 1503 | dest->data.digits[digit_index] &= mask; | 1493 | dest->data.digits[digit_index] &= mask; |
| 1504 | } | 1494 | } |
| ... | @@ -1555,7 +1545,6 @@ void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base) { | ... | @@ -1555,7 +1545,6 @@ void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base) { |
| 1555 | buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit); | 1545 | buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit); |
| 1556 | return; | 1546 | return; |
| 1557 | } | 1547 | } |
| 1558 | // TODO this code path is untested | | |
| 1559 | size_t first_digit_index = buf_len(buf); | 1548 | size_t first_digit_index = buf_len(buf); |
| 1560 | | 1549 | |
| 1561 | BigInt digit_bi = {0}; | 1550 | BigInt digit_bi = {0}; |