aboutsummaryrefslogtreecommitdiffstats
path: root/src/big_ops2.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2006-05-18 18:33:19 +0000
committerlloyd <[email protected]>2006-05-18 18:33:19 +0000
commita2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch)
treead3d6c4fcc8dd0f403f8105598943616246fe172 /src/big_ops2.cpp
Initial checkin1.5.6
Diffstat (limited to 'src/big_ops2.cpp')
-rw-r--r--src/big_ops2.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/src/big_ops2.cpp b/src/big_ops2.cpp
new file mode 100644
index 000000000..eeb0c7771
--- /dev/null
+++ b/src/big_ops2.cpp
@@ -0,0 +1,224 @@
+/*************************************************
+* BigInt Assignment Operators Source File *
+* (C) 1999-2006 The Botan Project *
+*************************************************/
+
+#include <botan/bigint.h>
+#include <botan/numthry.h>
+#include <botan/mp_core.h>
+#include <botan/bit_ops.h>
+#include <botan/util.h>
+#include <algorithm>
+
+namespace Botan {
+
+/*************************************************
+* Addition Operator *
+*************************************************/
+BigInt& BigInt::operator+=(const BigInt& y)
+ {
+ const u32bit x_sw = sig_words(), y_sw = y.sig_words();
+
+ const u32bit reg_size = std::max(x_sw, y_sw) + 1;
+ grow_to(reg_size);
+
+ if((sign() == y.sign()))
+ bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ else
+ {
+ s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
+
+ if(relative_size < 0)
+ {
+ SecureVector<word> z(reg_size - 1);
+ bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw);
+ copy_mem(reg.begin(), z.begin(), z.size());
+ set_sign(y.sign());
+ }
+ else if(relative_size == 0)
+ {
+ reg.clear();
+ set_sign(Positive);
+ }
+ else if(relative_size > 0)
+ bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
+ }
+
+ return (*this);
+ }
+
+/*************************************************
+* Subtraction Operator *
+*************************************************/
+BigInt& BigInt::operator-=(const BigInt& y)
+ {
+ const u32bit x_sw = sig_words(), y_sw = y.sig_words();
+
+ s32bit relative_size = bigint_cmp(data(), x_sw, y.data(), y_sw);
+
+ const u32bit reg_size = std::max(x_sw, y_sw) + 1;
+ grow_to(reg_size);
+
+ if(relative_size < 0)
+ {
+ if(sign() == y.sign())
+ {
+ SecureVector<word> z(reg_size - 1);
+ bigint_sub3(z, y.data(), reg_size - 1, data(), x_sw);
+ copy_mem(reg.begin(), z.begin(), z.size());
+ }
+ else
+ bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+
+ set_sign(y.reverse_sign());
+ }
+ else if(relative_size == 0)
+ {
+ if(sign() == y.sign())
+ {
+ reg.clear();
+ set_sign(Positive);
+ }
+ else
+ bigint_shl1(get_reg(), x_sw, 0, 1);
+ }
+ else if(relative_size > 0)
+ {
+ if(sign() == y.sign())
+ bigint_sub2(get_reg(), x_sw, y.data(), y_sw);
+ else
+ bigint_add2(get_reg(), reg_size - 1, y.data(), y_sw);
+ }
+
+ return (*this);
+ }
+
+/*************************************************
+* Multiplication Operator *
+*************************************************/
+BigInt& BigInt::operator*=(const BigInt& y)
+ {
+ const u32bit x_sw = sig_words(), y_sw = y.sig_words();
+ set_sign((sign() == y.sign()) ? Positive : Negative);
+
+ if(x_sw == 0 || y_sw == 0)
+ {
+ reg.clear();
+ set_sign(Positive);
+ }
+ else if(x_sw == 1 && y_sw)
+ {
+ grow_to(y_sw + 2);
+ bigint_linmul3(get_reg(), y.data(), y_sw, word_at(0));
+ }
+ else if(y_sw == 1 && x_sw)
+ {
+ grow_to(x_sw + 2);
+ bigint_linmul2(get_reg(), x_sw, y.word_at(0));
+ }
+ else
+ {
+ grow_to(size() + y.size());
+
+ SecureVector<word> z(data(), x_sw);
+ SecureVector<word> workspace(size());
+
+ bigint_mul(get_reg(), size(), workspace,
+ z, z.size(), x_sw,
+ y.data(), y.size(), y_sw);
+ }
+
+ return (*this);
+ }
+
+/*************************************************
+* Division Operator *
+*************************************************/
+BigInt& BigInt::operator/=(const BigInt& y)
+ {
+ if(y.sig_words() == 1 && power_of_2(y.word_at(0)))
+ (*this) >>= (y.bits() - 1);
+ else
+ (*this) = (*this) / y;
+ return (*this);
+ }
+
+/*************************************************
+* Modulo Operator *
+*************************************************/
+BigInt& BigInt::operator%=(const BigInt& mod)
+ {
+ return (*this = (*this) % mod);
+ }
+
+/*************************************************
+* Modulo Operator *
+*************************************************/
+word BigInt::operator%=(word mod)
+ {
+ if(mod == 0)
+ throw BigInt::DivideByZero();
+ if(power_of_2(mod))
+ {
+ word result = (word_at(0) & (mod - 1));
+ clear();
+ grow_to(2);
+ reg[0] = result;
+ return result;
+ }
+
+ word remainder = 0;
+
+ for(u32bit j = sig_words(); j > 0; --j)
+ remainder = bigint_modop(remainder, word_at(j-1), mod);
+ clear();
+ grow_to(2);
+
+ if(remainder && sign() == BigInt::Negative)
+ reg[0] = mod - remainder;
+ else
+ reg[0] = remainder;
+
+ set_sign(BigInt::Positive);
+
+ return word_at(0);
+ }
+
+/*************************************************
+* Left Shift Operator *
+*************************************************/
+BigInt& BigInt::operator<<=(u32bit shift)
+ {
+ if(shift)
+ {
+ const u32bit shift_words = shift / MP_WORD_BITS,
+ shift_bits = shift % MP_WORD_BITS,
+ words = sig_words();
+
+ grow_to(words + shift_words + (shift_bits ? 1 : 0));
+ bigint_shl1(get_reg(), words, shift_words, shift_bits);
+ }
+
+ return (*this);
+ }
+
+/*************************************************
+* Right Shift Operator *
+*************************************************/
+BigInt& BigInt::operator>>=(u32bit shift)
+ {
+ if(shift)
+ {
+ const u32bit shift_words = shift / MP_WORD_BITS,
+ shift_bits = shift % MP_WORD_BITS;
+
+ bigint_shr1(get_reg(), sig_words(), shift_words, shift_bits);
+
+ if(is_zero())
+ set_sign(Positive);
+ }
+
+ return (*this);
+ }
+
+}