diff --git a/vlib/math/big/big_test.v b/vlib/math/big/big_test.v index 17b7e6c169..32d681a7b3 100644 --- a/vlib/math/big/big_test.v +++ b/vlib/math/big/big_test.v @@ -432,3 +432,16 @@ fn test_set_bit() { a.set_bit(100, false) assert a == b } + +fn test_bit_len() { + assert big.zero_int.bit_len() == 0 + assert big.one_int.bit_len() == 1 + + assert big.integer_from_u32(0xffffffff).bit_len() == 32 + + assert big.one_int.lshift(1239).bit_len() == 1240 + + assert big.integer_from_string('4338476092346017364013796407961305761039463198075691378460917856') or { + panic('Could not read from decimal') + }.bit_len() == 212 +} diff --git a/vlib/math/big/integer.v b/vlib/math/big/integer.v index 91f80a504f..c8c1b11106 100644 --- a/vlib/math/big/integer.v +++ b/vlib/math/big/integer.v @@ -634,8 +634,7 @@ pub fn (integer Integer) binary_str() string { } // Add the sign if present sign_needed := integer.signum == -1 - mut result_builder := strings.new_builder(integer.digits.len * 32 + - if sign_needed { 1 } else { 0 }) + mut result_builder := strings.new_builder(integer.bit_len() + if sign_needed { 1 } else { 0 }) if sign_needed { result_builder.write_string('-') } @@ -901,3 +900,17 @@ pub fn (x Integer) gcd_binary(y Integer) Integer { } return b.lshift(shift) } + +[direct_array_access] +pub fn (x Integer) bit_len() int { + if x.signum == 0 { + return 0 + } + + mut length := 0 + for _ in 1 .. x.digits.len { + length += 32 + } + + return length + (32 - bits.leading_zeros_32(x.digits.last())) +}