|
|
@@ -14,6 +14,13 @@
|
|
|
|
|
|
using namespace math;
|
|
|
|
|
|
+static void read(int32_t & dst, char const * & str, size_t len) {
|
|
|
+ char seg[biginteger::SEG_DIGITS+1] = "";
|
|
|
+ strncpy(seg, str, len);
|
|
|
+ dst = atoi(seg);
|
|
|
+ str += len;
|
|
|
+}
|
|
|
+
|
|
|
biginteger::biginteger()
|
|
|
: biginteger(false, 0) {}
|
|
|
|
|
|
@@ -23,19 +30,11 @@ biginteger::biginteger(char const * number)
|
|
|
auto len = strlen(number);
|
|
|
auto elems = len/SEG_DIGITS;
|
|
|
data.resize(elems);
|
|
|
- {
|
|
|
- auto small = len-(elems*SEG_DIGITS);
|
|
|
- if (small > 0) {
|
|
|
- char seg[SEG_DIGITS+1] = "";
|
|
|
- strncpy(seg, number, small);
|
|
|
- data.push_back(atoi(seg));
|
|
|
- number += small;
|
|
|
- }
|
|
|
+ if (auto small = len-(elems*SEG_DIGITS)) {
|
|
|
+ read(*data.insert(data.end(), 0), number, small);
|
|
|
}
|
|
|
- for (data_type::size_type idx = elems; idx > 0; --idx, number += SEG_DIGITS) {
|
|
|
- char seg[SEG_DIGITS+1] = "";
|
|
|
- strncpy(seg, number, SEG_DIGITS);
|
|
|
- data[idx-1] = atoi(seg);
|
|
|
+ for (data_type::size_type idx = elems; idx > 0; --idx) {
|
|
|
+ read(data[idx-1], number, SEG_DIGITS);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -48,22 +47,27 @@ is_negative(neg) {
|
|
|
} while ((value = next) > 0);
|
|
|
}
|
|
|
|
|
|
+void biginteger::subtract_impl(biginteger const & lhs, bool is_sub) {
|
|
|
+ auto cmp = detail::compare(data, lhs.data);
|
|
|
+ if (cmp == 0) {
|
|
|
+ *this = biginteger::ZERO;
|
|
|
+ } else if (cmp > 0) {
|
|
|
+ detail::subtract_nounderflow(data, lhs.data);
|
|
|
+ } else {
|
|
|
+ data_type tmp{lhs.data};
|
|
|
+ is_negative = lhs.is_negative ^ is_sub;
|
|
|
+ swap(data, tmp);
|
|
|
+ detail::subtract_nounderflow(data, tmp);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
biginteger & math::operator+=(biginteger & rhs, biginteger const & lhs) {
|
|
|
if (lhs == biginteger::ZERO) { return rhs; }
|
|
|
else if (rhs == biginteger::ZERO) { rhs=lhs; }
|
|
|
else if (rhs.is_negative == lhs.is_negative) {
|
|
|
detail::add(rhs.data, lhs.data);
|
|
|
} else {
|
|
|
- auto cmp = detail::compare(rhs.data, lhs.data);
|
|
|
- if (cmp == 0) {
|
|
|
- rhs = biginteger::ZERO;
|
|
|
- } else if (cmp > 0) {
|
|
|
- detail::subtract_nounderflow(rhs.data, lhs.data);
|
|
|
- } else {
|
|
|
- biginteger tmp{lhs};
|
|
|
- swap(rhs, tmp);
|
|
|
- detail::subtract_nounderflow(rhs.data, tmp.data);
|
|
|
- }
|
|
|
+ rhs.subtract_impl(lhs, false);
|
|
|
}
|
|
|
return rhs;
|
|
|
}
|
|
|
@@ -74,16 +78,7 @@ biginteger & math::operator-=(biginteger & rhs, biginteger const & lhs) {
|
|
|
if (rhs.is_negative != lhs.is_negative) {
|
|
|
detail::add(rhs.data, lhs.data);
|
|
|
} else {
|
|
|
- auto cmp = detail::compare(rhs.data, lhs.data);
|
|
|
- if (cmp == 0) {
|
|
|
- rhs = biginteger::ZERO;
|
|
|
- } else if (cmp > 0) {
|
|
|
- detail::subtract_nounderflow(rhs.data, lhs.data);
|
|
|
- } else {
|
|
|
- biginteger tmp{-lhs};
|
|
|
- swap(rhs, tmp);
|
|
|
- detail::subtract_nounderflow(rhs.data, tmp.data);;
|
|
|
- }
|
|
|
+ rhs.subtract_impl(lhs, true);
|
|
|
}
|
|
|
return rhs;
|
|
|
}
|