authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-24 15:44:45-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-24 16:31:22-04:00
log4241cd666dbf5117a6c32357c091ca3bc7a0fcd0
tree8c9fcb5ff796a2d05c63e2d5b890b3092c5af614
parent877036e7ef37432579233347b5b3cfce66040f83
signaturelock-open Commit is signed but in an unrecognized format.

fix more bigint code paths and add tests


2 files changed, 14 insertions(+), 21 deletions(-)

src/bigint.cpp+10-21
......@@ -50,7 +50,7 @@ size_t bigint_bits_needed(const BigInt *op) {
5050 size_t full_bits = op->digit_count * 64;
5151 size_t leading_zero_count = bigint_clz(op, full_bits);
5252 size_t bits_needed = full_bits - leading_zero_count;
53 return bits_needed;
53 return bits_needed + op->is_negative;
5454}
5555
5656static 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) {
11881188 return bigint_init_bigint(dest, op1);
11891189 }
11901190 if (op1->is_negative || op2->is_negative) {
1191 // TODO this code path is untested
11921191 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
11931192
11941193 BigInt twos_comp_op1 = {0};
......@@ -1211,13 +1210,9 @@ void bigint_or(BigInt *dest, const BigInt *op1, const BigInt *op2) {
12111210 bigint_normalize(dest);
12121211 return;
12131212 }
1214 // TODO this code path is untested
1215 uint64_t first_digit = dest->data.digit;
12161213 dest->digit_count = max(op1->digit_count, op2->digit_count);
12171214 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
1218 dest->data.digits[0] = first_digit;
1219 size_t i = 1;
1220 for (; i < dest->digit_count; i += 1) {
1215 for (size_t i = 0; i < dest->digit_count; i += 1) {
12211216 uint64_t digit = 0;
12221217 if (i < op1->digit_count) {
12231218 digit |= op1_digits[i];
......@@ -1236,7 +1231,6 @@ void bigint_and(BigInt *dest, const BigInt *op1, const BigInt *op2) {
12361231 return bigint_init_unsigned(dest, 0);
12371232 }
12381233 if (op1->is_negative || op2->is_negative) {
1239 // TODO this code path is untested
12401234 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
12411235
12421236 BigInt twos_comp_op1 = {0};
......@@ -1282,7 +1276,6 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
12821276 return bigint_init_bigint(dest, op1);
12831277 }
12841278 if (op1->is_negative || op2->is_negative) {
1285 // TODO this code path is untested
12861279 size_t big_bit_count = max(bigint_bits_needed(op1), bigint_bits_needed(op2));
12871280
12881281 BigInt twos_comp_op1 = {0};
......@@ -1301,27 +1294,25 @@ void bigint_xor(BigInt *dest, const BigInt *op1, const BigInt *op2) {
13011294 const uint64_t *op2_digits = bigint_ptr(op2);
13021295
13031296 assert(op1->digit_count > 0 && op2->digit_count > 0);
1304 uint64_t first_digit = op1_digits[0] ^ op2_digits[0];
13051297 if (op1->digit_count == 1 && op2->digit_count == 1) {
13061298 dest->digit_count = 1;
1307 dest->data.digit = first_digit;
1299 dest->data.digit = op1_digits[0] ^ op2_digits[0];
13081300 bigint_normalize(dest);
13091301 return;
13101302 }
1311 // TODO this code path is untested
13121303 dest->digit_count = max(op1->digit_count, op2->digit_count);
13131304 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
1314 dest->data.digits[0] = first_digit;
1315 size_t i = 1;
1305 size_t i = 0;
13161306 for (; i < op1->digit_count && i < op2->digit_count; i += 1) {
13171307 dest->data.digits[i] = op1_digits[i] ^ op2_digits[i];
13181308 }
13191309 for (; i < dest->digit_count; i += 1) {
13201310 if (i < op1->digit_count) {
13211311 dest->data.digits[i] = op1_digits[i];
1322 }
1323 if (i < op2->digit_count) {
1312 } else if (i < op2->digit_count) {
13241313 dest->data.digits[i] = op2_digits[i];
1314 } else {
1315 zig_unreachable();
13251316 }
13261317 }
13271318 bigint_normalize(dest);
......@@ -1485,8 +1476,7 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed
14851476 bigint_normalize(dest);
14861477 return;
14871478 }
1488 // TODO this code path is untested
1489 dest->digit_count = bit_count / 64;
1479 dest->digit_count = (bit_count + 63) / 64;
14901480 assert(dest->digit_count >= op->digit_count);
14911481 dest->data.digits = allocate_nonzero<uint64_t>(dest->digit_count);
14921482 size_t i = 0;
......@@ -1496,9 +1486,9 @@ void bigint_not(BigInt *dest, const BigInt *op, size_t bit_count, bool is_signed
14961486 for (; i < dest->digit_count; i += 1) {
14971487 dest->data.digits[i] = 0xffffffffffffffffULL;
14981488 }
1499 size_t digit_index = dest->digit_count - (bit_count / 64) - 1;
1489 size_t digit_index = dest->digit_count - 1;
15001490 size_t digit_bit_index = bit_count % 64;
1501 if (digit_index < dest->digit_count) {
1491 if (digit_bit_index != 0) {
15021492 uint64_t mask = (1ULL << digit_bit_index) - 1;
15031493 dest->data.digits[digit_index] &= mask;
15041494 }
......@@ -1555,7 +1545,6 @@ void bigint_append_buf(Buf *buf, const BigInt *op, uint64_t base) {
15551545 buf_appendf(buf, "%" ZIG_PRI_u64, op->data.digit);
15561546 return;
15571547 }
1558 // TODO this code path is untested
15591548 size_t first_digit_index = buf_len(buf);
15601549
15611550 BigInt digit_bi = {0};
test/cases/eval.zig+4
......@@ -746,7 +746,11 @@ test "comptime bitwise operators" {
746746 assert(3 | -1 == -1);
747747 assert(-3 | -1 == -1);
748748 assert(3 ^ -1 == -4);
749 assert(-3 ^ -1 == 2);
749750 assert(~i8(-1) == 0);
750751 assert(~i128(-1) == 0);
752 assert(18446744073709551615 & 18446744073709551611 == 18446744073709551611);
753 assert(-18446744073709551615 & -18446744073709551611 == -18446744073709551615);
754 assert(~u128(0) == 0xffffffffffffffffffffffffffffffff);
751755 }
752756}