|
@@ -15,6 +15,7 @@ namespace detail {
|
|
|
int compare(data_type const & rhs, data_type const & lhs);
|
|
int compare(data_type const & rhs, data_type const & lhs);
|
|
|
data_type add(data_type const & rhs, data_type const & lhs);
|
|
data_type add(data_type const & rhs, data_type const & lhs);
|
|
|
data_type subtract_nounderflow(data_type const & rhs, data_type const & lhs);
|
|
data_type subtract_nounderflow(data_type const & rhs, data_type const & lhs);
|
|
|
|
|
+ data_type multiply(data_type const & rhs, data_type const & lhs);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void swap(biginteger & rhs, biginteger && lhs) {
|
|
static void swap(biginteger & rhs, biginteger && lhs) {
|
|
@@ -58,20 +59,18 @@ biginteger & operator-=(biginteger & rhs, biginteger const & lhs) {
|
|
|
return rhs;
|
|
return rhs;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-//biginteger & operator*=(biginteger & rhs, biginteger const & lhs) {
|
|
|
|
|
-// swap(rhs, rhs * lhs);
|
|
|
|
|
-// return rhs;
|
|
|
|
|
-//}
|
|
|
|
|
-//
|
|
|
|
|
|
|
+biginteger & operator*=(biginteger & rhs, biginteger const & lhs) {
|
|
|
|
|
+ swap(rhs, rhs * lhs);
|
|
|
|
|
+ return rhs;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
//biginteger & operator/=(biginteger & rhs, biginteger const & lhs) {
|
|
//biginteger & operator/=(biginteger & rhs, biginteger const & lhs) {
|
|
|
// swap(rhs, rhs / lhs);
|
|
// swap(rhs, rhs / lhs);
|
|
|
// return rhs;
|
|
// return rhs;
|
|
|
//}
|
|
//}
|
|
|
|
|
|
|
|
biginteger biginteger::operator-() const {
|
|
biginteger biginteger::operator-() const {
|
|
|
- biginteger tmp{*this};
|
|
|
|
|
- tmp.is_negative = !tmp.is_negative;
|
|
|
|
|
- return tmp;
|
|
|
|
|
|
|
+ return (*this) * NEGATIVE_ONE;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
biginteger math::operator+(biginteger const & rhs, biginteger const & lhs) {
|
|
biginteger math::operator+(biginteger const & rhs, biginteger const & lhs) {
|
|
@@ -82,7 +81,7 @@ biginteger math::operator+(biginteger const & rhs, biginteger const & lhs) {
|
|
|
} else {
|
|
} else {
|
|
|
auto cmp = detail::compare(rhs.data, lhs.data);
|
|
auto cmp = detail::compare(rhs.data, lhs.data);
|
|
|
if (cmp == 0) {
|
|
if (cmp == 0) {
|
|
|
- return 0;
|
|
|
|
|
|
|
+ return biginteger::ZERO;
|
|
|
} else if (cmp > 0) {
|
|
} else if (cmp > 0) {
|
|
|
return {rhs.is_negative, detail::subtract_nounderflow(rhs.data, lhs.data)};
|
|
return {rhs.is_negative, detail::subtract_nounderflow(rhs.data, lhs.data)};
|
|
|
} else {
|
|
} else {
|
|
@@ -99,7 +98,7 @@ biginteger math::operator-(biginteger const & rhs, biginteger const & lhs) {
|
|
|
} else {
|
|
} else {
|
|
|
auto cmp = detail::compare(rhs.data, lhs.data);
|
|
auto cmp = detail::compare(rhs.data, lhs.data);
|
|
|
if (cmp == 0) {
|
|
if (cmp == 0) {
|
|
|
- return 0;
|
|
|
|
|
|
|
+ return biginteger::ZERO;
|
|
|
} else if (cmp > 0) {
|
|
} else if (cmp > 0) {
|
|
|
return {rhs.is_negative, detail::subtract_nounderflow(rhs.data, lhs.data)};
|
|
return {rhs.is_negative, detail::subtract_nounderflow(rhs.data, lhs.data)};
|
|
|
} else {
|
|
} else {
|
|
@@ -108,6 +107,13 @@ biginteger math::operator-(biginteger const & rhs, biginteger const & lhs) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+biginteger math::operator*(biginteger const & rhs, biginteger const & lhs) {
|
|
|
|
|
+ if (rhs == biginteger::ZERO || lhs == biginteger::ZERO) {
|
|
|
|
|
+ return biginteger::ZERO;
|
|
|
|
|
+ }
|
|
|
|
|
+ return {rhs.is_negative != lhs.is_negative, detail::multiply(rhs.data, lhs.data)};
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
namespace detail {
|
|
namespace detail {
|
|
|
#define IMPL_COMPARE(expr) \
|
|
#define IMPL_COMPARE(expr) \
|
|
|
if (rhs expr < lhs expr) return -1; \
|
|
if (rhs expr < lhs expr) return -1; \
|
|
@@ -161,6 +167,35 @@ namespace detail {
|
|
|
if (rval[rbnd-1] == 0 && rbnd > 1) { rval.pop_back(); }
|
|
if (rval[rbnd-1] == 0 && rbnd > 1) { rval.pop_back(); }
|
|
|
return rval;
|
|
return rval;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ data_type multiply(data_type const & rhs, data_type const & lhs) {
|
|
|
|
|
+ if (compare(rhs, {1}) == 0) { return lhs; }
|
|
|
|
|
+ else if (compare(lhs, {1}) == 0) { return rhs; }
|
|
|
|
|
+ data_type::size_type const rbnd = rhs.size(), lbnd = lhs.size();
|
|
|
|
|
+ data_type::size_type const ubnd = rbnd + lbnd;
|
|
|
|
|
+ data_type rval(ubnd + 1);
|
|
|
|
|
+ // Multiply
|
|
|
|
|
+ for (data_type::size_type i = 0; i < rbnd; ++i) {
|
|
|
|
|
+ for (data_type::size_type j = 0; j < lbnd; ++j) {
|
|
|
|
|
+ // Max input 999,999,999
|
|
|
|
|
+ // Max output 999,999,998,000,000,001
|
|
|
|
|
+ int64_t product = static_cast<int64_t>(rhs[i]) * static_cast<int64_t>(lhs[j]);
|
|
|
|
|
+ int64_t overflow = product / biginteger::OVER_SEG;
|
|
|
|
|
+ rval[i+j] += static_cast<int32_t>(product - (overflow * biginteger::OVER_SEG));
|
|
|
|
|
+ rval[i+j+1] += static_cast<int32_t>(overflow);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // Carry
|
|
|
|
|
+ for (data_type::size_type i = 0; i < ubnd; ++i) {
|
|
|
|
|
+ if (rval[i] > biginteger::MAX_SEG) {
|
|
|
|
|
+ int32_t overflow = rval[i] / biginteger::OVER_SEG;
|
|
|
|
|
+ rval[i] -= (overflow * biginteger::OVER_SEG);
|
|
|
|
|
+ rval[i+1] += overflow;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (rval[ubnd] == 0) { rval.pop_back(); }
|
|
|
|
|
+ return rval;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool math::operator==(biginteger const & rhs, biginteger const & lhs) {
|
|
bool math::operator==(biginteger const & rhs, biginteger const & lhs) {
|