#include #include #include "number.h" number::number(std::uint32_t n): _operands{n} { } /* Type Conversion {{{ */ std::string number::to_hex_string() const { if (_operands.empty()) { return std::string("0x0"); } std::ostringstream ss; ss << "0x" << std::hex; for (auto it = _operands.crbegin(); it != _operands.crend(); ++it) { ss << *it; /* If more operands are present, successive ones must be padded. */ ss << std::setfill('0'); ss << std::setw(8); } return ss.str(); } std::string number::to_dec_string() const { if (_operands.empty()) { return std::string("0"); } std::ostringstream ss; ss << std::dec; if (_operands.size() == 1) { ss << _operands.front(); } else { /* TODO */ ss << "[Not implemented]"; } return ss.str(); } std::uint32_t number::to_uint32() const { if (*this > UINT32_MAX) { throw std::out_of_range("> UINT32_MAX"); } return (*this == 0) ? 0 : _operands.front(); } /* }}} */ /* Operations {{{ */ number number::operator+(const number &n) const { number result; auto it = _operands.cbegin(); auto it_n = n._operands.cbegin(); bool carry = false; while (it != _operands.cend() || it_n != n._operands.cend()) { const auto n1 = (it != _operands.cend()) ? *it++ : 0; const auto n2 = (it_n != n._operands.cend()) ? *it_n++ : 0; result._operands.push_back(n1 + n2 + (carry ? 1 : 0)); if (carry && (n1 == UINT32_MAX)) { carry = true; } else { carry = ((UINT32_MAX - n1 - (carry ? 1 : 0)) < n2); } } if (carry) { result._operands.push_back(1); } return result; } number number::operator*(const number &n) const { number result; for (number i; i < n; ++i) { result += *this; } return result; } number number::operator<<(std::uint32_t shift) const { if (shift > 32) { /* TODO */ throw std::out_of_range("> 32"); } number result(*this); std::uint32_t carry = 0; for (auto &operand: result._operands) { std::uint32_t tmp = ((1ull * operand) << shift) + carry; carry = ((1ull * operand) >> (32 - shift)); operand = tmp; } if (carry) { result._operands.push_back(carry); } return result; } /* }}} */ /* Comparison operators {{{ */ bool number::operator<(const number &n) const { const auto size = this->_operands.size(); if (size < n._operands.size()) { return true; } if (size > n._operands.size()) { return false; } /* Because first item is the least significant. */ auto l1(this->_operands); auto l2(n._operands); l1.reverse(); l2.reverse(); return l1 < l2; } bool number::operator>(const number &n) const { return n.operator<(*this); } bool number::operator<=(const number &n) const { return operator<(n) || operator==(n); } bool number::operator>=(const number &n) const { return operator>(n) || operator==(n); } bool number::operator==(const number &n) const { return _operands == n._operands; } bool number::operator!=(const number &n) const { return _operands != n._operands; } /* }}} */ /* Assignment operators {{{ */ number & number::operator+=(const number &n) { *this = *this + n; return *this; } number & number::operator<<=(std::uint32_t n) { *this = *this << n; return *this; } number & number::operator++() { *this = *this + 1; return *this; } /* }}} */ std::ostream & operator<<(std::ostream &os, const number &n) { return os << n.to_hex_string(); }