digit_t is now unsigned, asm division for 1 digit
[ipdf/code.git] / src / arbint.cpp
index c24eb8b..696dcd0 100644 (file)
 #include <sstream>
 #include <cstdarg>
 
+#include "rational.h"
+
 using namespace std;
 
 namespace IPDF
 {
+       
+/** Absolute value hackery **/
+template <> Arbint Tabs(const Arbint & a)
+{
+       //Debug("Called");
+       return a.Abs();
+}
+
 
 Arbint::Arbint(int64_t i) : m_digits(1), m_sign(i < 0)
 {
@@ -52,20 +62,14 @@ Arbint::Arbint(const vector<digit_t> & digits) : m_digits(digits), m_sign(false)
 
 Arbint & Arbint::operator=(const Arbint & cpy)
 {
-       memmove(m_digits.data(), cpy.m_digits.data(), 
-               sizeof(digit_t)*min(m_digits.size(), cpy.m_digits.size()));
-       if (cpy.m_digits.size() > m_digits.size())
-       {
-               unsigned old_size = m_digits.size();
-               m_digits.resize(cpy.m_digits.size());
-               memset(m_digits.data()+old_size, 0, sizeof(digit_t)*m_digits.size()-old_size);
-       }
+       m_digits = cpy.m_digits;
+       m_sign = cpy.m_sign;
        return *this;
 }
 
 void Arbint::Zero()
 {
-       memset(m_digits.data(), 0, sizeof(digit_t)*m_digits.size());
+       m_digits.resize(1, 0L);
 }
 
 unsigned Arbint::Shrink()
@@ -110,6 +114,18 @@ void Arbint::Division(const Arbint & div, Arbint & result, Arbint & remainder) c
 {
        remainder = 0;
        result = 0;
+       if (div.IsZero())
+       {
+               result = *this;
+               return;
+       }
+       else if (div.m_digits.size() == 1)
+       {
+               result.m_digits.resize(m_digits.size(), 0L);
+               remainder = Arbint(div_digits((digit_t*)&m_digits[0], div.m_digits[0], m_digits.size(), result.m_digits.data()));
+               result.m_sign = !(m_sign == div.m_sign);
+               return;
+       }
        for (int i = 8*sizeof(digit_t)*m_digits.size(); i >= 0; --i)
        {
                remainder <<= 1;
@@ -123,6 +139,7 @@ void Arbint::Division(const Arbint & div, Arbint & result, Arbint & remainder) c
                        result.BitSet(i);
                }
        }
+       result.m_sign = !(m_sign == div.m_sign);
 }
 
 Arbint & Arbint::operator+=(const Arbint & add)
@@ -186,7 +203,7 @@ Arbint & Arbint::SubBasic(const Arbint & sub)
        {
                m_sign = !m_sign;
                for (unsigned i = 0; i < m_digits.size(); ++i)
-                       m_digits[i] = -m_digits[i];
+                       m_digits[i] = (~m_digits[i]) + 1;
        }
        return *this;
 }
@@ -261,7 +278,7 @@ Arbint & Arbint::operator>>=(unsigned amount)
        
        if (whole >= old_size)
        {
-               m_digits.resize(1);
+               m_digits.resize(1,0L);
                m_digits[0] = 0L;
                return *this;
        }
@@ -325,7 +342,7 @@ Arbint & Arbint::operator<<=(unsigned amount)
 bool Arbint::GetBit(unsigned i) const
 {
        unsigned digit = i/(8*sizeof(digit_t));
-       if (digit > m_digits.size())
+       if (digit >= m_digits.size())
                return false;
                
        i = i % (8*sizeof(digit_t));
@@ -337,7 +354,7 @@ bool Arbint::GetBit(unsigned i) const
 void Arbint::BitClear(unsigned i)
 {
        unsigned digit = i/(8*sizeof(digit_t));
-       if (digit > m_digits.size())
+       if (digit >= m_digits.size())
                return;
        i = i % (8*sizeof(digit_t));
        m_digits[digit] &= ~(1L << i);  
@@ -346,7 +363,7 @@ void Arbint::BitClear(unsigned i)
 void Arbint::BitSet(unsigned i)
 {
        unsigned digit = i/(8*sizeof(digit_t));
-       if (digit > m_digits.size())
+       if (digit >= m_digits.size())
        {
                m_digits.resize(digit+1, 0L);
        }

UCC git Repository :: git.ucc.asn.au