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