diff --git a/Bignum.cpp b/Bignum.cpp index fbd0606..2b5fe11 100644 --- a/Bignum.cpp +++ b/Bignum.cpp @@ -133,16 +133,15 @@ Bignum operator+(const Bignum& left, const Bignum& right) { } const Bignum& Bignum::operator+=(const Bignum& other) { - if (other.sign == 0) { + if (other.sign == 0) return *this; - } Bignum this_abs = abs(); Bignum other_abs = other.abs(); - if (sign == other.sign) { + if (sign == other.sign) store = add(this_abs.store, other_abs.store); - } else { + else { if (this_abs > other_abs) store = subtract(this_abs.store, other_abs.store); else { @@ -161,16 +160,15 @@ Bignum operator-(const Bignum& left, const Bignum& right) { } const Bignum& Bignum::operator-=(const Bignum& other) { - if (other.sign == 0) { + if (other.sign == 0) return *this; - } Bignum this_abs = abs(); Bignum other_abs = other.abs(); - if (sign != other.sign) { + if (sign != other.sign) store = add(this_abs.store, other_abs.store); - } else { + else { if (this_abs > other_abs) store = subtract(this_abs.store, other_abs.store); else { @@ -189,7 +187,15 @@ Bignum operator>>(const Bignum& b, unsigned int n) { } const Bignum& Bignum::operator>>=(unsigned int n) { - store[0] >>= n; + uint32_t leading(0); + uint32_t trailing(0); + + for (std::vector::reverse_iterator i = store.rbegin(); i != store.rend(); ++i) { + trailing = *i & ((1 << n) - 1); + *i >>= n; + *i |= leading; + leading = trailing << (sizeof(uint32_t) * CHAR_BIT - n); + } reconcile_sign_of_zero(); diff --git a/Bignum.h b/Bignum.h index 6b45a2d..eea445f 100644 --- a/Bignum.h +++ b/Bignum.h @@ -17,11 +17,11 @@ class Bignum { const Bignum& operator+=(const Bignum& other); const Bignum& operator-=(const Bignum& other); const Bignum& operator>>=(unsigned int n); - bool equal(const Bignum& other) const; - bool less(const Bignum& other) const; Bignum operator-() const; Bignum abs() const; + bool equal(const Bignum& other) const; + bool less(const Bignum& other) const; int signum() const; friend std::ostream& operator<<(std::ostream& out, const Bignum& n); diff --git a/Bignum_unittest.cpp b/Bignum_unittest.cpp index 1b6d137..f32ff6c 100644 --- a/Bignum_unittest.cpp +++ b/Bignum_unittest.cpp @@ -464,7 +464,6 @@ TEST(BignumTest, RightShiftNegativeOneByOne) { ASSERT_EQ(Bignum(d(1, 0x0U), 0), n); } - TEST(BignumTest, RightShiftNegativeOneByOneWithAssignment) { Bignum m(d(1, 0x1U), -1); m >>= 1; @@ -485,3 +484,18 @@ TEST(BignumTest, RightShiftByFifteenWithAssignment) { ASSERT_EQ(Bignum(d(1, 0x00011312U), 1), m); } + +TEST(BignumTest, RightShiftMultipleDigits) { + Bignum m(d(3, 0x01234567U, 0x89ABCDEFU, 0x78784949U), 1); + Bignum n(m >> 7); + + ASSERT_EQ(Bignum(d(3, 0xDE02468AU, 0x9313579BU, 0x00F0F092U), 1), n); +} + +TEST(BignumTest, RightShiftMultipleDigitsWithAssignment) { + Bignum m(d(3, 0x00000034U, 0xC08905EAU, 0x4892BEADU), 1); + m >>= 23; + + ASSERT_EQ(Bignum(d(3, 0x120BD400U, 0x257D5B81U, 0x00000091U), 1), m); +} +