cpp_mp/mp/lib.hpp

100 lines
2.2 KiB
C++

#pragma once
#include <algorithm>
#include <string>
#include <stdexcept>
#include "utils.hpp"
namespace mp
{
inline char hex_digit(uint8_t bits)
{
return bits > 9 ? 'a' + (bits - 10) : '0' + bits;
}
template <AnyConstMpInt T>
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 "0x" + str.substr(first);
}
return "0x0";
}
template <AnyMpInt T>
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<ElementType>;
LongerType acc = (static_cast<LongerType>(remainder) << (T::ELEMENT_BYTES * 8)) | value[i];
value[i] = static_cast<ElementType>(acc / divisor);
remainder = static_cast<ElementType>(acc % divisor);
}
return remainder;
}
template <AnyConstMpInt T>
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<char>('0' + rem));
} while (temp != 0U);
std::reverse(str.begin(), str.end());
return str;
}
template <AnyMpInt T>
inline void parse_string(const char* str, T& number)
{
number.zero();
for (; *str; ++str)
{
if (*str < '0' || *str > '9')
{
throw std::invalid_argument("Invalid character in input string");
}
number = number * 10U + static_cast<typename T::ElementType>(*str - '0');
}
}
// template <AnyConstInt T>
// inline T parse_string(const char* str)
// {
// T number;
// parse_string(str, number);
// return number;
// }
}