115 lines
2.6 KiB
C++
115 lines
2.6 KiB
C++
#pragma once
|
|
|
|
#include "utils.hpp"
|
|
#include "storage.hpp"
|
|
|
|
namespace mp
|
|
{
|
|
|
|
template <ElementSuitable TElem, size_t MaxBytes>
|
|
class BasicInt
|
|
{
|
|
public:
|
|
using ElementType = TElem;
|
|
constexpr static size_t MAX_BYTES = MaxBytes;
|
|
constexpr static size_t ELEMENT_BYTES = sizeof(TElem);
|
|
constexpr static size_t MAX_ELEMS = (MAX_BYTES + ELEMENT_BYTES - 1) / ELEMENT_BYTES;
|
|
constexpr static TElem LAST_ELEM_MASK = calculate_last_elem_mask<TElem, MAX_BYTES>();
|
|
|
|
BasicInt() = default;
|
|
|
|
BasicInt(std::initializer_list<ElementType> init)
|
|
{
|
|
for (size_t i = 0; i < init.size(); ++i)
|
|
{
|
|
set(i, *(init.begin() + i));
|
|
}
|
|
}
|
|
|
|
BasicInt(const BasicInt& other) = default;
|
|
BasicInt(BasicInt&& other) noexcept = default;
|
|
BasicInt& operator=(const BasicInt& other) = default;
|
|
BasicInt& operator=(BasicInt&& other) noexcept = default;
|
|
|
|
TElem& operator[](size_t index) { return m_data[index]; }
|
|
const TElem& operator[](size_t index) const { return m_data[index]; }
|
|
|
|
void resize(size_t new_size)
|
|
{
|
|
m_data.resize(new_size);
|
|
}
|
|
|
|
void zero() { m_data.clear(); }
|
|
|
|
bool try_set(size_t idx, TElem value)
|
|
{
|
|
if (idx >= m_data.size())
|
|
{
|
|
if (value == 0)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (idx >= MAX_ELEMS)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_data.resize(idx + 1);
|
|
}
|
|
|
|
m_data[idx] = value;
|
|
|
|
if (idx == MAX_ELEMS - 1 && value > LAST_ELEM_MASK)
|
|
{
|
|
m_data[idx] &= LAST_ELEM_MASK;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void set(size_t idx, TElem value)
|
|
{
|
|
if (!try_set(idx, value))
|
|
{
|
|
throw std::out_of_range("Value exceeds maximum size");
|
|
}
|
|
}
|
|
|
|
TElem get(size_t idx) const
|
|
{
|
|
if (idx >= m_data.size())
|
|
{
|
|
return TElem{0};
|
|
}
|
|
return m_data[idx];
|
|
}
|
|
|
|
void fix_leading_zeros()
|
|
{
|
|
size_t new_size = m_data.size();
|
|
while (new_size > 0 && m_data[new_size - 1] == TElem{0})
|
|
{
|
|
new_size--;
|
|
}
|
|
|
|
m_data.resize(new_size);
|
|
}
|
|
|
|
//std::span<TElem> data() { return m_data; }
|
|
|
|
size_t size_elems() const { return m_data.size(); }
|
|
|
|
bool negative() const { return m_negative; }
|
|
void set_negative(bool neg) { m_negative = neg; }
|
|
|
|
private:
|
|
Container<TElem, MAX_ELEMS> m_data;
|
|
bool m_negative = false;
|
|
};
|
|
|
|
template<size_t MaxBytes>
|
|
using Int = BasicInt<LongestElementSuitableType, MaxBytes>;
|
|
|
|
} // namespace mp
|