redid comparison without addition or subtraction due to realization that doing them relative could lead to cycle
This commit is contained in:
parent
01c0cbb0ec
commit
35efa772f0
1 changed files with 71 additions and 8 deletions
79
integer.cpp
79
integer.cpp
|
@ -2,6 +2,7 @@
|
|||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#define todo(msg) \
|
||||
|
@ -59,8 +60,68 @@ public:
|
|||
isNegative = rhs.isNegative;
|
||||
return *this;
|
||||
}
|
||||
void expand() {
|
||||
byte *new_buf = new byte[size + 1];
|
||||
std::copy(bytes, bytes + size, new_buf);
|
||||
size++;
|
||||
delete[] bytes;
|
||||
bytes = new_buf;
|
||||
}
|
||||
std::size_t true_size() const {
|
||||
std::size_t ret = size;
|
||||
if (bytes == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
while (bytes[ret - 1] == 0 && ret > 1) {
|
||||
ret--;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
friend bool abs_lt(Integer const &lhs, Integer const &rhs) {
|
||||
std::size_t true_lhs_size = lhs.true_size();
|
||||
std::size_t true_rhs_size = rhs.true_size();
|
||||
if (true_lhs_size != true_rhs_size) {
|
||||
return true_lhs_size < true_rhs_size;
|
||||
}
|
||||
if (true_lhs_size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto idx = true_lhs_size - 1;
|
||||
while (idx >= 0) {
|
||||
if (lhs.bytes[idx] != rhs.bytes[idx]) {
|
||||
return lhs.bytes[idx] < rhs.bytes[idx];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
friend Integer &operator+=(Integer &lhs, Integer const &rhs) {
|
||||
todo("+=");
|
||||
// TODO: negative numbers
|
||||
bool overflow = false;
|
||||
for (std::size_t i = 0; i < std::min(lhs.size, rhs.size); i++) {
|
||||
if (std::numeric_limits<byte>::max() - lhs.bytes[i] <= rhs.bytes[i]) {
|
||||
overflow = true;
|
||||
} else if (std::numeric_limits<byte>::max() - lhs.bytes[i] -
|
||||
(rhs.bytes[i]) <=
|
||||
(overflow ? 1 : 0)) {
|
||||
overflow = true;
|
||||
}
|
||||
lhs.bytes[i] += rhs.bytes[i] + (overflow ? 1 : 0);
|
||||
}
|
||||
if (overflow) {
|
||||
std::size_t idx = std::min(lhs.size, rhs.size);
|
||||
if (idx == lhs.size) {
|
||||
lhs.expand();
|
||||
}
|
||||
lhs.bytes[idx]++;
|
||||
if (lhs.bytes[idx] == 0) {
|
||||
idx++;
|
||||
if (idx == lhs.size) {
|
||||
lhs.expand();
|
||||
}
|
||||
lhs.bytes[idx]++;
|
||||
}
|
||||
}
|
||||
return lhs;
|
||||
}
|
||||
friend Integer &operator-=(Integer &lhs, Integer const &rhs) {
|
||||
|
@ -129,17 +190,19 @@ public:
|
|||
return ret;
|
||||
}
|
||||
friend bool operator<(Integer const &lhs, Integer const &rhs) {
|
||||
Integer tmp = (lhs - rhs);
|
||||
return tmp.isNegative && tmp != 0;
|
||||
if (lhs.isNegative != rhs.isNegative) {
|
||||
return lhs.isNegative;
|
||||
} else {
|
||||
return abs_lt(lhs, rhs);
|
||||
}
|
||||
}
|
||||
friend bool operator>(Integer const &lhs, Integer const &rhs) {
|
||||
Integer tmp = (rhs - lhs);
|
||||
return tmp.isNegative && tmp != 0;
|
||||
return rhs < lhs;
|
||||
}
|
||||
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;
|
||||
auto l_true = lhs.true_size();
|
||||
return l_true == rhs.true_size() &&
|
||||
std::equal(lhs.bytes, lhs.bytes + l_true, rhs.bytes);
|
||||
}
|
||||
|
||||
friend std::ostream &operator<<(std::ostream &lhs, Integer const &rhs) {
|
||||
|
|
Loading…
Reference in a new issue