#pragma once #include #include #include #include "utils.hpp" #include "int.hpp" namespace mp { inline char hex_digit(uint8_t bits) { return bits > 9 ? 'a' + (bits - 10) : '0' + bits; } template inline std::string to_hex_string(const T& number) { constexpr size_t ELEMENT_DIGITS = T::ELEMENT_BYTES * 2; std::string str(number.size_elems() * ELEMENT_DIGITS, '?'); for (size_t elem = 0; elem < number.size_elems(); ++elem) { auto v = number[elem]; for (size_t digit = 0; digit < ELEMENT_DIGITS; ++digit) { str[str.size() - 1 - (elem * ELEMENT_DIGITS) - digit] = hex_digit((v >> (digit * 4)) & 0xF); } } auto first = str.find_first_not_of('0'); if (first != std::string::npos) { return (number.negative() ? "-" : "") + ("0x" + str.substr(first)); } return "0x0"; } template inline typename T::ElementType div_mod(T& value, const typename T::ElementType divisor) { using ElementType = typename T::ElementType; ElementType remainder = 0; for (size_t i = value.size_elems(); i-- > 0; ) { using LongerType = DoubleWidthType; LongerType acc = (static_cast(remainder) << (T::ELEMENT_BYTES * 8)) | value[i]; value[i] = static_cast(acc / divisor); remainder = static_cast(acc % divisor); } return remainder; } template inline std::string to_string(const T& number) { std::string str; T temp = number; do { auto rem = div_mod(temp, 10U); str.push_back(static_cast('0' + rem)); } while (temp != 0U); if (number.negative()) str.push_back('-'); std::reverse(str.begin(), str.end()); return str; } template inline void parse_string(const char* str, T& number) { number.zero(); bool negative = false; if (*str == '-') { negative = true; ++str; } for (; *str; ++str) { if (*str < '0' || *str > '9') { throw std::invalid_argument("Invalid character in input string"); } number = number * 10U + static_cast(*str - '0'); } number.set_negative(negative); } template inline T from_string(const char* str) { T number; parse_string(str, number); return number; } template inline Int from_string(const char* str) { Int number; parse_string(str, number); return number; } // template // inline T parse_string(const char* str) // { // T number; // parse_string(str, number); // return number; // } }