121 lines
2.5 KiB
C++
121 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include <algorithm>
|
|
#include <string>
|
|
#include <stdexcept>
|
|
|
|
#include "utils.hpp"
|
|
#include "int.hpp"
|
|
|
|
namespace mp
|
|
{
|
|
|
|
inline char hex_digit(uint8_t bits)
|
|
{
|
|
return bits > 9 ? 'a' + (bits - 10) : '0' + bits;
|
|
}
|
|
|
|
template <AnyMpInt 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 (number.negative() ? "-" : "") + ("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 <AnyMpInt 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);
|
|
|
|
if (number.negative())
|
|
str.push_back('-');
|
|
|
|
std::reverse(str.begin(), str.end());
|
|
return str;
|
|
}
|
|
|
|
template <AnyInt T>
|
|
inline T from_string(const char* str)
|
|
{
|
|
T number;
|
|
parse_string(str, number);
|
|
return number;
|
|
}
|
|
|
|
template <size_t N>
|
|
inline Int<N> from_string(const char* str)
|
|
{
|
|
Int<N> number;
|
|
parse_string(str, number);
|
|
return number;
|
|
}
|
|
|
|
template <AnyInt T>
|
|
inline T factorial(const T& n)
|
|
{
|
|
if (n < 0)
|
|
{
|
|
throw std::invalid_argument("Factorial is not defined for negative numbers");
|
|
}
|
|
|
|
T result = 1;
|
|
for (T i = 2; i <= n; ++i)
|
|
{
|
|
result *= i;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
// template <AnyInt T>
|
|
// inline T parse_string(const char* str)
|
|
// {
|
|
// T number;
|
|
// parse_string(str, number);
|
|
// return number;
|
|
// }
|
|
|
|
} |