X-Git-Url: https://git.ucc.asn.au/?p=ipdf%2Fcode.git;a=blobdiff_plain;f=src%2Farbint.cpp;fp=src%2Farbint.cpp;h=3a1757b091ef911faa74546394866864516a1e5a;hp=4f8aff2cceea543c05740863e48ecef5c516ed9c;hb=eaebb5a37393bb02c3272d6259d60ce75d197b6f;hpb=6ad7fc3c833837713405b64a50e62dd128cb7a30 diff --git a/src/arbint.cpp b/src/arbint.cpp index 4f8aff2..3a1757b 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,47 @@ 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 +{ + //TODO: Optimise? + remainder = *this; + result = 0L; + while ((remainder -= div) > 0L) + { + //Debug("Remainder %c%s", remainder.SignChar(), remainder.DigitStr().c_str()); + //Debug("Result %c%s + 1", result.SignChar(), result.DigitStr().c_str()); + result += 1; + } + remainder += div; +} + Arbint & Arbint::operator+=(const Arbint & add) { if (m_sign == add.m_sign) @@ -130,7 +184,6 @@ Arbint & Arbint::SubBasic(const Arbint & sub) m_digits[i] = -m_digits[i]; } return *this; - return *this; } @@ -153,6 +206,15 @@ 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; @@ -164,7 +226,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 +237,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 << ',';