X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fparanoidnumber.cpp;h=efae86003e6ddefd36f5b071db370a6c78243b87;hb=35bc799125eec0d0c839af56fd136c8e85793a56;hp=82c7ba453b7830738eef11319d5321151195b01c;hpb=03cc1b0a0d0705e0b1d92e13fdb18608c7a00272;p=ipdf%2Fcode.git diff --git a/src/paranoidnumber.cpp b/src/paranoidnumber.cpp index 82c7ba4..efae860 100644 --- a/src/paranoidnumber.cpp +++ b/src/paranoidnumber.cpp @@ -6,6 +6,8 @@ #include #include +// here be many copy paste bugs + using namespace std; namespace IPDF { @@ -35,6 +37,12 @@ ParanoidNumber::ParanoidNumber(const string & str) : m_value(0), m_next() int dp = 0; int end = 0; + bool negate = str[0] == '-'; + if (negate) + { + dp++; + end++; + } while (str[dp] != '\0' && str[dp] != '.') { ++dp; @@ -43,7 +51,7 @@ ParanoidNumber::ParanoidNumber(const string & str) : m_value(0), m_next() while (str[end] != '\0') ++end; ParanoidNumber m(1); - for (int i = dp-1; i >= 0; --i) + for (int i = dp-1; i >= negate; --i) { ParanoidNumber b(str[i]-'0'); b*=m; @@ -58,6 +66,14 @@ ParanoidNumber::ParanoidNumber(const string & str) : m_value(0), m_next() b*=n; this->operator+=(b); } + + if (negate) + Negate(); + + #ifdef PARANOID_COMPARE_EPSILON + double d = strtod(str.c_str(), NULL); + CompareForSanity(d, d); + #endif } ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a) @@ -80,20 +96,9 @@ ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a) for (auto n : a.m_next[i]) m_next[i].push_back(new ParanoidNumber(*n)); } - /* - for (unsigned j = 0; j < m_next[i].size() && j < a.m_next[i].size(); ++j) - { - if (a.m_next[i][j] != NULL) - m_next[i][j]->operator=(*(a.m_next[i][j])); - } - - for (unsigned j = a.m_next[i].size(); j < m_next[i].size(); ++j) - { - delete m_next[i][j]; - } - m_next[i].resize(a.m_next[i].size()); - */ - //} + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(a.Digit(),a.Digit()); + #endif return *this; } @@ -273,88 +278,147 @@ bool TrustingOp(int8_t & a, const int8_t & b, Optype op) ParanoidNumber & ParanoidNumber::operator+=(const digit_t & a) { - - //assert(this != NULL); + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare += a; + #endif delete Operation(new ParanoidNumber(a), ADD); - Simplify(ADD); Simplify(SUBTRACT); + Simplify(ADD); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator-=(const digit_t & a) { + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare -= a; + #endif delete Operation(new ParanoidNumber(a), SUBTRACT); - Simplify(SUBTRACT); Simplify(ADD); + Simplify(SUBTRACT); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator*=(const digit_t & a) { + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare *= a; + #endif delete Operation(new ParanoidNumber(a), MULTIPLY); + Simplify(DIVIDE); Simplify(MULTIPLY); - Simplify(DIVIDE); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator/=(const digit_t & a) { + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare /= a; + #endif delete Operation(new ParanoidNumber(a), DIVIDE); Simplify(MULTIPLY); Simplify(DIVIDE); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a) { - - //assert(this != NULL); + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare += a.Digit(); + #endif delete Operation(new ParanoidNumber(a), ADD); - Simplify(ADD); Simplify(SUBTRACT); + Simplify(ADD); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a.Digit()); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a) { + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare -= a.Digit(); + #endif delete Operation(new ParanoidNumber(a), SUBTRACT); - Simplify(SUBTRACT); Simplify(ADD); + Simplify(SUBTRACT); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a.Digit()); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a) { + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare *= a.Digit(); + #endif delete Operation(new ParanoidNumber(a), MULTIPLY); + Simplify(DIVIDE); Simplify(MULTIPLY); - Simplify(DIVIDE); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a.Digit()); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a) { + #ifdef PARANOID_COMPARE_EPSILON + digit_t compare = Digit(); + compare /= a.Digit(); + #endif delete Operation(new ParanoidNumber(a), DIVIDE); Simplify(MULTIPLY); Simplify(DIVIDE); + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(compare, a.Digit()); + #endif return *this; } ParanoidNumber & ParanoidNumber::operator=(const digit_t & a) { + for (int i = 0; i < NOP; ++i) { for (auto n : m_next[i]) delete n; + m_next[i].clear(); } m_value = a; #ifdef PARANOID_CACHE_RESULT m_cached_result = a; #endif + + #ifdef PARANOID_COMPARE_EPSILON + CompareForSanity(a,a); + #endif + return *this; } @@ -366,12 +430,15 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa m_cached_result = NAN; #endif #ifdef PARANOID_SIZE_LIMIT - if (m_size > PARANOID_SIZE_LIMIT) + if (m_size >= PARANOID_SIZE_LIMIT) { + this->operator=(this->Digit()); if (op == ADD) m_value += b->Digit(); else m_value -= b->Digit(); + m_size = 0; + Debug("Cut off %p", this); return b; } //Debug("At size limit %d", m_size); @@ -493,20 +560,22 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op) { - //assert(SanityCheck()); - //assert(b->SanityCheck()); #ifdef PARANOID_CACHE_RESULTS m_cached_result = NAN; #endif #ifdef PARANOID_SIZE_LIMIT - if (m_size > PARANOID_SIZE_LIMIT) + if (m_size >= PARANOID_SIZE_LIMIT) { + this->operator=(this->Digit()); if (op == MULTIPLY) m_value *= b->Digit(); else m_value /= b->Digit(); - //Debug("At size limit %d", m_size); + m_size = 0; + + Debug("Cut off %p", this); return b; + } #endif @@ -530,7 +599,11 @@ ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, } if (b->Floating() && b->m_value == 1) return b; - + if (b->Floating() && b->m_value == 0 && op == MULTIPLY) + { + operator=(*b); + return b; + } if (NoTerms() && b->NoTerms()) @@ -846,10 +919,21 @@ bool ParanoidNumber::SanityCheck(set & visited) const { if (!div->SanityCheck(visited)) return false; + if (div->Digit() == 0) + { + Error("Divide by zero"); + return false; + } } return true; } +void ParanoidNumber::Negate() +{ + swap(m_next[ADD], m_next[SUBTRACT]); + m_value = -m_value; +} + #ifdef PARANOID_USE_ARENA void * ParanoidNumber::operator new(size_t s)