| ... | ... | @@ -60,6 +60,9 @@ static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) |
| 60 | 60 | bigint_init_unsigned(dest, 0); |
| 61 | 61 | return; |
| 62 | 62 | } |
| 63 | |
| 64 | BigInt pos_op = {0}; |
| 65 | |
| 63 | 66 | if (op->is_negative) { |
| 64 | 67 | BigInt negated = {0}; |
| 65 | 68 | bigint_negate(&negated, op); |
| ... | ... | @@ -70,13 +73,14 @@ static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) |
| 70 | 73 | BigInt one = {0}; |
| 71 | 74 | bigint_init_unsigned(&one, 1); |
| 72 | 75 | |
| 73 | | bigint_add(dest, &inverted, &one); |
| 74 | | return; |
| 76 | bigint_add(&pos_op, &inverted, &one); |
| 77 | } else { |
| 78 | bigint_init_bigint(&pos_op, op); |
| 75 | 79 | } |
| 76 | 80 | |
| 77 | 81 | dest->is_negative = false; |
| 78 | | const uint64_t *op_digits = bigint_ptr(op); |
| 79 | | if (op->digit_count == 1) { |
| 82 | const uint64_t *op_digits = bigint_ptr(&pos_op); |
| 83 | if (pos_op.digit_count == 1) { |
| 80 | 84 | dest->data.digit = op_digits[0]; |
| 81 | 85 | if (bit_count < 64) { |
| 82 | 86 | dest->data.digit &= (1ULL << bit_count) - 1; |
| ... | ... | @@ -98,11 +102,11 @@ static void to_twos_complement(BigInt *dest, const BigInt *op, size_t bit_count) |
| 98 | 102 | } |
| 99 | 103 | dest->data.digits = heap::c_allocator.allocate_nonzero<uint64_t>(dest->digit_count); |
| 100 | 104 | for (size_t i = 0; i < digits_to_copy; i += 1) { |
| 101 | | uint64_t digit = (i < op->digit_count) ? op_digits[i] : 0; |
| 105 | uint64_t digit = (i < pos_op.digit_count) ? op_digits[i] : 0; |
| 102 | 106 | dest->data.digits[i] = digit; |
| 103 | 107 | } |
| 104 | 108 | if (leftover_bits != 0) { |
| 105 | | uint64_t digit = (digits_to_copy < op->digit_count) ? op_digits[digits_to_copy] : 0; |
| 109 | uint64_t digit = (digits_to_copy < pos_op.digit_count) ? op_digits[digits_to_copy] : 0; |
| 106 | 110 | dest->data.digits[digits_to_copy] = digit & ((1ULL << leftover_bits) - 1); |
| 107 | 111 | } |
| 108 | 112 | bigint_normalize(dest); |
| ... | ... | @@ -469,18 +473,18 @@ void bigint_min(BigInt* dest, const BigInt *op1, const BigInt *op2) { |
| 469 | 473 | } |
| 470 | 474 | |
| 471 | 475 | /// clamps op within bit_count/signedness boundaries |
| 472 | | /// signed bounds are [-2^(bit_count-1)..2^(bit_count-1)-1] |
| 473 | | /// unsigned bounds are [0..2^bit_count-1] |
| 476 | /// signed bounds are [-2^(bit_count-1)..2^(bit_count-1)-1] |
| 477 | /// unsigned bounds are [0..2^bit_count-1] |
| 474 | 478 | void bigint_clamp_by_bitcount(BigInt* dest, uint32_t bit_count, bool is_signed) { |
| 475 | | // compute the number of bits required to store the value, and use that |
| 479 | // compute the number of bits required to store the value, and use that |
| 476 | 480 | // to decide whether to clamp the result |
| 477 | 481 | bool is_negative = dest->is_negative; |
| 478 | | // to workaround the fact this bits_needed calculation would yield 65 or more for |
| 479 | | // all negative numbers, set is_negative to false. this is a cheap way to find |
| 480 | | // bits_needed(abs(dest)). |
| 482 | // to workaround the fact this bits_needed calculation would yield 65 or more for |
| 483 | // all negative numbers, set is_negative to false. this is a cheap way to find |
| 484 | // bits_needed(abs(dest)). |
| 481 | 485 | dest->is_negative = false; |
| 482 | 486 | // because we've set is_negative to false, we have to account for the extra bit here |
| 483 | | // by adding 1 additional bit_needed when (is_negative && !is_signed). |
| 487 | // by adding 1 additional bit_needed when (is_negative && !is_signed). |
| 484 | 488 | size_t full_bits = dest->digit_count * 64; |
| 485 | 489 | size_t leading_zero_count = bigint_clz(dest, full_bits); |
| 486 | 490 | size_t bits_needed = full_bits - leading_zero_count + (is_negative && !is_signed); |
| ... | ... | @@ -491,7 +495,7 @@ void bigint_clamp_by_bitcount(BigInt* dest, uint32_t bit_count, bool is_signed) |
| 491 | 495 | bigint_init_unsigned(&one, 1); |
| 492 | 496 | BigInt bit_count_big; |
| 493 | 497 | bigint_init_unsigned(&bit_count_big, bit_count); |
| 494 | | |
| 498 | |
| 495 | 499 | if(is_signed) { |
| 496 | 500 | if(is_negative) { |
| 497 | 501 | BigInt bound; |
| ... | ... | @@ -639,25 +643,22 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { |
| 639 | 643 | size_t i = 1; |
| 640 | 644 | |
| 641 | 645 | for (;;) { |
| 642 | | bool found_digit = false; |
| 643 | 646 | uint64_t x = bigger_op_digits[i]; |
| 644 | 647 | uint64_t prev_overflow = overflow; |
| 645 | 648 | overflow = 0; |
| 646 | 649 | |
| 647 | 650 | if (i < smaller_op->digit_count) { |
| 648 | | found_digit = true; |
| 649 | 651 | uint64_t digit = smaller_op_digits[i]; |
| 650 | 652 | overflow += sub_u64_overflow(x, digit, &x); |
| 651 | 653 | } |
| 652 | | if (sub_u64_overflow(x, prev_overflow, &x)) { |
| 653 | | found_digit = true; |
| 654 | | overflow += 1; |
| 655 | | } |
| 654 | |
| 655 | overflow += sub_u64_overflow(x, prev_overflow, &x); |
| 656 | 656 | dest->data.digits[i] = x; |
| 657 | 657 | i += 1; |
| 658 | 658 | |
| 659 | | if (!found_digit || i >= bigger_op->digit_count) |
| 659 | if (i >= bigger_op->digit_count) { |
| 660 | 660 | break; |
| 661 | } |
| 661 | 662 | } |
| 662 | 663 | assert(overflow == 0); |
| 663 | 664 | dest->digit_count = i; |