From 68dfceb76cbc78e1e0dd529dd0c14be116528353 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Mon, 7 Jul 2014 09:17:12 +0800 Subject: [PATCH] Arbint subtraction should work* now Yes I was being clever and resizing if sub.m_digits.size() > this->m_digits.size() But I forgot about when this->m_digits.size() > sub.m_digits.size() Passes tests/realops.test now! On the other hand, CPU rendering of Beziers doesn't work anymore. I think it's just drawing two lines instead of lots of them. --- src/arbint.cpp | 44 +++++++++++++++++++++++++++++--------------- src/main.cpp | 2 +- src/tests/arb.cpp | 17 +++++++++++++++-- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/src/arbint.cpp b/src/arbint.cpp index 666b10e..12cf18d 100644 --- a/src/arbint.cpp +++ b/src/arbint.cpp @@ -81,7 +81,7 @@ unsigned Arbint::Shrink() unsigned shrunk = 0; while (m_digits.size() > 1 && m_digits[m_digits.size()-1] == 0L) { - Debug("Shrink 1"); + //Debug("Shrink 1"); m_digits.pop_back(); shrunk++; } @@ -91,12 +91,19 @@ unsigned Arbint::Shrink() void Arbint::GrowDigit(digit_t new_msd) { static unsigned total_grows = 0; + static unsigned biggest_arbint = 1; 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) + total_grows++; + if (m_digits.size() > biggest_arbint) { - Fatal("Too many GrowDigit calls!"); + biggest_arbint = m_digits.size(); + Warn("New biggest Arbint of size %u", m_digits.size()); } + //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) @@ -145,7 +152,7 @@ void Arbint::Division(const Arbint & div, Arbint & result, Arbint & remainder) c result.m_sign = !(m_sign == div.m_sign); return; } */ - + for (int i = 8*sizeof(digit_t)*m_digits.size(); i >= 0; --i) { remainder <<= 1; @@ -220,7 +227,7 @@ Arbint & Arbint::SubBasic(const Arbint & sub) bool fith = false; while (sub.m_digits.size() > m_digits.size()) { - fith = true; + fith = false; GrowDigit(0L); } if (fith) @@ -233,18 +240,25 @@ Arbint & Arbint::SubBasic(const Arbint & sub) if (fith) { - Debug("SUB_DIGITS -> sub was %c%s, I am %c%s", SignChar(), sub.DigitStr().c_str(), SignChar(), DigitStr().c_str()); + Debug("SUB_DIGITS -> sub was %c%s, I am %c%s, borrow is %lu", SignChar(), sub.DigitStr().c_str(), SignChar(), DigitStr().c_str(), borrow); } //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]); - vector 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 (sub.m_digits.size() < m_digits.size()) + { + m_digits[m_digits.size()-1] -= borrow; + } + else + { + m_sign = !m_sign; + for (unsigned i = 0; i < m_digits.size(); ++i) + m_digits[i] = (~m_digits[i]); + vector 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) { @@ -361,7 +375,7 @@ Arbint & Arbint::operator<<=(unsigned amount) unsigned old_size = m_digits.size(); for (unsigned i = 0; i < whole; ++i) { - + //Debug("i = %u, whole = %u", i, whole); GrowDigit(0L);//m_digits.resize(m_digits.size() + whole); } memmove(m_digits.data()+whole, m_digits.data(), sizeof(digit_t)*old_size); @@ -420,7 +434,7 @@ void Arbint::BitSet(unsigned i) unsigned digit = i/(8*sizeof(digit_t)); while (m_digits.size() < digit+1) { - Debug("Grow BitSet Size %u, digit %u", m_digits.size(), digit); + //Debug("Grow BitSet Size %u, digit %u", m_digits.size(), digit); GrowDigit(0L); } diff --git a/src/main.cpp b/src/main.cpp index 9af7bbc..194ef04 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -98,7 +98,7 @@ int main(int argc, char ** argv) } } Debug("Make rect"); - doc.Add(BEZIER, Rect(0.1,0.1,0.8,0.8), 0); + doc.Add(RECT_OUTLINE, Rect(0.1,0.1,0.8,0.8), 0); Debug("Made rect"); } diff --git a/src/tests/arb.cpp b/src/tests/arb.cpp index ffbf74e..f8a74d3 100644 --- a/src/tests/arb.cpp +++ b/src/tests/arb.cpp @@ -7,7 +7,7 @@ using namespace std; using namespace IPDF; -#define TEST_CASES 100 +#define TEST_CASES 10 void TestShifting(unsigned cases) @@ -87,11 +87,20 @@ void TestConstructFromDouble(unsigned cases) void TestSubtraction() { - + Arbint b(2u, 45L, 10L); + Arbint a(1u, 128L, 0L); + Arbint c(a - b); + Arbint test = -Arbint(2u, 18446744073709551533LU,9L); + Debug("%c%s - %c%s = %c%s", a.SignChar(), a.DigitStr().c_str(), b.SignChar(), b.DigitStr().c_str(), c.SignChar(), c.DigitStr().c_str()); + if (c != test) + { + Fatal("Expected %c%s, got %c%s", test.SignChar(), test.DigitStr().c_str(), c.SignChar(), c.DigitStr().c_str()); + } } int main(int argc, char ** argv) { + Debug("Shift testing..."); TestShifting(TEST_CASES); Debug("Left/Right shift testing succeeded"); @@ -104,5 +113,9 @@ int main(int argc, char ** argv) Debug("Testing construct from double"); TestConstructFromDouble(TEST_CASES); Debug("Construct from double successful"); + + Debug("Testing subtractions"); + TestSubtraction(); + Debug("Testing subtractions successful"); return 0; } -- 2.20.1