X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=src%2Fparanoidnumber.cpp;h=6b602c0ececc1b17d5d20607394131cdaf12141d;hb=748d002a813bbe6309dd22259bdce3278c02b0c8;hp=b2a66f47f2a77fab83bd72e89d0145e4f698340f;hpb=1d179b93f6a1b2a4fe3823c26fba862c24bc5d6e;p=ipdf%2Fcode.git diff --git a/src/paranoidnumber.cpp b/src/paranoidnumber.cpp index b2a66f4..6b602c0 100644 --- a/src/paranoidnumber.cpp +++ b/src/paranoidnumber.cpp @@ -29,7 +29,7 @@ ParanoidNumber::~ParanoidNumber() ParanoidNumber::ParanoidNumber(const string & str) : m_value(0), m_next() { #ifdef PARANOID_SIZE_LIMIT - m_size = 0; + m_size = 1; #endif #ifdef PARANOID_CACHE_RESULTS m_cached_result = NAN; @@ -37,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; @@ -45,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; @@ -60,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) @@ -416,16 +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 + b->m_size >= PARANOID_SIZE_LIMIT) { + this->operator=(this->Digit()); if (op == ADD) - { - m_value += b->Digit() / GetFactors(); - } + m_value += b->Digit(); else - { - m_value -= b->Digit() / GetFactors(); - } + m_value -= b->Digit(); + m_size = 1; + //Debug("Cut off %p", this); return b; } //Debug("At size limit %d", m_size); @@ -528,7 +541,7 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa //merge->m_next[*merge_op].push_back(b); m_next[op].push_back(b); #ifdef PARANOID_SIZE_LIMIT - m_size += 1+b->m_size; + m_size += b->m_size; #endif } else @@ -551,17 +564,16 @@ ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, m_cached_result = NAN; #endif #ifdef PARANOID_SIZE_LIMIT - if (m_size >= PARANOID_SIZE_LIMIT) + if (m_size + b->m_size >= PARANOID_SIZE_LIMIT) { + this->operator=(this->Digit()); if (op == MULTIPLY) m_value *= b->Digit(); else m_value /= b->Digit(); - - for (auto n : m_next[ADD]) - delete n->OperationFactor(new ParanoidNumber(*b), op); - for (auto n : m_next[SUBTRACT]) - delete n->OperationFactor(new ParanoidNumber(*b), op); + m_size = 1; + + //Debug("Cut off %p", this); return b; } @@ -678,7 +690,7 @@ ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, delete(sub->OperationFactor(new ParanoidNumber(*cpy_b), op)); #ifdef PARANOID_SIZE_LIMIT - m_size += 1+b->m_size; + m_size += b->m_size; #endif } //assert(SanityCheck()); @@ -771,7 +783,7 @@ bool ParanoidNumber::Simplify(Optype op) if (result != NULL) { #ifdef PARANOID_SIZE_LIMIT - m_size -= (1+result->m_size); + m_size -= result->m_size; #endif *m = NULL; delete(result); @@ -788,7 +800,7 @@ bool ParanoidNumber::Simplify(Optype op) #ifdef PARANOID_SIZE_LIMIT if (Operation(n, op) == n) { - m_size -= (1+n->m_size); + m_size -= n->m_size; delete n; } #else @@ -916,6 +928,12 @@ bool ParanoidNumber::SanityCheck(set & visited) const 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)