Skip to content

Commit

Permalink
Changed big_unsigned bit length function to be single bit accurate.
Browse files Browse the repository at this point in the history
  • Loading branch information
gpdaniels committed Oct 4, 2023
1 parent 74ec473 commit e0b2bff
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 16 deletions.
9 changes: 6 additions & 3 deletions source/math/big_integer
Original file line number Diff line number Diff line change
Expand Up @@ -739,20 +739,23 @@ namespace gtl {
}

public:
/// @brief Get the length of the big number in allocated bits for the magnitude.
/// @brief Get the length of the big number in allocated bits.
/// @return The number of bits allocated to store the big number.
/// @note This does not include a bit to store the sign.
unsigned long long int get_length_bits() const {
return this->magnitude.get_length_bits();
}

/// @brief Get the length of the big number in allocated bytes for the magnitude.
/// @return The number of bytes allocated to store the big number.
/// @brief Get the length of the big number in bytes.
/// @return The number of bytes needed to store the big number.
/// @note This does not include a byte to store the sign.
unsigned long long int get_length_bytes() const {
return this->magnitude.get_length_bytes();
}

/// @brief Get the length of the big number as a decimal number.
/// @return The number of digits required to represent the big number.
/// @note This does not include a character to store the sign.
unsigned long long int get_length_decimal() const {
return this->magnitude.get_length_decimal();
}
Expand Down
18 changes: 14 additions & 4 deletions source/math/big_unsigned
Original file line number Diff line number Diff line change
Expand Up @@ -903,14 +903,24 @@ namespace gtl {
}

public:
/// @brief Get the length of the big number in allocated bits, this will be a multiple of eight.
/// @brief Get the length of the big number in allocated bits.
/// @return The number of bits allocated to store the big number.
unsigned long long int get_length_bits() const {
return this->chunks.size() * big_unsigned::chunk_bits;
unsigned int msb = this->chunks.back() | 1;
unsigned int remainder = big_unsigned::chunk_bits;
while (msb < 0x01000000) {
msb <<= 8;
remainder -= 8;
}
while ((msb > 0) && (!(msb & 0x80000000))) {
msb <<= 1;
--remainder;
}
return remainder + (this->chunks.size() - 1) * big_unsigned::chunk_bits;
}

/// @brief Get the length of the big number in allocated bytes.
/// @return The number of bytes allocated to store the big number.
/// @brief Get the length of the big number in bytes.
/// @return The number of bytes needed to store the big number.
unsigned long long int get_length_bytes() const {
const unsigned long long int remainder = (this->chunks.back() > 0xFFFFFF) + (this->chunks.back() > 0xFFFF) + (this->chunks.back() > 0xFF) + 1;
return remainder + (this->chunks.size() - 1) * sizeof(chunk_type);
Expand Down
12 changes: 6 additions & 6 deletions tests/math/big_integer.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1156,24 +1156,24 @@ TEST(big_integer, operator, get_length_bits) {

gtl::big_integer big_integer_lhs(lhs);
gtl::big_integer big_integer_rhs(rhs);
REQUIRE(big_integer_lhs.get_length_bits() == 64);
REQUIRE(big_integer_rhs.get_length_bits() == 32);
REQUIRE(big_integer_lhs.get_length_bits() == 63);
REQUIRE(big_integer_rhs.get_length_bits() == 2);

constexpr static const char* two_power_333 = "17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592";
gtl::big_integer big_integer_333(two_power_333, testbench::string_length(two_power_333));
REQUIRE(big_integer_333.get_length_bits() == 352);
REQUIRE(big_integer_333.get_length_bits() == 334);

signed long long int lhs_negative = -(1ll << 62);
signed long long int rhs_negative = -2;

gtl::big_integer big_integer_lhs_negative(lhs_negative);
gtl::big_integer big_integer_rhs_negative(rhs_negative);
REQUIRE(big_integer_lhs_negative.get_length_bits() == 64);
REQUIRE(big_integer_rhs_negative.get_length_bits() == 32);
REQUIRE(big_integer_lhs_negative.get_length_bits() == 63);
REQUIRE(big_integer_rhs_negative.get_length_bits() == 2);

constexpr static const char* two_power_333_negative = "-17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592";
gtl::big_integer big_integer_333_negative(two_power_333_negative, testbench::string_length(two_power_333_negative));
REQUIRE(big_integer_333_negative.get_length_bits() == 352);
REQUIRE(big_integer_333_negative.get_length_bits() == 334);
}

TEST(big_integer, operator, get_length_bytes) {
Expand Down
6 changes: 3 additions & 3 deletions tests/math/big_unsigned.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,12 +652,12 @@ TEST(big_unsigned, operator, get_length_bits) {

gtl::big_unsigned big_unsigned_lhs(lhs);
gtl::big_unsigned big_unsigned_rhs(rhs);
REQUIRE(big_unsigned_lhs.get_length_bits() == 64);
REQUIRE(big_unsigned_rhs.get_length_bits() == 32);
REQUIRE(big_unsigned_lhs.get_length_bits() == 63);
REQUIRE(big_unsigned_rhs.get_length_bits() == 2);

constexpr static const char* two_power_333 = "17498005798264095394980017816940970922825355447145699491406164851279623993595007385788105416184430592";
gtl::big_unsigned big_unsigned_333(two_power_333, testbench::string_length(two_power_333));
REQUIRE(big_unsigned_333.get_length_bits() == 352);
REQUIRE(big_unsigned_333.get_length_bits() == 334);
}

TEST(big_unsigned, operator, get_length_bytes) {
Expand Down

0 comments on commit e0b2bff

Please sign in to comment.