diff options
author | lloyd <[email protected]> | 2008-09-28 22:40:27 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-28 22:40:27 +0000 |
commit | c32a8e6c7ecf97fc9423e6a967ce3d98b0689404 (patch) | |
tree | d9d41c74dd0f99f43119ae355f461fae1f3bf32c /src/bigint/big_ops2.cpp | |
parent | 31204986023619c385d378e79a6511bb81ef7b78 (diff) |
Move all BigInt stuff into bigint/. Currently all asm modules are disabled;
configure.pl doesn't understand how to handle this yet (replace logic only
understands stuff in src, not how one module can replace another modules
src, or anything about prioritizing).
Move some hex and base64 stuff out of charset.cpp and into their
codec directories.
Diffstat (limited to 'src/bigint/big_ops2.cpp')
-rw-r--r-- | src/bigint/big_ops2.cpp | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/src/bigint/big_ops2.cpp b/src/bigint/big_ops2.cpp new file mode 100644 index 000000000..ef083f394 --- /dev/null +++ b/src/bigint/big_ops2.cpp @@ -0,0 +1,222 @@ +/************************************************* +* BigInt Assignment Operators Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include <botan/bigint.h> +#include <botan/mp_core.h> +#include <botan/bit_ops.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(get_reg().begin(), z.begin(), z.size()); + set_sign(y.sign()); + } + else if(relative_size == 0) + { + get_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(get_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()) + { + get_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) + { + get_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); + get_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) + get_reg()[0] = mod - remainder; + else + get_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); + } + +} |