unsigned Arbint::Shrink()
{
+
if (m_digits.size() <= 1)
return 0;
- unsigned i;
- for (i = m_digits.size()-1; (i > 0 && m_digits[i] != 0L); --i);
- unsigned result = m_digits.size() - i;
- m_digits.resize(i);
- return result;
+
+ unsigned shrunk = 0;
+ while (m_digits.size() > 1 && m_digits[m_digits.size()-1] == 0L)
+ {
+ Debug("Shrink 1");
+ m_digits.pop_back();
+ shrunk++;
+ }
+ return shrunk;
+}
+
+void Arbint::GrowDigit(digit_t new_msd)
+{
+ static unsigned total_grows = 0;
+ m_digits.push_back(new_msd);
+ Warn("Arbint grows digit (%.16lx), this->m_digits.size() = %u, total grown = %u", new_msd, m_digits.size(), ++total_grows);
+ if (total_grows++ > 10000)
+ {
+ Fatal("Too many GrowDigit calls!");
+ }
}
Arbint & Arbint::operator*=(const Arbint & mul)
digit_t carry = add_digits((digit_t*)new_digits.data(), step.data(), step.size());
if (carry != 0L)
{
- new_digits.push_back(carry);
+ Debug("Add carry");
+ GrowDigit(carry);
}
}
m_digits.swap(new_digits);
m_sign = !(m_sign == mul.m_sign);
+ Shrink();
return *this;
}
result = *this;
return;
}
+ /* may break things (even more that is)
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;
}
}
result.m_sign = !(m_sign == div.m_sign);
+ result.Shrink();
}
Arbint & Arbint::operator+=(const Arbint & add)
// a + -b == a - b
SubBasic(add);
}
+ Shrink();
return *this;
}
Arbint & Arbint::AddBasic(const Arbint & add)
{
- if (add.m_digits.size() >= m_digits.size())
+ while (m_digits.size() < add.m_digits.size())
{
- m_digits.resize(add.m_digits.size()+1,0L);
+
+ Debug("Size is %u, add's size is %u", m_digits.size(), add.m_digits.size());
+ GrowDigit(0L);
}
+ //m_digits.resize(add.m_digits.size()+1,0L);
digit_t carry = add_digits((digit_t*)m_digits.data(),
(digit_t*)add.m_digits.data(), add.m_digits.size());
if (carry != 0L)
- m_digits[m_digits.size()-1] = carry;
- else if (m_digits.back() == 0L)
- m_digits.resize(m_digits.size()-1);
+ {
+ Debug("Grow carry %lu", carry);
+ GrowDigit(carry);
+ }
+ Shrink();
return *this;
}
Arbint & Arbint::SubBasic(const Arbint & sub)
{
- if (sub.m_digits.size() >= m_digits.size())
+ bool fith = false;
+ while (sub.m_digits.size() > m_digits.size())
{
- m_digits.resize(sub.m_digits.size(),0L);
+ fith = true;
+ GrowDigit(0L);
}
+ if (fith)
+ {
+ Debug("START sub was %c%s, I am %c%s", SignChar(), sub.DigitStr().c_str(), SignChar(), DigitStr().c_str());
+ }
+
digit_t borrow = sub_digits((digit_t*)m_digits.data(),
(digit_t*)sub.m_digits.data(), sub.m_digits.size());
+ if (fith)
+ {
+ Debug("SUB_DIGITS -> sub was %c%s, I am %c%s", SignChar(), sub.DigitStr().c_str(), SignChar(), DigitStr().c_str());
+ }
//TODO: Write ASM to do this bit?
if (borrow != 0L)
m_sign = !m_sign;
for (unsigned i = 0; i < m_digits.size(); ++i)
m_digits[i] = (~m_digits[i]);
- std::vector<digit_t> one_digits(m_digits.size(), 0L);
- one_digits[0] = 1;
+ vector<digit_t> one_digits(m_digits.size(), 0L);
+ one_digits[0] = 1L;
add_digits((digit_t*)m_digits.data(), (digit_t*)one_digits.data(), m_digits.size());
}
+ if (fith)
+ {
+ Debug("END -> sub was %c%s, I am %c%s", sub.SignChar(), sub.DigitStr().c_str(), SignChar(), DigitStr().c_str());
+ }
+ Shrink();
+ if (fith)
+ {
+ Debug("SHRUNK -> sub was %c%s, I am %c%s", sub.SignChar(), sub.DigitStr().c_str(), SignChar(), DigitStr().c_str());
+ }
return *this;
}
m_digits[i] |= underflow;
underflow = next_underflow;
}
+ Shrink();
return *this;
}
// Shift by whole number of digits
unsigned whole = amount/(8*sizeof(digit_t));
unsigned old_size = m_digits.size();
- m_digits.resize(m_digits.size() + whole);
+ for (unsigned i = 0; i < whole; ++i)
+ {
+
+ GrowDigit(0L);//m_digits.resize(m_digits.size() + whole);
+ }
memmove(m_digits.data()+whole, m_digits.data(), sizeof(digit_t)*old_size);
memset(m_digits.data(), 0L, whole*sizeof(digit_t));
}
if (overflow != 0L)
m_digits.push_back(overflow);
-
+ Shrink();
return *this;
}
void Arbint::BitSet(unsigned i)
{
unsigned digit = i/(8*sizeof(digit_t));
- if (digit >= m_digits.size())
+ while (m_digits.size() < digit+1)
{
- m_digits.resize(digit+1, 0L);
+ Debug("Grow BitSet Size %u, digit %u", m_digits.size(), digit);
+ GrowDigit(0L);
}
+
i = i % (8*sizeof(digit_t));
m_digits[digit] |= (1L << i);
}
{
return abs(a);
}
-
template <> Arbint Tabs(const Arbint & a);
P = Q = T(1);
return;
}
-
T g = gcd(Tabs(P), Tabs(Q));
//Debug("Got gcd!");
P /= g;
Rational operator-(const Rational & r) const
{
Rational result = (r.P == T(0)) ? Rational(P,Q) : Rational(P*r.Q - r.P*Q, Q*r.Q);
- result.CheckAccuracy(ToDouble() - r.ToDouble(),"-");
+ //result.CheckAccuracy(ToDouble() - r.ToDouble(),"-");
return result;
}
Rational operator*(const Rational & r) const
//Rational operator*(const Rational & r) const {return Rational(ToDouble()*r.ToDouble());}
//Rational operator/(const Rational & r) const {return Rational(ToDouble()/r.ToDouble());}
+ Rational operator-() const {Rational r(*this); r.P = -r.P;}
Rational & operator=(const Rational & r) {P = r.P; Q = r.Q; Simplify(); return *this;}
Rational & operator+=(const Rational & r) {this->operator=(*this+r); return *this;}
Rational & operator-=(const Rational & r) {this->operator=(*this-r); return *this;}
Rational & operator*=(const Rational & r) {this->operator=(*this*r); return *this;}
Rational & operator/=(const Rational & r) {this->operator=(*this/r); return *this;}
- double ToDouble() const {return (double)(P) / (double)(Q);}
+ double ToDouble() const
+ {
+ return (double)P/(double)Q;
+ }
bool CheckAccuracy(double d, const char * msg, double threshold = 1e-3) const
{
double result = fabs(ToDouble() - d);