diff options
author | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-05-18 18:33:19 +0000 |
commit | a2c99d3270eb73ef2db5704fc54356c6b75096f8 (patch) | |
tree | ad3d6c4fcc8dd0f403f8105598943616246fe172 /src/big_ops2.cpp |
Initial checkin1.5.6
Diffstat (limited to 'src/big_ops2.cpp')
-rw-r--r-- | src/big_ops2.cpp | 224 |
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); + } + +} |