138 lines
3.4 KiB
C++
138 lines
3.4 KiB
C++
#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
|