#include #include #include #include #include #include #define todo(msg) \ std::cerr << msg << std::endl; \ assert(false); // TODO: try to maximize rvalue usage to reuse resources // "Use rvalue references to reuse the resources of temporaries when possible, // particularly for binary operands." class Integer { using byte = unsigned char; // bytes are litle endian byte *bytes; bool isNegative; std::size_t size; public: Integer(long long num = 0) : bytes{new byte[sizeof(long long)]}, isNegative{num < 0}, size{sizeof(long long)} { for (std::size_t i = 0; i < size; i++) { bytes[i] = num % 256; num /= 256; } } Integer(Integer const &rhs) : bytes{new byte[rhs.size]}, isNegative{rhs.isNegative}, size{rhs.size} { for (std::size_t i = 0; i < size; i++) { bytes[i] = rhs.bytes[i]; } } Integer(Integer &&rhs) : bytes{rhs.bytes}, isNegative{rhs.isNegative}, size{rhs.size} { rhs.bytes = nullptr; } ~Integer() { delete[] bytes; bytes = nullptr; } Integer &operator=(Integer const &rhs) { delete[] bytes; bytes = new byte[rhs.size]; size = rhs.size; isNegative = rhs.isNegative; for (std::size_t i = 0; i < size; i++) { bytes[i] = rhs.bytes[i]; } return *this; } Integer &operator=(Integer &&rhs) { bytes = rhs.bytes; rhs.bytes = nullptr; size = rhs.size; isNegative = rhs.isNegative; return *this; } friend Integer &operator+=(Integer &lhs, Integer const &rhs) { todo("+="); return lhs; } friend Integer &operator-=(Integer &lhs, Integer const &rhs) { todo("-="); return lhs; } friend Integer &operator*=(Integer &lhs, Integer const &rhs) { Integer tmp = std::move(lhs); Integer tmp_r = rhs; lhs = 0; while (tmp_r > 0) { lhs += tmp; tmp_r -= 1; } return lhs; } friend Integer &operator/=(Integer &lhs, Integer const &rhs) { Integer tmp = std::move(lhs); lhs = 0; while (tmp > rhs) { tmp -= rhs; lhs += 1; } return lhs; } friend Integer &operator%=(Integer &lhs, Integer const &rhs) { while (lhs > rhs) { lhs -= rhs; } return lhs; } friend Integer operator+(Integer const &lhs, Integer const &rhs) { Integer ret{lhs}; ret += rhs; return ret; } friend Integer operator-(Integer const &lhs, Integer const &rhs) { Integer ret{lhs}; ret -= rhs; return ret; } friend Integer operator*(Integer const &lhs, Integer const &rhs) { Integer ret{lhs}; ret *= rhs; return ret; } friend Integer operator/(Integer const &lhs, Integer const &rhs) { Integer ret{lhs}; ret /= rhs; return ret; } friend Integer operator%(Integer const &lhs, Integer const &rhs) { Integer ret{lhs}; ret %= rhs; return ret; } friend Integer operator%(Integer const &lhs, byte rhs) { if (lhs.size == 0 || lhs.bytes == nullptr) { return 0; } return lhs.bytes[0] % rhs; } friend Integer operator-(Integer const &val) { Integer ret = val; ret.isNegative = !ret.isNegative; return ret; } friend bool operator<(Integer const &lhs, Integer const &rhs) { Integer tmp = (lhs - rhs); return tmp.isNegative && tmp != 0; } friend bool operator>(Integer const &lhs, Integer const &rhs) { Integer tmp = (rhs - lhs); return tmp.isNegative && tmp != 0; } friend bool operator==(Integer const &lhs, Integer const &rhs) { todo("need to actually do a check for the case that one or both of them is " "0"); return (rhs - lhs) == 0; } friend std::ostream &operator<<(std::ostream &lhs, Integer const &rhs) { if (rhs == 0) { lhs << 0; return lhs; } Integer discard = rhs; std::stringstream to_output{}; while (discard != 0) { to_output << discard % 10; discard /= 10; } std::string out; to_output >> out; std::reverse(out.begin(), out.end()); lhs << out; return lhs; } explicit operator unsigned long() { unsigned long ret = 0; for (std::size_t i = 0; i < std::min(size, sizeof(unsigned long)); i++) { ret += (static_cast(this->bytes[i]) << (i * 8)); } return ret; } }; int main(void) { for (std::size_t i = 0; i <= 8584148901; i++) { unsigned long n = i * i; n = i + i; n = i - i; n = i / i; } }