Init
This commit is contained in:
commit
ac10af30da
6
.clang-format
Normal file
6
.clang-format
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
BasedOnStyle: Microsoft
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Left
|
||||||
|
IndentWidth: 4 # spaces per indent level
|
||||||
|
TabWidth: 4 # width of a tab character
|
||||||
|
UseTab: Never # options: Never, ForIndentation, Alwayss
|
||||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.vscode/
|
||||||
|
build/
|
||||||
7
CMakeLists.txt
Normal file
7
CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(CppMpInt)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
|
||||||
|
add_executable(main main.cpp)
|
||||||
31
main.cpp
Normal file
31
main.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "mp.hpp"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
static void PrintInt(const char* name, const T& val)
|
||||||
|
{
|
||||||
|
std::cout << name << " = " << mp::ToHexString(val) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// mp::Int a{0xDEADBEEFDEADF154, 0x0123456789ABCDEF, 0x1111222233334444};
|
||||||
|
mp::Int<4> a{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF};
|
||||||
|
mp::Int<5> b{0x55};
|
||||||
|
|
||||||
|
PrintInt("a", a);
|
||||||
|
PrintInt("b", b);
|
||||||
|
|
||||||
|
auto c = a + b;
|
||||||
|
PrintInt("c", c);
|
||||||
|
|
||||||
|
a += mp::Int<1>{1};
|
||||||
|
PrintInt("a", a);
|
||||||
|
|
||||||
|
a -= mp::Int<1>{1};
|
||||||
|
PrintInt("a", a);
|
||||||
|
|
||||||
|
std::cout << mp::Int<16>::LAST_ELEM_MASK << std::endl;
|
||||||
|
|
||||||
|
}
|
||||||
4
mp.hpp
Normal file
4
mp.hpp
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mp_int.hpp"
|
||||||
|
#include "mp_lib.hpp"
|
||||||
137
mp_int.hpp
Normal file
137
mp_int.hpp
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "mp_math.hpp"
|
||||||
|
#include "mp_utils.hpp"
|
||||||
|
|
||||||
|
namespace mp
|
||||||
|
{
|
||||||
|
|
||||||
|
static constexpr size_t UNLIMITED = std::numeric_limits<size_t>().max();
|
||||||
|
|
||||||
|
// template<class TElem, size_t MaxSize, bool SelfContained>
|
||||||
|
// struct ElemContainerImpl
|
||||||
|
// {
|
||||||
|
// using type = std::vector<TElem>;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// template<class TElem, size_t MaxSize>
|
||||||
|
// struct ElemContainerImpl<TElem, MaxSize, true>
|
||||||
|
// {
|
||||||
|
// using type = std::array<TElem, MaxSize>;
|
||||||
|
// };
|
||||||
|
|
||||||
|
// template<class TElem, size_t MaxSize, bool SelfContained>
|
||||||
|
// using ElemContainer = typename ElemContainerImpl<TElem, MaxSize, SelfContained>::type;
|
||||||
|
|
||||||
|
template <class TElem, size_t MaxSize> class BasicInt;
|
||||||
|
|
||||||
|
template <class TA, class TB,
|
||||||
|
typename = typename std::enable_if<std::is_same_v<typename TA::ElementType, typename TB::ElementType>>>
|
||||||
|
using IntOpResultType = BasicInt<typename TA::ElementType, std::max(TA::MAX_SIZE, TB::MAX_SIZE)>;
|
||||||
|
|
||||||
|
template <class TElem, size_t MaxSize> class BasicInt
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using ElementType = TElem;
|
||||||
|
static constexpr size_t MAX_SIZE = MaxSize;
|
||||||
|
|
||||||
|
using ThisType = BasicInt<TElem, MaxSize>;
|
||||||
|
|
||||||
|
static constexpr size_t ELEMENT_BYTES = sizeof(ElementType);
|
||||||
|
static constexpr size_t MAX_ELEMS = utils::AlignUp(MaxSize, ELEMENT_BYTES) / ELEMENT_BYTES;
|
||||||
|
static constexpr ElementType LAST_ELEM_MASK = utils::GetNBytesMask<ElementType>(MAX_SIZE % ELEMENT_BYTES);
|
||||||
|
static constexpr ElementType ELEMENT_MAX = std::numeric_limits<ElementType>().max();
|
||||||
|
|
||||||
|
// static constexpr size_t LAST_ELEM_MASK = GetNBytesMask(3);
|
||||||
|
|
||||||
|
BasicInt(std::initializer_list<ElementType> init) : m_elems{init}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <class... TArgs> Int(TArgs&&... args)
|
||||||
|
// {
|
||||||
|
// (m_value.push_back(args), ...);
|
||||||
|
// }
|
||||||
|
|
||||||
|
size_t GetNumElements() const
|
||||||
|
{
|
||||||
|
return m_elems.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
TElem GetElement(size_t index) const
|
||||||
|
{
|
||||||
|
if (index >= m_elems.size())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_elems[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetElement(size_t index, TElem value)
|
||||||
|
{
|
||||||
|
if (index >= m_elems.size())
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_elems.resize(index + 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_elems[index] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TOp, class TR, class TRhs> void BinaryOp(TR& r, const TRhs& rhs) const
|
||||||
|
{
|
||||||
|
TOp::Op(r, *this, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TOp, class TRhs> IntOpResultType<ThisType, TRhs> ExtBinaryOp(const TRhs& rhs) const
|
||||||
|
{
|
||||||
|
IntOpResultType<ThisType, TRhs> result{};
|
||||||
|
BinaryOp<TOp>(result, rhs);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TOp, class TRhs> ThisType& CompoundBinaryOp(const TRhs& rhs)
|
||||||
|
{
|
||||||
|
BinaryOp<TOp>(*this, rhs);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TRhs> auto operator+(const TRhs& rhs) const
|
||||||
|
{
|
||||||
|
return ExtBinaryOp<Addition>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TRhs> auto operator+=(const TRhs& rhs)
|
||||||
|
{
|
||||||
|
return CompoundBinaryOp<Addition>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TRhs> auto operator-(const TRhs& rhs) const
|
||||||
|
{
|
||||||
|
return ExtBinaryOp<Subtraction>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TRhs> auto& operator-=(const TRhs& rhs)
|
||||||
|
{
|
||||||
|
return CompoundBinaryOp<Subtraction>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<ElementType> m_elems;
|
||||||
|
};
|
||||||
|
|
||||||
|
// using UnlimitedInt = Int<UNLIMITED>;
|
||||||
|
using DefaultElemType = size_t;
|
||||||
|
|
||||||
|
|
||||||
|
template <size_t MaxSize> using Int = BasicInt<DefaultElemType, MaxSize>;
|
||||||
|
using UnlimitedInt = Int<UNLIMITED>;
|
||||||
|
|
||||||
|
} // namespace mp
|
||||||
28
mp_lib.hpp
Normal file
28
mp_lib.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "mp_utils.hpp"
|
||||||
|
|
||||||
|
namespace mp
|
||||||
|
{
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline std::string ToHexString(const T& number)
|
||||||
|
{
|
||||||
|
constexpr size_t ELEMENT_DIGITS = T::ELEMENT_BYTES * 2;
|
||||||
|
|
||||||
|
std::string str(number.GetNumElements() * ELEMENT_DIGITS, '-');
|
||||||
|
|
||||||
|
for (size_t elem = 0; elem < number.GetNumElements(); ++elem)
|
||||||
|
{
|
||||||
|
auto v = number.GetElement(elem);
|
||||||
|
for (size_t digit = 0; digit < ELEMENT_DIGITS; ++digit)
|
||||||
|
{
|
||||||
|
str[str.size() - 1 - (elem * ELEMENT_DIGITS) - digit] = utils::HexDigit((v >> (digit * 4)) & 0xF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mp
|
||||||
73
mp_math.hpp
Normal file
73
mp_math.hpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace mp
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Addition
|
||||||
|
{
|
||||||
|
template <class TR, class TLhs, class TRhs> static void Op(TR& r, const TLhs& lhs, const TRhs& rhs)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<typename TR::ElementType, typename TLhs::ElementType>);
|
||||||
|
static_assert(std::is_same_v<typename TR::ElementType, typename TRhs::ElementType>);
|
||||||
|
|
||||||
|
using ElementType = TR::ElementType;
|
||||||
|
|
||||||
|
ElementType carry = 0;
|
||||||
|
size_t end = std::max(lhs.GetNumElements(), rhs.GetNumElements());
|
||||||
|
for (size_t i = 0; i < end; ++i)
|
||||||
|
{
|
||||||
|
ElementType a = lhs.GetElement(i);
|
||||||
|
ElementType b = rhs.GetElement(i);
|
||||||
|
|
||||||
|
ElementType c = carry + a;
|
||||||
|
carry = (c < a) ? 1 : 0;
|
||||||
|
c += b;
|
||||||
|
carry |= (c < b) ? 1 : 0;
|
||||||
|
|
||||||
|
r.SetElement(i, c);
|
||||||
|
|
||||||
|
// carry = (((a + carry) > (ELEMENT_MAX - b)) || (a > (ELEMENT_MAX - carry))) ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r.SetElement(end, carry);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Subtraction
|
||||||
|
{
|
||||||
|
template <class TR, class TLhs, class TRhs> static void Op(TR& r, const TLhs& lhs, const TRhs& rhs)
|
||||||
|
{
|
||||||
|
static_assert(std::is_same_v<typename TR::ElementType, typename TLhs::ElementType>);
|
||||||
|
static_assert(std::is_same_v<typename TR::ElementType, typename TRhs::ElementType>);
|
||||||
|
|
||||||
|
using ElementType = TR::ElementType;
|
||||||
|
|
||||||
|
ElementType borrow = 0;
|
||||||
|
size_t end = std::max(lhs.GetNumElements(), rhs.GetNumElements());
|
||||||
|
for (size_t i = 0; i < end; ++i)
|
||||||
|
{
|
||||||
|
ElementType a = lhs.GetElement(i);
|
||||||
|
ElementType b = rhs.GetElement(i);
|
||||||
|
|
||||||
|
ElementType c = a - b - borrow;
|
||||||
|
|
||||||
|
borrow = (a < b || (a - b) < borrow) ? 1 : 0;
|
||||||
|
|
||||||
|
r.SetElement(i, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (borrow > 0)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Subtraction result negative");
|
||||||
|
}
|
||||||
|
|
||||||
|
// r.SetElement(end, borrow);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mp
|
||||||
33
mp_utils.hpp
Normal file
33
mp_utils.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace mp::utils
|
||||||
|
{
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline constexpr T GetNBytesMask(size_t bytes)
|
||||||
|
{
|
||||||
|
T res = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < bytes; ++i)
|
||||||
|
{
|
||||||
|
res <<= 8;
|
||||||
|
res |= 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char HexDigit(uint8_t bits)
|
||||||
|
{
|
||||||
|
return bits > 9 ? 'a' + (bits - 10) : '0' + bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr size_t AlignUp(size_t value, size_t alignment)
|
||||||
|
{
|
||||||
|
return (value + alignment - 1) / alignment * alignment;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mp::utils
|
||||||
Loading…
x
Reference in New Issue
Block a user