X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Farbint.cpp;h=748330fe38b55be76ded37e585dc2e224a5bdd1b;hp=4f8aff2cceea543c05740863e48ecef5c516ed9c;hb=e4c05570709db2718a983c27322942769eab4c86;hpb=ee5287fabfb214e8f7b483cde424108270525fd7 diff --git a/src/arbint.cpp b/src/arbint.cpp index 4f8aff2..748330f 100644 --- a/src/arbint.cpp +++ b/src/arbint.cpp @@ -1,3 +1,12 @@ +/** + * @file arbint.cpp + * @brief Arbitrary sized integer definitions + * @see arbint.h + * @see add_digits_asm.s + * @see sub_digits_asm.s + * @see mul_digits_asm.s + */ + #include "arbint.h" #include #include @@ -15,7 +24,7 @@ namespace IPDF Arbint::Arbint(digit_t i) : m_digits(1), m_sign(i < 0) { - m_digits[0] = i; + m_digits[0] = llabs(i); } Arbint::Arbint(unsigned n, digit_t d0, ...) : m_digits(n), m_sign(false) @@ -31,10 +40,14 @@ Arbint::Arbint(unsigned n, digit_t d0, ...) : m_digits(n), m_sign(false) va_end(ap); } -Arbint::Arbint(const Arbint & cpy) : m_digits(cpy.m_digits.size()), m_sign(cpy.m_sign) +Arbint::Arbint(const Arbint & cpy) : m_digits(cpy.m_digits), m_sign(cpy.m_sign) +{ + +} + +Arbint::Arbint(const vector & digits) : m_digits(digits), m_sign(false) { - memcpy(m_digits.data(), cpy.m_digits.data(), - sizeof(digit_t)*m_digits.size()); + } Arbint & Arbint::operator=(const Arbint & cpy) @@ -66,6 +79,63 @@ unsigned Arbint::Shrink() return result; } +Arbint & Arbint::operator*=(const Arbint & mul) +{ + vector new_digits(m_digits.size(), 0L); + new_digits.reserve(new_digits.size()+mul.m_digits.size()); + for (unsigned i = 0; i < mul.m_digits.size(); ++i) + { + vector step(m_digits.size()+i, 0L); + memcpy(step.data()+i, m_digits.data(), sizeof(digit_t)*m_digits.size()); + + digit_t overflow = mul_digits((digit_t*)step.data()+i, mul.m_digits[i], m_digits.size()); + if (overflow != 0L) + { + step.push_back(overflow); + } + new_digits.resize(max(new_digits.size(), step.size()), 0L); + digit_t carry = add_digits((digit_t*)new_digits.data(), step.data(), step.size()); + if (carry != 0L) + { + new_digits.push_back(carry); + } + } + + m_digits.swap(new_digits); + m_sign = !(m_sign == mul.m_sign); + return *this; +} + +void Arbint::Division(const Arbint & div, Arbint & result, Arbint & remainder) const +{ + if (div == Arbint(1L)) + { + result = *this; + remainder = 0L; + return; + } + if (div == *this) + { + result = 1L; + remainder = 0L; + return; + } + + + result = 0L; + remainder = *this; + Arbint next_rem(remainder); + while ((next_rem -= div) >= Arbint(0L)) + { + //Debug("%li - %li = %li", digit_t(remainder), digit_t(div), digit_t(next_rem)); + //Debug("Sign is %d", next_rem.m_sign); + remainder = next_rem; + result += 1L; + } + + +} + Arbint & Arbint::operator+=(const Arbint & add) { if (m_sign == add.m_sign) @@ -130,7 +200,6 @@ Arbint & Arbint::SubBasic(const Arbint & sub) m_digits[i] = -m_digits[i]; } return *this; - return *this; } @@ -153,9 +222,19 @@ string Arbint::Str(const string & base) const return s; } +bool Arbint::IsZero() const +{ + for (unsigned i = m_digits.size()-1; i > 0; --i) + { + if (m_digits[i] != 0L) return false; + } + return (m_digits[0] == 0L); +} + bool Arbint::operator==(const Arbint & equ) const { - if (m_sign != equ.m_sign) return false; + if (m_sign != equ.m_sign) + return false; unsigned min_size = m_digits.size(); const Arbint * larger = &equ; if (m_digits.size() > equ.m_digits.size()) @@ -164,7 +243,7 @@ bool Arbint::operator==(const Arbint & equ) const larger = this; } - if (memcmp(m_digits.data(), equ.m_digits.data(), min_size) != 0) + if (memcmp(m_digits.data(), equ.m_digits.data(), sizeof(digit_t)*min_size) != 0) return false; for (unsigned i = min_size; i < larger->m_digits.size(); ++i) @@ -175,10 +254,17 @@ bool Arbint::operator==(const Arbint & equ) const return true; } +bool Arbint::operator<(const Arbint & less) const +{ + Arbint cpy(*this); + cpy -= less; + return (cpy.m_sign && !cpy.IsZero()); +} + string Arbint::DigitStr() const { stringstream ss(""); - //ss << std::hex << std::setfill('0'); + ss << std::hex << std::setfill('0'); for (unsigned i = 0; i < m_digits.size(); ++i) { if (i != 0) ss << ',';