#include <cassert>
#include <iostream>
+// here be many copy paste bugs
+
using namespace std;
namespace IPDF
{
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;
int dp = 0;
int end = 0;
+ bool negate = str[0] == '-';
+ if (negate)
+ {
+ dp++;
+ end++;
+ }
while (str[dp] != '\0' && str[dp] != '.')
{
++dp;
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;
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)
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;
}
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;
}
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();
else
m_value -= b->Digit();
+ m_size = 1;
+ //Debug("Cut off %p", this);
return b;
}
//Debug("At size limit %d", m_size);
//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
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 + b->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 = 1;
+
+ //Debug("Cut off %p", this);
return b;
+
}
#endif
}
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())
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());
if (result != NULL)
{
#ifdef PARANOID_SIZE_LIMIT
- m_size -= (1+result->m_size);
+ m_size -= result->m_size;
#endif
*m = NULL;
delete(result);
#ifdef PARANOID_SIZE_LIMIT
if (Operation(n, op) == n)
{
- m_size -= (1+n->m_size);
+ m_size -= n->m_size;
delete n;
}
#else
{
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)