aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/math/bigint/divide.cpp76
1 files changed, 37 insertions, 39 deletions
diff --git a/src/lib/math/bigint/divide.cpp b/src/lib/math/bigint/divide.cpp
index ed9a12112..98df233e3 100644
--- a/src/lib/math/bigint/divide.cpp
+++ b/src/lib/math/bigint/divide.cpp
@@ -164,6 +164,8 @@ void divide(const BigInt& x, const BigInt& y_arg, BigInt& q_out, BigInt& r_out)
const size_t y_words = y_arg.sig_words();
+ BOTAN_ASSERT_NOMSG(y_words > 0);
+
BigInt y = y_arg;
BigInt r = x;
@@ -173,62 +175,58 @@ void divide(const BigInt& x, const BigInt& y_arg, BigInt& q_out, BigInt& r_out)
r.set_sign(BigInt::Positive);
y.set_sign(BigInt::Positive);
- if(r.is_nonzero())
- {
- // Calculate shifts needed to normalize y with high bit set
- const size_t shifts = BOTAN_MP_WORD_BITS - high_bit(y.word_at(y_words-1));
-
- y <<= shifts;
- r <<= shifts;
-
- // we know y has not changed size, since we only shifted up to set high bit
- const size_t t = y_words - 1;
- const size_t n = std::max(t, r.sig_words() - 1); // r may have changed size however
+ // Calculate shifts needed to normalize y with high bit set
+ const size_t shifts = BOTAN_MP_WORD_BITS - high_bit(y.word_at(y_words-1));
- BOTAN_ASSERT_NOMSG(n >= t);
+ y <<= shifts;
+ r <<= shifts;
- q.grow_to(n - t + 1);
+ // we know y has not changed size, since we only shifted up to set high bit
+ const size_t t = y_words - 1;
+ const size_t n = std::max(y_words, r.sig_words()) - 1; // r may have changed size however
- word* q_words = q.mutable_data();
+ BOTAN_ASSERT_NOMSG(n >= t);
- BigInt shifted_y = y << (BOTAN_MP_WORD_BITS * (n-t));
+ q.grow_to(n - t + 1);
- // Set q_{n-t} to number of times r > shifted_y
- q_words[n-t] = r.reduce_below(shifted_y, ws);
+ word* q_words = q.mutable_data();
- const word y_t0 = y.word_at(t);
- const word y_t1 = y.word_at(t-1);
+ BigInt shifted_y = y << (BOTAN_MP_WORD_BITS * (n-t));
- for(size_t j = n; j != t; --j)
- {
- const word x_j0 = r.word_at(j);
- const word x_j1 = r.word_at(j-1);
- const word x_j2 = r.word_at(j-2);
+ // Set q_{n-t} to number of times r > shifted_y
+ q_words[n-t] = r.reduce_below(shifted_y, ws);
- word qjt = bigint_divop(x_j0, x_j1, y_t0);
+ const word y_t0 = y.word_at(t);
+ const word y_t1 = y.word_at(t-1);
- qjt = CT::Mask<word>::is_equal(x_j0, y_t0).select(MP_WORD_MAX, qjt);
+ for(size_t j = n; j != t; --j)
+ {
+ const word x_j0 = r.word_at(j);
+ const word x_j1 = r.word_at(j-1);
+ const word x_j2 = r.word_at(j-2);
- // Per HAC 14.23, this operation is required at most twice
- qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
- qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
- BOTAN_DEBUG_ASSERT(division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2) == false);
+ word qjt = bigint_divop(x_j0, x_j1, y_t0);
- shifted_y >>= BOTAN_MP_WORD_BITS;
- // Now shifted_y == y << (BOTAN_MP_WORD_BITS * (j-t-1))
+ qjt = CT::Mask<word>::is_equal(x_j0, y_t0).select(MP_WORD_MAX, qjt);
- r -= qjt * shifted_y;
+ // Per HAC 14.23, this operation is required at most twice
+ qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
+ qjt -= division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2);
+ BOTAN_DEBUG_ASSERT(division_check(qjt, y_t0, y_t1, x_j0, x_j1, x_j2) == false);
- // TODO this could be better
- qjt -= r.is_negative();
- r += static_cast<word>(r.is_negative()) * shifted_y;
+ shifted_y >>= BOTAN_MP_WORD_BITS;
+ // Now shifted_y == y << (BOTAN_MP_WORD_BITS * (j-t-1))
- q_words[j-t-1] = qjt;
- }
+ // TODO this sequence could be better
+ r -= qjt * shifted_y;
+ qjt -= r.is_negative();
+ r += static_cast<word>(r.is_negative()) * shifted_y;
- r >>= shifts;
+ q_words[j-t-1] = qjt;
}
+ r >>= shifts;
+
sign_fixup(x, y_arg, q, r);
r_out = r;