|
@@ -96,6 +96,21 @@ String UnsignedBigInteger::to_base10() const
|
|
|
return builder.to_string();
|
|
|
}
|
|
|
|
|
|
+void UnsignedBigInteger::set_to_0()
|
|
|
+{
|
|
|
+ m_words.clear_with_capacity();
|
|
|
+ m_is_invalid = false;
|
|
|
+}
|
|
|
+
|
|
|
+void UnsignedBigInteger::set_to(const UnsignedBigInteger& other)
|
|
|
+{
|
|
|
+ m_is_invalid = other.m_is_invalid;
|
|
|
+ m_words.clear_with_capacity();
|
|
|
+ m_words.ensure_capacity(other.m_words.size());
|
|
|
+ for (size_t i = 0; i < other.m_words.size(); ++i)
|
|
|
+ m_words.unchecked_append(other.m_words[i]);
|
|
|
+}
|
|
|
+
|
|
|
size_t UnsignedBigInteger::trimmed_length() const
|
|
|
{
|
|
|
size_t num_leading_zeroes = 0;
|
|
@@ -106,18 +121,135 @@ size_t UnsignedBigInteger::trimmed_length() const
|
|
|
return length() - num_leading_zeroes;
|
|
|
}
|
|
|
|
|
|
+FLATTEN UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) const
|
|
|
+{
|
|
|
+ UnsignedBigInteger result;
|
|
|
+
|
|
|
+ add_without_allocation(*this, other, result);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+FLATTEN UnsignedBigInteger UnsignedBigInteger::minus(const UnsignedBigInteger& other) const
|
|
|
+{
|
|
|
+ UnsignedBigInteger result;
|
|
|
+
|
|
|
+ subtract_without_allocation(*this, other, result);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+FLATTEN UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const
|
|
|
+{
|
|
|
+ UnsignedBigInteger output;
|
|
|
+ UnsignedBigInteger temp_result;
|
|
|
+ UnsignedBigInteger temp_plus;
|
|
|
+
|
|
|
+ shift_left_without_allocation(*this, num_bits, temp_result, temp_plus, output);
|
|
|
+
|
|
|
+ return output;
|
|
|
+}
|
|
|
+
|
|
|
+FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigInteger& other) const
|
|
|
+{
|
|
|
+ UnsignedBigInteger result;
|
|
|
+ UnsignedBigInteger temp_shift_result;
|
|
|
+ UnsignedBigInteger temp_shift_plus;
|
|
|
+ UnsignedBigInteger temp_shift;
|
|
|
+ UnsignedBigInteger temp_plus;
|
|
|
+
|
|
|
+ multiply_without_allocation(*this, other, temp_shift_result, temp_shift_plus, temp_shift, temp_plus, result);
|
|
|
+
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+FLATTEN UnsignedDivisionResult UnsignedBigInteger::divided_by(const UnsignedBigInteger& divisor) const
|
|
|
+{
|
|
|
+ UnsignedBigInteger quotient;
|
|
|
+ UnsignedBigInteger remainder;
|
|
|
+
|
|
|
+ UnsignedBigInteger temp_shift_result;
|
|
|
+ UnsignedBigInteger temp_shift_plus;
|
|
|
+ UnsignedBigInteger temp_shift;
|
|
|
+ UnsignedBigInteger temp_minus;
|
|
|
+
|
|
|
+ divide_without_allocation(*this, divisor, temp_shift_result, temp_shift_plus, temp_shift, temp_minus, quotient, remainder);
|
|
|
+
|
|
|
+ return UnsignedDivisionResult { quotient, remainder };
|
|
|
+}
|
|
|
+
|
|
|
+void UnsignedBigInteger::set_bit_inplace(size_t bit_index)
|
|
|
+{
|
|
|
+ const size_t word_index = bit_index / UnsignedBigInteger::BITS_IN_WORD;
|
|
|
+ const size_t inner_word_index = bit_index % UnsignedBigInteger::BITS_IN_WORD;
|
|
|
+
|
|
|
+ m_words.ensure_capacity(word_index);
|
|
|
+
|
|
|
+ for (size_t i = length(); i <= word_index; ++i) {
|
|
|
+ m_words.unchecked_append(0);
|
|
|
+ }
|
|
|
+ m_words[word_index] |= (1 << inner_word_index);
|
|
|
+}
|
|
|
+
|
|
|
+bool UnsignedBigInteger::operator==(const UnsignedBigInteger& other) const
|
|
|
+{
|
|
|
+ auto length = trimmed_length();
|
|
|
+
|
|
|
+ if (length != other.trimmed_length()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (is_invalid() != other.is_invalid()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return !__builtin_memcmp(m_words.data(), other.words().data(), length);
|
|
|
+}
|
|
|
+
|
|
|
+bool UnsignedBigInteger::operator!=(const UnsignedBigInteger& other) const
|
|
|
+{
|
|
|
+ return !(*this == other);
|
|
|
+}
|
|
|
+
|
|
|
+bool UnsignedBigInteger::operator<(const UnsignedBigInteger& other) const
|
|
|
+{
|
|
|
+ auto length = trimmed_length();
|
|
|
+ auto other_length = other.trimmed_length();
|
|
|
+
|
|
|
+ if (length < other_length) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (length > other_length) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (length == 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ for (int i = length - 1; i >= 0; --i) {
|
|
|
+ if (m_words[i] == other.m_words[i])
|
|
|
+ continue;
|
|
|
+ return m_words[i] < other.m_words[i];
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Complexity: O(N) where N is the number of words in the larger number
|
|
|
*/
|
|
|
-UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) const
|
|
|
+void UnsignedBigInteger::add_without_allocation(
|
|
|
+ const UnsignedBigInteger& left,
|
|
|
+ const UnsignedBigInteger& right,
|
|
|
+ UnsignedBigInteger& output)
|
|
|
{
|
|
|
- const UnsignedBigInteger* const longer = (length() > other.length()) ? this : &other;
|
|
|
- const UnsignedBigInteger* const shorter = (longer == &other) ? this : &other;
|
|
|
- UnsignedBigInteger result;
|
|
|
+ const UnsignedBigInteger* const longer = (left.length() > right.length()) ? &left : &right;
|
|
|
+ const UnsignedBigInteger* const shorter = (longer == &right) ? &left : &right;
|
|
|
|
|
|
u8 carry = 0;
|
|
|
|
|
|
- result.m_words.ensure_capacity(longer->length() + 1);
|
|
|
+ output.set_to_0();
|
|
|
+ output.m_words.ensure_capacity(longer->length() + 1);
|
|
|
|
|
|
for (size_t i = 0; i < shorter->length(); ++i) {
|
|
|
u32 word_addition_result = shorter->m_words[i] + longer->m_words[i];
|
|
@@ -130,7 +262,7 @@ UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) con
|
|
|
word_addition_result++;
|
|
|
}
|
|
|
carry = carry_out;
|
|
|
- result.m_words.unchecked_append(word_addition_result);
|
|
|
+ output.m_words.unchecked_append(word_addition_result);
|
|
|
}
|
|
|
|
|
|
for (size_t i = shorter->length(); i < longer->length(); ++i) {
|
|
@@ -140,97 +272,130 @@ UnsignedBigInteger UnsignedBigInteger::plus(const UnsignedBigInteger& other) con
|
|
|
if (word_addition_result < longer->m_words[i]) {
|
|
|
carry = 1;
|
|
|
}
|
|
|
- result.m_words.unchecked_append(word_addition_result);
|
|
|
+ output.m_words.unchecked_append(word_addition_result);
|
|
|
}
|
|
|
if (carry) {
|
|
|
- result.m_words.unchecked_append(carry);
|
|
|
+ output.m_words.unchecked_append(carry);
|
|
|
}
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Complexity: O(N) where N is the number of words in the larger number
|
|
|
*/
|
|
|
-UnsignedBigInteger UnsignedBigInteger::minus(const UnsignedBigInteger& other) const
|
|
|
+void UnsignedBigInteger::subtract_without_allocation(
|
|
|
+ const UnsignedBigInteger& left,
|
|
|
+ const UnsignedBigInteger& right,
|
|
|
+ UnsignedBigInteger& output)
|
|
|
{
|
|
|
- UnsignedBigInteger result;
|
|
|
-
|
|
|
- if (*this < other) {
|
|
|
- return UnsignedBigInteger::create_invalid();
|
|
|
+ if (left < right) {
|
|
|
+ output.invalidate();
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
u8 borrow = 0;
|
|
|
- auto own_length = length(), other_length = other.length();
|
|
|
+ auto own_length = left.length();
|
|
|
+ auto other_length = right.length();
|
|
|
|
|
|
- result.m_words.ensure_capacity(own_length);
|
|
|
+ output.set_to_0();
|
|
|
+ output.m_words.ensure_capacity(own_length);
|
|
|
|
|
|
for (size_t i = 0; i < own_length; ++i) {
|
|
|
- u32 other_word = (i < other_length) ? other.m_words[i] : 0;
|
|
|
- i64 temp = static_cast<i64>(m_words[i]) - static_cast<i64>(other_word) - static_cast<i64>(borrow);
|
|
|
+ u32 other_word = (i < other_length) ? right.m_words[i] : 0;
|
|
|
+ i64 temp = static_cast<i64>(left.m_words[i]) - static_cast<i64>(other_word) - static_cast<i64>(borrow);
|
|
|
// If temp < 0, we had an underflow
|
|
|
borrow = (temp >= 0) ? 0 : 1;
|
|
|
if (temp < 0) {
|
|
|
temp += (UINT32_MAX + 1);
|
|
|
}
|
|
|
- result.m_words.append(temp);
|
|
|
+ output.m_words.append(temp);
|
|
|
}
|
|
|
|
|
|
// This assertion should not fail, because we verified that *this>=other at the beginning of the function
|
|
|
ASSERT(borrow == 0);
|
|
|
-
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
-UnsignedBigInteger UnsignedBigInteger::shift_left(size_t num_bits) const
|
|
|
+/**
|
|
|
+ * Complexity : O(N + num_bits % 8) where N is the number of words in the number
|
|
|
+ * Shift method :
|
|
|
+ * Start by shifting by whole words in num_bits (by putting missing words at the start),
|
|
|
+ * then shift the number's words two by two by the remaining amount of bits.
|
|
|
+ */
|
|
|
+FLATTEN void UnsignedBigInteger::shift_left_without_allocation(
|
|
|
+ const UnsignedBigInteger& number,
|
|
|
+ size_t num_bits,
|
|
|
+ UnsignedBigInteger& temp_result,
|
|
|
+ UnsignedBigInteger& temp_plus,
|
|
|
+ UnsignedBigInteger& output)
|
|
|
{
|
|
|
// We can only do shift operations on individual words
|
|
|
// where the shift amount is <= size of word (32).
|
|
|
// But we do know how to shift by a multiple of word size (e.g 64=32*2)
|
|
|
// So we first shift the result by how many whole words fit in 'num_bits'
|
|
|
- UnsignedBigInteger temp_result = shift_left_by_n_words(num_bits / UnsignedBigInteger::BITS_IN_WORD);
|
|
|
+ shift_left_by_n_words(number, num_bits / UnsignedBigInteger::BITS_IN_WORD, temp_result);
|
|
|
+
|
|
|
+ output.set_to(temp_result);
|
|
|
|
|
|
// And now we shift by the leftover amount of bits
|
|
|
num_bits %= UnsignedBigInteger::BITS_IN_WORD;
|
|
|
|
|
|
- UnsignedBigInteger result(temp_result);
|
|
|
+ if (num_bits == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
for (size_t i = 0; i < temp_result.length(); ++i) {
|
|
|
- u32 current_word_of_temp_result = temp_result.shift_left_get_one_word(num_bits, i);
|
|
|
- result.m_words[i] = current_word_of_temp_result;
|
|
|
+ u32 current_word_of_temp_result = shift_left_get_one_word(temp_result, num_bits, i);
|
|
|
+ output.m_words[i] = current_word_of_temp_result;
|
|
|
}
|
|
|
|
|
|
// Shifting the last word can produce a carry
|
|
|
- u32 carry_word = temp_result.shift_left_get_one_word(num_bits, temp_result.length());
|
|
|
+ u32 carry_word = shift_left_get_one_word(temp_result, num_bits, temp_result.length());
|
|
|
if (carry_word != 0) {
|
|
|
- result = result.plus(UnsignedBigInteger(carry_word).shift_left_by_n_words(temp_result.length()));
|
|
|
+
|
|
|
+ // output += (carry_word << temp_result.length())
|
|
|
+ // FIXME : Using temp_plus this way to transform carry_word into a bigint is not
|
|
|
+ // efficient nor pretty. Maybe we should have an "add_with_shift" method ?
|
|
|
+ temp_plus.set_to_0();
|
|
|
+ temp_plus.m_words.append(carry_word);
|
|
|
+ shift_left_by_n_words(temp_plus, temp_result.length(), temp_result);
|
|
|
+ add_without_allocation(output, temp_result, temp_plus);
|
|
|
+ output.set_to(temp_plus);
|
|
|
}
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Complexity: O(N^2) where N is the number of words in the larger number
|
|
|
- * Multiplcation method:
|
|
|
+ * Multiplication method:
|
|
|
* An integer is equal to the sum of the powers of two
|
|
|
* according to the indexes of its 'on' bits.
|
|
|
* So to multiple x*y, we go over each '1' bit in x (say the i'th bit),
|
|
|
* and add y<<i to the result.
|
|
|
*/
|
|
|
-FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigInteger& other) const
|
|
|
+FLATTEN void UnsignedBigInteger::multiply_without_allocation(
|
|
|
+ const UnsignedBigInteger& left,
|
|
|
+ const UnsignedBigInteger& right,
|
|
|
+ UnsignedBigInteger& temp_shift_result,
|
|
|
+ UnsignedBigInteger& temp_shift_plus,
|
|
|
+ UnsignedBigInteger& temp_shift,
|
|
|
+ UnsignedBigInteger& temp_plus,
|
|
|
+ UnsignedBigInteger& output)
|
|
|
{
|
|
|
- UnsignedBigInteger result;
|
|
|
+ output.set_to_0();
|
|
|
+
|
|
|
// iterate all bits
|
|
|
- for (size_t word_index = 0; word_index < length(); ++word_index) {
|
|
|
+ for (size_t word_index = 0; word_index < left.length(); ++word_index) {
|
|
|
for (size_t bit_index = 0; bit_index < UnsignedBigInteger::BITS_IN_WORD; ++bit_index) {
|
|
|
// If the bit is off - skip over it
|
|
|
- if (!(m_words[word_index] & (1 << bit_index)))
|
|
|
+ if (!(left.m_words[word_index] & (1 << bit_index)))
|
|
|
continue;
|
|
|
|
|
|
const size_t shift_amount = word_index * UnsignedBigInteger::BITS_IN_WORD + bit_index;
|
|
|
- auto shift_result = other.shift_left(shift_amount);
|
|
|
- result = result.plus(shift_result);
|
|
|
+
|
|
|
+ // output += (right << shift_amount);
|
|
|
+ shift_left_without_allocation(right, shift_amount, temp_shift_result, temp_shift_plus, temp_shift);
|
|
|
+ add_without_allocation(output, temp_shift, temp_plus);
|
|
|
+ output.set_to(temp_plus);
|
|
|
}
|
|
|
}
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -241,118 +406,71 @@ FLATTEN UnsignedBigInteger UnsignedBigInteger::multiplied_by(const UnsignedBigIn
|
|
|
* so we set the ith bit in the quotient and reduce divisor<<i from the dividend.
|
|
|
* When we're done, what's left from the dividend is the remainder.
|
|
|
*/
|
|
|
-FLATTEN UnsignedDivisionResult UnsignedBigInteger::divided_by(const UnsignedBigInteger& divisor) const
|
|
|
+FLATTEN void UnsignedBigInteger::divide_without_allocation(
|
|
|
+ const UnsignedBigInteger& numerator,
|
|
|
+ const UnsignedBigInteger& denominator,
|
|
|
+ UnsignedBigInteger& temp_shift_result,
|
|
|
+ UnsignedBigInteger& temp_shift_plus,
|
|
|
+ UnsignedBigInteger& temp_shift,
|
|
|
+ UnsignedBigInteger& temp_minus,
|
|
|
+ UnsignedBigInteger& quotient,
|
|
|
+ UnsignedBigInteger& remainder)
|
|
|
{
|
|
|
- UnsignedBigInteger leftover_dividend(*this);
|
|
|
- UnsignedBigInteger quotient;
|
|
|
+ quotient.set_to_0();
|
|
|
+ remainder.set_to(numerator);
|
|
|
|
|
|
// iterate all bits
|
|
|
- for (int word_index = trimmed_length() - 1; word_index >= 0; --word_index) {
|
|
|
+ for (int word_index = numerator.trimmed_length() - 1; word_index >= 0; --word_index) {
|
|
|
for (int bit_index = UnsignedBigInteger::BITS_IN_WORD - 1; bit_index >= 0; --bit_index) {
|
|
|
-
|
|
|
const size_t shift_amount = word_index * UnsignedBigInteger::BITS_IN_WORD + bit_index;
|
|
|
- UnsignedBigInteger divisor_shifted = divisor.shift_left(shift_amount);
|
|
|
+ shift_left_without_allocation(denominator, shift_amount, temp_shift_result, temp_shift_plus, temp_shift);
|
|
|
|
|
|
- UnsignedBigInteger temp_subtraction_result = leftover_dividend.minus(divisor_shifted);
|
|
|
- if (!temp_subtraction_result.is_invalid()) {
|
|
|
- leftover_dividend = temp_subtraction_result;
|
|
|
+ subtract_without_allocation(remainder, temp_shift, temp_minus);
|
|
|
+ if (!temp_minus.is_invalid()) {
|
|
|
+ remainder.set_to(temp_minus);
|
|
|
quotient.set_bit_inplace(shift_amount);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- return UnsignedDivisionResult { quotient, leftover_dividend };
|
|
|
-}
|
|
|
-
|
|
|
-void UnsignedBigInteger::set_bit_inplace(size_t bit_index)
|
|
|
-{
|
|
|
- const size_t word_index = bit_index / UnsignedBigInteger::BITS_IN_WORD;
|
|
|
- const size_t inner_word_index = bit_index % UnsignedBigInteger::BITS_IN_WORD;
|
|
|
-
|
|
|
- m_words.ensure_capacity(word_index);
|
|
|
-
|
|
|
- for (size_t i = length(); i <= word_index; ++i) {
|
|
|
- m_words.unchecked_append(0);
|
|
|
- }
|
|
|
- m_words[word_index] |= (1 << inner_word_index);
|
|
|
}
|
|
|
|
|
|
-bool UnsignedBigInteger::operator==(const UnsignedBigInteger& other) const
|
|
|
-{
|
|
|
- auto length = trimmed_length();
|
|
|
-
|
|
|
- if (length != other.trimmed_length()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (is_invalid() != other.is_invalid()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- return !__builtin_memcmp(m_words.data(), other.words().data(), length);
|
|
|
-}
|
|
|
-
|
|
|
-bool UnsignedBigInteger::operator!=(const UnsignedBigInteger& other) const
|
|
|
-{
|
|
|
- return !(*this == other);
|
|
|
-}
|
|
|
-
|
|
|
-bool UnsignedBigInteger::operator<(const UnsignedBigInteger& other) const
|
|
|
-{
|
|
|
- auto length = trimmed_length();
|
|
|
- auto other_length = other.trimmed_length();
|
|
|
-
|
|
|
- if (length < other_length) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (length > other_length) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- if (length == 0) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- for (int i = length - 1; i >= 0; --i) {
|
|
|
- if (m_words[i] == other.m_words[i])
|
|
|
- continue;
|
|
|
- return m_words[i] < other.m_words[i];
|
|
|
- }
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
-ALWAYS_INLINE UnsignedBigInteger UnsignedBigInteger::shift_left_by_n_words(const size_t number_of_words) const
|
|
|
+ALWAYS_INLINE void UnsignedBigInteger::shift_left_by_n_words(
|
|
|
+ const UnsignedBigInteger& number,
|
|
|
+ const size_t number_of_words,
|
|
|
+ UnsignedBigInteger& output)
|
|
|
{
|
|
|
// shifting left by N words means just inserting N zeroes to the beginning of the words vector
|
|
|
- UnsignedBigInteger result;
|
|
|
-
|
|
|
- result.m_words.ensure_capacity(number_of_words + length());
|
|
|
+ output.set_to_0();
|
|
|
+ output.m_words.ensure_capacity(number_of_words + number.length());
|
|
|
|
|
|
for (size_t i = 0; i < number_of_words; ++i) {
|
|
|
- result.m_words.unchecked_append(0);
|
|
|
+ output.m_words.unchecked_append(0);
|
|
|
}
|
|
|
- for (size_t i = 0; i < length(); ++i) {
|
|
|
- result.m_words.unchecked_append(m_words[i]);
|
|
|
+ for (size_t i = 0; i < number.length(); ++i) {
|
|
|
+ output.m_words.unchecked_append(number.m_words[i]);
|
|
|
}
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Returns the word at a requested index in the result of a shift operation
|
|
|
*/
|
|
|
-ALWAYS_INLINE u32 UnsignedBigInteger::shift_left_get_one_word(const size_t num_bits, const size_t result_word_index) const
|
|
|
+ALWAYS_INLINE u32 UnsignedBigInteger::shift_left_get_one_word(
|
|
|
+ const UnsignedBigInteger& number,
|
|
|
+ const size_t num_bits,
|
|
|
+ const size_t result_word_index)
|
|
|
{
|
|
|
// "<= length()" (rather than length() - 1) is intentional,
|
|
|
// The result inedx of length() is used when calculating the carry word
|
|
|
- ASSERT(result_word_index <= length());
|
|
|
+ ASSERT(result_word_index <= number.length());
|
|
|
ASSERT(num_bits <= UnsignedBigInteger::BITS_IN_WORD);
|
|
|
u32 result = 0;
|
|
|
|
|
|
// we need to check for "num_bits != 0" since shifting right by 32 is apparently undefined behaviour!
|
|
|
if (result_word_index > 0 && num_bits != 0) {
|
|
|
- result += m_words[result_word_index - 1] >> (UnsignedBigInteger::BITS_IN_WORD - num_bits);
|
|
|
+ result += number.m_words[result_word_index - 1] >> (UnsignedBigInteger::BITS_IN_WORD - num_bits);
|
|
|
}
|
|
|
- if (result_word_index < length() && num_bits < 32) {
|
|
|
- result += m_words[result_word_index] << num_bits;
|
|
|
+ if (result_word_index < number.length() && num_bits < 32) {
|
|
|
+ result += number.m_words[result_word_index] << num_bits;
|
|
|
}
|
|
|
return result;
|
|
|
}
|