/*************************************************
* BigInt Assignment Operators Source File *
* (C) 1999-2007 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);
}
}
syntax highlighted by Code2HTML, v. 0.9.1