浏览代码

Splitting out an add for just one element to make division create fewer vectors.

Samuel Jaffe 8 年之前
父节点
当前提交
bf155c29d6
共有 1 个文件被更改,包括 20 次插入12 次删除
  1. 20 12
      src/bignum_helper.cpp

+ 20 - 12
src/bignum_helper.cpp

@@ -30,15 +30,9 @@ namespace math { namespace detail {
   }
 #undef IMPL_COMPARE
   
-  void add(data_type & rhs, data_type const & lhs, size_t offset) {
-    rhs.resize(std::max(rhs.size(), lhs.size()+offset)+1);
-    auto const lbnd = lhs.size(), ubnd = rhs.size() - 1;
-    // Add
-    for (size_t i = 0; i < lbnd; ++i) {
-      rhs[i+offset] += lhs[i];
-    }
-    // Carry
-    for (size_t i = 0; i < ubnd; ++i) {
+  void carry(data_type & rhs, size_t start) {
+    auto const ubnd = rhs.size() - 1;
+    for (size_t i = start; i < ubnd; ++i) {
       if (rhs[i] > MAX_SEG) {
         rhs[i] -= OVER_SEG;
         rhs[i+1] += 1;
@@ -47,6 +41,21 @@ namespace math { namespace detail {
     if (rhs[ubnd] == 0) { rhs.pop_back(); }
   }
   
+  void add(data_type & rhs, data_type const & lhs, size_t offset) {
+    rhs.resize(std::max(rhs.size(), lhs.size()+offset)+1);
+    auto const lbnd = lhs.size();
+    for (size_t i = 0; i < lbnd; ++i) {
+      rhs[i+offset] += lhs[i];
+    }
+    carry(rhs, offset);
+  }
+
+  void add(data_type & rhs, int32_t lhs, size_t offset) {
+    rhs.resize(std::max(rhs.size(), offset)+1);
+    rhs[offset] += lhs;
+    carry(rhs, offset);
+  }
+
   void subtract_nounderflow(data_type & rhs, data_type const & lhs, size_t offset) {
     size_t const rbnd = rhs.size(), lbnd = lhs.size();
     // Subtract
@@ -121,12 +130,11 @@ namespace math { namespace detail {
       auto const diff = std::max(1UL, digits(remainder) - dig) - 1;
       auto const shift = diff / SEG_DIGITS;
       auto const ipow = diff - (shift * SEG_DIGITS);
-      data_type step{shift10({1}, powers[ipow], 0)};
       data_type value{shift10(divisor, powers[ipow], 0)};
       do {
         subtract_nounderflow(remainder, value, shift);
-        add(accum, step, shift);
-      } while (compare(remainder, value) >= 0);
+        add(accum, powers[ipow], shift);
+      } while (compare(remainder, value) >= 0); // Up to 9 times
     } while (compare(remainder, divisor) >= 0);
     return accum;
   }