浏览代码

Making operators / and % take rhs by value, to optimize chained operations.

Samuel Jaffe 8 年之前
父节点
当前提交
ef70f4888e
共有 2 个文件被更改,包括 17 次插入22 次删除
  1. 2 2
      include/biginteger.h
  2. 15 20
      src/biginteger.cpp

+ 2 - 2
include/biginteger.h

@@ -32,8 +32,8 @@ namespace math {
     friend biginteger operator+(biginteger, biginteger const &);
     friend biginteger operator-(biginteger, biginteger const &);
     friend biginteger operator*(biginteger, biginteger const &);
-    friend biginteger operator/(biginteger const &, biginteger const &);
-    friend biginteger operator%(biginteger const &, biginteger const &);
+    friend biginteger operator/(biginteger, biginteger const &);
+    friend biginteger operator%(biginteger, biginteger const &);
     friend biginteger & operator+=(biginteger &, biginteger const &);
     friend biginteger & operator-=(biginteger &, biginteger const &);
     friend biginteger & operator*=(biginteger &, biginteger const &);

+ 15 - 20
src/biginteger.cpp

@@ -24,10 +24,6 @@ namespace detail {
   std::pair<data_type, data_type> divide(data_type remainder, data_type const & divisor);
 }
 
-static void swap(biginteger & rhs, biginteger && lhs) {
-  swap(rhs, lhs);
-}
-
 biginteger::biginteger()
 : biginteger(false, 0) {}
 
@@ -134,7 +130,17 @@ biginteger & math::operator*=(biginteger & rhs, biginteger const & lhs) {
 }
 
 biginteger & math::operator/=(biginteger & rhs, biginteger const & lhs) {
-  swap(rhs, rhs / lhs);
+  rhs.is_negative ^= lhs.is_negative;
+  if (lhs == biginteger::ZERO) { throw std::domain_error("cannot divide by 0"); }
+  else if (rhs == biginteger::ZERO) { rhs = biginteger::ZERO; }
+  else if (detail::compare(lhs.data, {1}) != 0) {
+    auto cmp = detail::compare(rhs.data, lhs.data);
+    if (cmp < 0) { rhs = biginteger::ZERO; }
+    else if (cmp == 0) { rhs.data = {1}; }
+    else {
+      rhs.data = detail::divide(rhs.data, lhs.data).first;
+    }
+  }
   return rhs;
 }
 
@@ -154,28 +160,17 @@ biginteger math::operator*(biginteger rhs, biginteger const & lhs) {
   return rhs *= lhs;
 }
 
-biginteger math::operator/(biginteger const & rhs, biginteger const & lhs) {
-  if (lhs == biginteger::ZERO) { throw std::domain_error("cannot divide by 0"); }
-  else if (rhs == biginteger::ZERO) { return biginteger::ZERO; }
-  else if (detail::compare(lhs.data, {1}) == 0) {
-    return {rhs.is_negative != lhs.is_negative, biginteger::data_type{rhs.data}};
-  } else {
-    auto cmp = detail::compare(rhs.data, lhs.data);
-    bool is_neg = rhs.is_negative != lhs.is_negative;
-    if (cmp < 0) { return biginteger::ZERO; }
-    else if (cmp == 0) { return {is_neg, {1}}; }
-    else { return {is_neg, detail::divide(rhs.data, lhs.data).first}; }
-  }
+biginteger math::operator/(biginteger rhs, biginteger const & lhs) {
+  return rhs /= lhs;
 }
 
-biginteger math::operator%(biginteger const & rhs, biginteger const & lhs) {
+biginteger math::operator%(biginteger rhs, biginteger const & lhs) {
   if (lhs == biginteger::ZERO) { throw std::domain_error("cannot divide by 0"); }
   else if (detail::compare(lhs.data, biginteger::ONE.data) == 0 ||
            rhs == biginteger::ZERO) { return biginteger::ZERO; }
   else {
     auto cmp = detail::compare(rhs.data, lhs.data);
-    if (cmp < 0) { return rhs; }
-    else if (cmp == 0) { return biginteger::ZERO; }
+    if (cmp == 0) { return biginteger::ZERO; }
     else {
       auto data = detail::divide(rhs.data, lhs.data).second;
       if (detail::compare(data, {0}) == 0) { return biginteger::ZERO; }