X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;ds=inline;f=src%2Fparanoidnumber.cpp;h=2bb44da2b5fbbf0dab74ccb9c7b35d6233cfbf62;hb=36b4b285d3dbdab423511e7188c37bd1d0443edb;hp=2510f66388cfce8f5431009c9887a330522f2974;hpb=6472d20ee58d2ecc0aee8bc1a12a071b2afc8a27;p=ipdf%2Fcode.git diff --git a/src/paranoidnumber.cpp b/src/paranoidnumber.cpp index 2510f66..2bb44da 100644 --- a/src/paranoidnumber.cpp +++ b/src/paranoidnumber.cpp @@ -3,13 +3,14 @@ #include #include #include "log.h" +#include using namespace std; namespace IPDF { -ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next(NULL) +ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next_term(NULL), m_next_factor(NULL) { int dp = 0; int end = 0; @@ -26,7 +27,10 @@ ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next { ParanoidNumber b(str[i]-'0'); b*=m; + //Debug("m is %s", m.Str().c_str()); + //Debug("Add %s", b.Str().c_str()); this->operator+=(b); + //Debug("Now at %s", Str().c_str()); m*=10; } ParanoidNumber n(1); @@ -34,142 +38,131 @@ ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next { n/=10; ParanoidNumber b(str[i]-'0'); + //Debug("%s * %s", b.Str().c_str(), n.Str().c_str()); b*=n; + //Debug("b -> %s", b.Str().c_str()); + //Debug("Add %s", b.Str().c_str()); this->operator+=(b); - } - -} + //Debug("Now at %s", Str().c_str()); -ParanoidNumber * ParanoidNumber::InsertAfter(float value, Optype op) -{ - return InsertAfter(new ParanoidNumber(value, op)); -} - -ParanoidNumber * ParanoidNumber::InsertAfter(ParanoidNumber * insert) -{ - //Debug("Insert {%s} after {%f, %s}",insert->Str().c_str(), - // m_value, g_opstr[m_op]); - ParanoidNumber * n = m_next; - m_next = insert; - - ParanoidNumber * p = m_next; - while (p->m_next != NULL) - p = p->m_next; - p->m_next = n; - - return m_next; + } + Debug("Constructed {%s} from %s (%f)", Str().c_str(), str, ToDouble()); } - ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a) { - const ParanoidNumber * na = &a; - ParanoidNumber * nb = this; - ParanoidNumber * p = NULL; - while (na != NULL && nb != NULL) + //TODO: Optimise + delete m_next_term; + delete m_next_factor; + m_op = a.m_op; + if (a.m_next_term != NULL) { - nb->m_value = na->m_value; - nb->m_op = na->m_op; - na = na->m_next; - p = nb; - nb = nb->m_next; - - } - - while (na != NULL) // => nb == NULL - { - InsertAfter(na->m_value, na->m_op); - na = na->m_next; + m_next_term = new ParanoidNumber(*(a.m_next_term)); } - - if (nb != NULL) + if (a.m_next_factor != NULL) { - if (p != NULL) - p->m_next = NULL; - delete nb; + m_next_factor = new ParanoidNumber(*(a.m_next_factor)); } return *this; } ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a) { - ParanoidNumber * insert = new ParanoidNumber(a, ADD); - if (m_next == NULL || m_next->m_op == ADD || m_next->m_op == SUBTRACT) - { - InsertAfter(insert); - Simplify(); - return *this; - } + // this = v + t + (a) + // -> v + (a) + t - if (m_next->m_op == MULTIPLY) // (a*b) + c == (a+[c/b]) * b - insert->operator/=(*m_next); - else - insert->operator*=(*m_next); // (a/b) + c == (a+[c*b])/b + ParanoidNumber * nt = m_next_term; + ParanoidNumber * nf = m_next_factor; - if (insert->m_next != NULL) // neither of the above simplified - { - //Debug("{%s} did not simplify, change back to {%s}", insert->Str().c_str(), a.Str().c_str()); - insert->operator=(a); // Just add as is - insert->m_op = ADD; - ParanoidNumber * n = this; - while (n->m_next != NULL) - n = n->m_next; - n->InsertAfter(insert); - } - else + ParanoidNumber ca(a); + if (m_next_factor != NULL) { - InsertAfter(insert); + if (m_next_factor->m_op == MULTIPLY) + ca /= (*m_next_factor); + else + ca *= (*m_next_factor); + + if (ca.Floating()) + { + m_next_factor = NULL; + m_next_term = NULL; + operator+=(ca); + m_next_factor = nf; + m_next_term = nt; + Simplify(); + return *this; + } + } + + m_next_term = new ParanoidNumber(a, ADD); + ParanoidNumber * t = m_next_term; + while (t->m_next_term != NULL) + t = t->m_next_term; + t->m_next_term = nt; + //Debug("Simplify {%s} after add", Str().c_str()); Simplify(); return *this; } + ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a) { - ParanoidNumber * insert = new ParanoidNumber(a, SUBTRACT); - if (m_next == NULL || m_next->m_op == ADD || m_next->m_op == SUBTRACT) - { - InsertAfter(insert); - Simplify(); - return *this; - } + // this = v + t + (a) + // -> v + (a) + t - if (m_next->m_op == MULTIPLY) // (a*b) - c == (a-[c/b]) * b - insert->operator/=(*m_next); - else - insert->operator*=(*m_next); // (a/b) - c == (a-[c*b])/b + ParanoidNumber * nt = m_next_term; + ParanoidNumber * nf = m_next_factor; - if (insert->m_next != NULL) // neither of the above simplified + ParanoidNumber ca(a, SUBTRACT); + if (m_next_factor != NULL) { - //Debug("{%s} did not simplify, change back to {%s}", insert->Str().c_str(), a.Str().c_str()); - insert->operator=(a); // Just add as is - insert->m_op = SUBTRACT; - ParanoidNumber * n = this; - while (n->m_next != NULL) - n = n->m_next; - n->InsertAfter(insert); - } - else + if (m_next_factor->m_op == MULTIPLY) + ca /= (*m_next_factor); + else + ca *= (*m_next_factor); + + if (ca.Floating()) + { + m_next_factor = NULL; + m_next_term = NULL; + operator-=(ca); + m_next_factor = nf; + m_next_term = nt; + Simplify(); + return *this; + } + + } + + m_next_term = new ParanoidNumber(a,SUBTRACT); + ParanoidNumber * t = m_next_term; + while (t->m_next_term != NULL) { - InsertAfter(insert); + t->m_op = SUBTRACT; + t = t->m_next_term; } + t->m_op = SUBTRACT; + //Debug("next term {%s}", m_next_term->Str().c_str()); + t->m_next_term = nt; + //Debug("Simplify {%s} after sub", Str().c_str()); Simplify(); return *this; } ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a) { - ParanoidNumber * n = m_next; - while (n != NULL) - { - if (n->m_op == ADD || n->m_op == SUBTRACT) - { - n->operator*=(a); - break; - } - n = n->m_next; - } - - InsertAfter(new ParanoidNumber(a, MULTIPLY)); + Debug("{%s} *= {%s}", Str().c_str(), a.Str().c_str()); + // this = (vf + t) * (a) + ParanoidNumber * nf = m_next_factor; + m_next_factor = new ParanoidNumber(a, MULTIPLY); + ParanoidNumber * t = m_next_factor; + while (t->m_next_factor != NULL) + t = t->m_next_factor; + t->m_next_factor = nf; + if (m_next_term != NULL) + m_next_term->operator*=(a); + //Debug("Simplify after mul"); + Debug("Simplify {%s}", Str().c_str()); Simplify(); return *this; } @@ -177,122 +170,164 @@ ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a) ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a) { - ParanoidNumber * n = m_next; - while (n != NULL) - { - if (n->m_op == ADD || n->m_op == SUBTRACT) - { - n->operator/=(a); - break; - } - n = n->m_next; - } - - InsertAfter(new ParanoidNumber(a, DIVIDE)); + //Debug("Called %s /= %s", Str().c_str(), a.Str().c_str()); + // this = (vf + t) * (a) + ParanoidNumber * nf = m_next_factor; + m_next_factor = new ParanoidNumber(a, DIVIDE); + ParanoidNumber * t = m_next_factor; + while (t->m_next_factor != NULL) + t = t->m_next_factor; + t->m_next_factor = nf; + if (m_next_term != NULL) + m_next_term->operator/=(a); Simplify(); return *this; } -double ParanoidNumber::ToDouble() const -{ - double value = (m_op == SUBTRACT) ? -m_value : m_value; - const ParanoidNumber * n = m_next; - while (n != NULL) + + +void ParanoidNumber::SimplifyTerms() +{ + //Debug("Simplify {%s}", Str().c_str()); + if (m_next_term == NULL) { - switch (n->m_op) + //Debug("No terms!"); + return; + } + + for (ParanoidNumber * a = this; a != NULL; a = a->m_next_term) + { + ParanoidNumber * bprev = a; + ParanoidNumber * b = a->m_next_term; + while (b != NULL) { - case ADD: - case SUBTRACT: - return value + n->ToDouble(); - break; - case MULTIPLY: - value *= n->m_value; - break; - case DIVIDE: - value /= n->m_value; - break; + //Debug("Simplify factors of %s", b->Str().c_str()); + b->SimplifyFactors(); + if (b->m_next_factor != NULL) + { + bprev = b; + b = b->m_next_term; + continue; + } + float f = a->m_value; + feclearexcept(FE_ALL_EXCEPT); + switch (b->m_op) + { + case ADD: + f += b->m_value; + break; + case SUBTRACT: + f -= b->m_value; + break; + default: + Fatal("Unexpected %c in term list...", OpChar(b->m_op)); + break; + } + if (!fetestexcept(FE_ALL_EXCEPT)) + { + a->m_value = f; + bprev->m_next_term = b->m_next_term; + b->m_next_term = NULL; + delete b; + b = bprev; + } + bprev = b; + b = b->m_next_term; } - n = n->m_next; } - return value; } -void ParanoidNumber::Simplify() -{ - ParanoidNumber * n = m_next; - ParanoidNumber * p = this; - - while (n != NULL) +void ParanoidNumber::SimplifyFactors() +{ + //Debug("Simplify {%s}", Str().c_str()); + if (m_next_factor == NULL) { - - float a = p->m_value; - switch (n->m_op) + //Debug("No factors!"); + return; + } + + for (ParanoidNumber * a = this; a != NULL; a = a->m_next_factor) + { + ParanoidNumber * bprev = a; + ParanoidNumber * b = a->m_next_factor; + while (b != NULL) { - case ADD: - n->Simplify(); - feclearexcept(FE_ALL_EXCEPT); - a += n->m_value; - break; - case SUBTRACT: - n->Simplify(); - feclearexcept(FE_ALL_EXCEPT); - a -= n->m_value; - break; - case MULTIPLY: - feclearexcept(FE_ALL_EXCEPT); - a *= n->m_value; - break; - case DIVIDE: - feclearexcept(FE_ALL_EXCEPT); - a /= n->m_value; - break; + b->SimplifyTerms(); + if (b->m_next_term != NULL) + { + bprev = b; + b = b->m_next_factor; + continue; + } + float f = a->m_value; + feclearexcept(FE_ALL_EXCEPT); + switch (b->m_op) + { + case MULTIPLY: + if (a->m_op != DIVIDE) + f *= b->m_value; + else + f /= b->m_value; + break; + case DIVIDE: + if (a->m_op != DIVIDE) + f /= b->m_value; + else + f *= b->m_value; + break; + default: + Fatal("Unexpected %c in factor list...",OpChar(b->m_op)); + break; + } + if (!fetestexcept(FE_ALL_EXCEPT)) + { + a->m_value = f; + bprev->m_next_factor = b->m_next_factor; + b->m_next_factor = NULL; + delete b; + b = bprev; + } + //else + //Debug("Failed to simplify %f %c %f", a->m_value, OpChar(b->m_op), b->m_value); + bprev = b; + b = b->m_next_factor; } - // can't merge p and n - if (fetestexcept(FE_ALL_EXCEPT)) - { - while (n != NULL && n->m_op != ADD && n->m_op != SUBTRACT) - n = n->m_next; - if (n != NULL) - n->Simplify(); - return; - } - else - { - // merge n into p - p->m_value = a; - p->m_next = n->m_next; - n->m_next = NULL; - delete n; - n = p->m_next; - } - //Debug(" -> {%s}", Str().c_str()); } } +void ParanoidNumber::Simplify() +{ + SimplifyFactors(); + SimplifyTerms(); +} + string ParanoidNumber::Str() const { string result(""); - switch (m_op) + stringstream s; + + s << m_value; + + if (m_next_factor != NULL) { - case ADD: - result += " +"; - break; - case SUBTRACT: - result += " -"; - break; - case MULTIPLY: - result += " *"; - break; - case DIVIDE: - result += " /"; - break; + result += OpChar(m_op); + result += "("; + result += s.str(); + result += m_next_factor->Str(); + result += ")"; + } + else + { + result += OpChar(m_op); + result += s.str(); + } + + if (m_next_term != NULL) + { + result += " "; + result += m_next_term->Str(); } - stringstream s(""); - s << m_value; - result += s.str(); - if (m_next != NULL) - result += m_next->Str(); return result; }