8#include <botan/bigint.h>
10#include <botan/assert.h>
11#include <botan/exceptn.h>
13#include <botan/mem_ops.h>
14#include <botan/internal/buffer_stuffer.h>
15#include <botan/internal/divide.h>
16#include <botan/internal/mp_core.h>
22consteval word decimal_conversion_radix() {
23 if constexpr(
sizeof(
word) == 8) {
24 return 10000000000000000000U;
30consteval size_t decimal_conversion_radix_digits() {
31 if constexpr(
sizeof(
word) == 8) {
42 constexpr word conversion_radix = decimal_conversion_radix();
43 constexpr size_t radix_digits = decimal_conversion_radix_digits();
46 const size_t digit_estimate =
static_cast<size_t>(1 + (
static_cast<double>(this->
bits()) / 3.32));
49 const size_t digit_blocks = (digit_estimate + radix_digits - 1) / radix_digits;
55 std::vector<word> digit_groups(digit_blocks);
57 for(
size_t i = 0; i != digit_blocks; ++i) {
60 digit_groups[i] = remainder;
66 std::vector<uint8_t> digits(digit_blocks * radix_digits);
68 for(
size_t i = 0; i != digit_blocks; ++i) {
69 word remainder = digit_groups[i];
70 for(
size_t j = 0; j != radix_digits; ++j) {
72 const word digit = remainder - new_remainder * 10;
73 digits[radix_digits * i + j] =
static_cast<uint8_t
>(digit);
74 remainder = new_remainder;
79 while(!digits.empty() && digits.back() == 0) {
87 s.reserve(1 + digits.size());
96 for(
auto i = digits.rbegin(); i != digits.rend(); ++i) {
97 s.push_back(*i +
'0');
108 const size_t this_bytes = this->
bytes();
109 std::vector<uint8_t>
bits(std::max<size_t>(1, this_bytes));
129 if(digits.size() % 2 == 1) {
131 const char buf0_with_leading_0[2] = {
'0', digits[0]};
135 if(digits.size() > 1) {
143 }
else if(radix == 10) {
147 constexpr word conversion_radix = decimal_conversion_radix();
148 constexpr size_t radix_digits = decimal_conversion_radix_digits();
153 const size_t partial_block = digits.size() % radix_digits;
155 if(partial_block > 0) {
157 for(
size_t i = 0; i < partial_block; ++i) {
158 const char c = digits[i];
160 acc = acc * 10 +
static_cast<word>(c -
'0');
166 for(
size_t i = partial_block; i != digits.size(); i += radix_digits) {
168 for(
size_t j = 0; j < radix_digits; ++j) {
169 const char c = digits[i + j];
171 acc = acc * 10 +
static_cast<word>(c -
'0');
173 r *= conversion_radix;
188 throw Encoding_Error(
"encode_fixed_length_int_pair: values must be positive");
191 throw Encoding_Error(
"encode_fixed_length_int_pair: values too large to encode properly");
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ARG_CHECK(expr, msg)
static BigInt decode(const uint8_t buf[], size_t length)
std::string to_dec_string() const
std::string to_hex_string() const
static secure_vector< uint8_t > encode_fixed_length_int_pair(const BigInt &n1, const BigInt &n2, size_t bytes)
void serialize_to(std::span< uint8_t > out) const
static BigInt from_bytes(std::span< const uint8_t > bytes)
static BigInt from_radix_digits(std::string_view digits, size_t radix)
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr std::span< uint8_t > next(size_t bytes)
secure_vector< uint8_t > hex_decode_locked(const char input[], size_t input_length, bool ignore_ws)
constexpr W divide_10(W x)
void hex_encode(char output[], const uint8_t input[], size_t input_length, bool uppercase)
void ct_divide_word(const BigInt &x, word y, BigInt &q_out, word &r_out)
const char * cast_uint8_ptr_to_char(const uint8_t *b)
std::vector< T, secure_allocator< T > > secure_vector
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word