Compile with float/double again.
[ipdf/code.git] / src / paranoidnumber.cpp
index b2a66f4..60802eb 100644 (file)
@@ -29,14 +29,20 @@ 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;
+       m_cache_valid = false;
        #endif
        
        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)
@@ -71,8 +85,9 @@ ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
        #endif
        
        m_value = a.m_value;
-       #ifdef PARANOID_CACHE_RESULT
+       #ifdef PARANOID_CACHE_RESULTS
        m_cached_result = a.m_cached_result;
+       m_cache_valid = a.m_cache_valid;
        #endif
        for (int i = 0; i < NOP; ++i)
        {
@@ -397,8 +412,9 @@ ParanoidNumber & ParanoidNumber::operator=(const digit_t & a)
                m_next[i].clear();
        }
        m_value = a;
-       #ifdef PARANOID_CACHE_RESULT
+       #ifdef PARANOID_CACHE_RESULTS
        m_cached_result = a;
+       m_cache_valid = true;
        #endif
 
        #ifdef PARANOID_COMPARE_EPSILON
@@ -413,19 +429,21 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa
 {
        ////assert(b->SanityCheck());
        #ifdef PARANOID_CACHE_RESULTS
-       m_cached_result = NAN;
+       m_cache_valid = false;
        #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;
+                       #ifdef PARANOID_CACHE_RESULTS
+                               m_cached_result = m_value;
+                               m_cache_valid = true;
+                       #endif
                        return b;
                }
                //Debug("At size limit %d", m_size);
@@ -528,7 +546,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
@@ -548,20 +566,22 @@ ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, Pa
 ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
 {
        #ifdef PARANOID_CACHE_RESULTS
-       m_cached_result = NAN;
+       m_cache_valid = false;
        #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;
+                       #ifdef PARANOID_CACHE_RESULTS
+                               m_cached_result = m_value;
+                               m_cache_valid = true;
+                       #endif
+                       //Debug("Cut off %p", this);
                        return b;
                        
                }
@@ -678,7 +698,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 +791,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 +808,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   
@@ -826,10 +846,11 @@ ParanoidNumber::digit_t ParanoidNumber::Digit() const
 
        // Get around the absurd requirement that const correctness be observed.
        #ifdef PARANOID_CACHE_RESULTS
+       if (m_cache_valid) // le sigh ambiguous function compiler warnings
+               return m_cached_result;
+               
        digit_t & result = ((ParanoidNumber*)(this))->m_cached_result;
        
-       if (!isnan(float(result))) // le sigh ambiguous function compiler warnings
-               return result;
        #else
                digit_t result;
        #endif
@@ -846,6 +867,10 @@ ParanoidNumber::digit_t ParanoidNumber::Digit() const
                result += add->Digit();
        for (auto sub : m_next[SUBTRACT])
                result -= sub->Digit();
+               
+       #ifdef PARANOID_CACHE_RESULTS
+               ((ParanoidNumber*)(this))->m_cache_valid = true;
+       #endif
        return result;
                
 }
@@ -916,6 +941,15 @@ bool ParanoidNumber::SanityCheck(set<ParanoidNumber*> & visited) const
        return true;
 }
 
+void ParanoidNumber::Negate()
+{
+       swap(m_next[ADD], m_next[SUBTRACT]);
+       m_value = -m_value;
+       #ifdef PARANOID_CACHE_RESULTS
+               m_cached_result = -m_cached_result;
+       #endif
+}
+
 #ifdef PARANOID_USE_ARENA
 
 void * ParanoidNumber::operator new(size_t s)

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