浏览代码

Make modulo happen 'in-place'.
Remove unneeded private constructor.

Samuel Jaffe 8 年之前
父节点
当前提交
09324c512f
共有 3 个文件被更改,包括 16 次插入16 次删除
  1. 0 1
      include/biginteger.h
  2. 11 15
      src/biginteger.cpp
  3. 5 0
      test/biginteger.t.h

+ 0 - 1
include/biginteger.h

@@ -49,7 +49,6 @@ namespace math {
     friend bool operator> (biginteger const &, biginteger const &);
   private:
     biginteger(bool, uint64_t);
-    biginteger(bool, data_type &&);
     friend void swap(biginteger & rhs, biginteger & lhs) {
       using std::swap;
       swap(rhs.is_negative, lhs.is_negative);

+ 11 - 15
src/biginteger.cpp

@@ -21,7 +21,7 @@ namespace detail {
   void add(data_type & rhs, data_type const & lhs);
   void subtract_nounderflow(data_type & rhs, data_type const & lhs);
   void multiply(data_type & rhs, data_type const & lhs);
-  std::pair<data_type, data_type> divide(data_type remainder, data_type const & divisor);
+  data_type divide(data_type & remainder, data_type const & divisor);
 }
 
 biginteger::biginteger()
@@ -71,9 +71,6 @@ is_negative(neg) {
   } while ((value = next) > 0);
 }
 
-biginteger::biginteger(bool neg, data_type && dt) :
-is_negative(neg), data(std::move(dt)) {}
-
 biginteger & math::operator+=(biginteger & rhs, biginteger const & lhs) {
   if (lhs == biginteger::ZERO) { return rhs; }
   else if (rhs == biginteger::ZERO) { rhs=lhs; }
@@ -133,13 +130,11 @@ biginteger & math::operator/=(biginteger & rhs, biginteger const & 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) {
+  else if (detail::compare(lhs.data, biginteger::ONE.data) != 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;
-    }
+    else { rhs.data = detail::divide(rhs.data, lhs.data); }
   }
   return rhs;
 }
@@ -172,14 +167,15 @@ biginteger math::operator%(biginteger rhs, biginteger const & lhs) {
     auto cmp = detail::compare(rhs.data, lhs.data);
     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; }
+      detail::divide(rhs.data, lhs.data);
+      if (detail::compare(rhs.data, biginteger::ZERO.data) == 0) { return biginteger::ZERO; }
       else if (rhs.is_negative != lhs.is_negative) {
+        rhs.is_negative = lhs.is_negative;
         auto tmp = lhs.data;
-        swap(data, tmp);
-        detail::subtract_nounderflow(data, tmp);
+        swap(rhs.data, tmp);
+        detail::subtract_nounderflow(rhs.data, tmp);
       }
-      return {lhs.is_negative, std::move(data)};
+      return rhs;
     }
   }
 }
@@ -282,7 +278,7 @@ namespace detail {
   
   int32_t powers[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
   
-  std::pair<data_type, data_type> divide(data_type remainder, data_type const & divisor) {
+  data_type divide(data_type & remainder, data_type const & divisor) {
     data_type accum{0};
     auto const dig = digits(divisor);
     do {
@@ -296,7 +292,7 @@ namespace detail {
         add(accum, step);
       } while (detail::compare(remainder, value) >= 0);
     } while (detail::compare(remainder, divisor) >= 0);
-    return { std::move(accum), std::move(remainder) };
+    return accum;
   }
 }
 

+ 5 - 0
test/biginteger.t.h

@@ -13,6 +13,11 @@
 
 class biginteger_TestSuite : public CxxTest::TestSuite {
 public:
+  void testConstructFromStringIsSameValueAsFromInt() {
+    using bi = math::biginteger;
+    TS_ASSERT_EQUALS(bi("1000000"), bi(1000000));
+  }
+  
   void testAddPastBounds() {
     math::biginteger bi{999999999ULL};
     TS_ASSERT_EQUALS((bi+1).to_string(), "1000000000");