1 #include "paranoidnumber.h"
12 ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_op(ADD), m_next(NULL)
16 while (str[dp] != '\0' && str[dp] != '.')
21 while (str[end] != '\0')
25 for (int i = dp-1; i >= 0; --i)
27 ParanoidNumber b(str[i]-'0');
33 for (int i = dp+1; i < end; ++i)
36 ParanoidNumber b(str[i]-'0');
43 ParanoidNumber * ParanoidNumber::InsertAfter(float value, Optype op)
45 return InsertAfter(new ParanoidNumber(value, op));
48 ParanoidNumber * ParanoidNumber::InsertAfter(ParanoidNumber * insert)
50 //Debug("Insert {%s} after {%f, %s}",insert->Str().c_str(),
51 // m_value, g_opstr[m_op]);
52 ParanoidNumber * n = m_next;
55 ParanoidNumber * p = m_next;
56 while (p->m_next != NULL)
64 ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
66 const ParanoidNumber * na = &a;
67 ParanoidNumber * nb = this;
68 ParanoidNumber * p = NULL;
69 while (na != NULL && nb != NULL)
71 nb->m_value = na->m_value;
79 while (na != NULL) // => nb == NULL
81 InsertAfter(na->m_value, na->m_op);
94 ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a)
96 ParanoidNumber * insert = new ParanoidNumber(a, ADD);
97 if (m_next == NULL || m_next->m_op == ADD || m_next->m_op == SUBTRACT)
104 if (m_next->m_op == MULTIPLY) // (a*b) + c == (a+[c/b]) * b
105 insert->operator/=(*m_next);
107 insert->operator*=(*m_next); // (a/b) + c == (a+[c*b])/b
109 if (insert->m_next != NULL) // neither of the above simplified
111 //Debug("{%s} did not simplify, change back to {%s}", insert->Str().c_str(), a.Str().c_str());
112 insert->operator=(a); // Just add as is
114 ParanoidNumber * n = this;
115 while (n->m_next != NULL)
117 n->InsertAfter(insert);
126 ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a)
128 ParanoidNumber * insert = new ParanoidNumber(a, SUBTRACT);
129 if (m_next == NULL || m_next->m_op == ADD || m_next->m_op == SUBTRACT)
136 if (m_next->m_op == MULTIPLY) // (a*b) - c == (a-[c/b]) * b
137 insert->operator/=(*m_next);
139 insert->operator*=(*m_next); // (a/b) - c == (a-[c*b])/b
141 if (insert->m_next != NULL) // neither of the above simplified
143 //Debug("{%s} did not simplify, change back to {%s}", insert->Str().c_str(), a.Str().c_str());
144 insert->operator=(a); // Just add as is
145 insert->m_op = SUBTRACT;
146 ParanoidNumber * n = this;
147 while (n->m_next != NULL)
149 n->InsertAfter(insert);
159 ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a)
161 ParanoidNumber * n = m_next;
164 if (n->m_op == ADD || n->m_op == SUBTRACT)
172 InsertAfter(new ParanoidNumber(a, MULTIPLY));
178 ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a)
180 ParanoidNumber * n = m_next;
183 if (n->m_op == ADD || n->m_op == SUBTRACT)
191 InsertAfter(new ParanoidNumber(a, DIVIDE));
196 double ParanoidNumber::ToDouble() const
198 double value = (m_op == SUBTRACT) ? -m_value : m_value;
199 const ParanoidNumber * n = m_next;
206 return value + n->ToDouble();
220 void ParanoidNumber::Simplify()
222 ParanoidNumber * n = m_next;
223 ParanoidNumber * p = this;
228 float a = p->m_value;
233 feclearexcept(FE_ALL_EXCEPT);
238 feclearexcept(FE_ALL_EXCEPT);
242 feclearexcept(FE_ALL_EXCEPT);
246 feclearexcept(FE_ALL_EXCEPT);
251 // can't merge p and n
252 if (fetestexcept(FE_ALL_EXCEPT))
254 while (n != NULL && n->m_op != ADD && n->m_op != SUBTRACT)
264 p->m_next = n->m_next;
269 //Debug(" -> {%s}", Str().c_str());
273 string ParanoidNumber::Str() const
295 result += m_next->Str();