1 #include "paranoidnumber.h"
12 int64_t ParanoidNumber::g_count = 0;
15 ParanoidNumber::~ParanoidNumber()
18 for (int i = 0; i < NOP; ++i)
22 ParanoidNumber::ParanoidNumber(const char * str) : m_value(0)
27 while (str[dp] != '\0' && str[dp] != '.')
32 while (str[end] != '\0')
35 for (int i = dp-1; i >= 0; --i)
37 ParanoidNumber b(str[i]-'0');
43 for (int i = dp+1; i < end; ++i)
45 Debug("{%s} /= 10", n.Str().c_str());
47 Debug("{%s}", n.Str().c_str());
48 ParanoidNumber b(str[i]-'0');
50 Debug("{%s} += {%s}", Str().c_str(), b.Str().c_str());
55 ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
58 for (int i = 0; i < NOP; ++i)
60 if (a.m_next[i] == NULL)
62 if (m_next[i] != NULL)
68 if (m_next[i] != NULL)
70 m_next[i]->operator=(*(a.m_next[i]));
74 m_next[i] = new ParanoidNumber(*(a.m_next[i]));
81 string ParanoidNumber::Str() const
87 if (m_next[MULTIPLY] != NULL)
90 if (m_next[MULTIPLY]->m_next[ADD] != NULL || m_next[MULTIPLY]->m_next[SUBTRACT] != NULL)
91 result += "(" + m_next[MULTIPLY]->Str() + ")";
93 result += m_next[MULTIPLY]->Str();
95 if (m_next[DIVIDE] != NULL)
98 if (m_next[DIVIDE]->m_next[ADD] != NULL || m_next[DIVIDE]->m_next[SUBTRACT] != NULL)
99 result += "(" + m_next[DIVIDE]->Str() + ")";
101 result += m_next[DIVIDE]->Str();
104 if (m_next[ADD] != NULL)
107 if (m_next[ADD]->m_next[MULTIPLY] != NULL || m_next[ADD]->m_next[DIVIDE] != NULL)
108 result += "(" + m_next[ADD]->Str() + ")";
110 result += m_next[ADD]->Str();
112 if (m_next[SUBTRACT] != NULL)
115 if (m_next[SUBTRACT]->m_next[MULTIPLY] != NULL || m_next[SUBTRACT]->m_next[DIVIDE] != NULL)
116 result += "(" + m_next[SUBTRACT]->Str() + ")";
118 result += m_next[SUBTRACT]->Str();
126 bool TrustingOp<float>(float & a, const float & b, Optype op)
128 feclearexcept(FE_ALL_EXCEPT);
146 return !fetestexcept(FE_ALL_EXCEPT);
150 bool TrustingOp<double>(double & a, const double & b, Optype op)
152 feclearexcept(FE_ALL_EXCEPT);
170 return !fetestexcept(FE_ALL_EXCEPT);
174 bool TrustingOp<int8_t>(int8_t & a, const int8_t & b, Optype op)
182 exact = (abs(sa) <= 127);
186 exact = (abs(sa) <= 127);
190 exact = (abs(sa) <= 127);
193 exact = (b != 0 && sa > b && sa % b == 0);
204 ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a)
206 delete Operation(new ParanoidNumber(a), ADD);
211 ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a)
213 delete Operation(new ParanoidNumber(a), SUBTRACT);
217 ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a)
219 delete Operation(new ParanoidNumber(a), MULTIPLY);
224 ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a)
226 delete Operation(new ParanoidNumber(a), DIVIDE);
231 * Performs the operation on a with argument b (a += b, a -= b, a *= b, a /= b)
232 * @returns b if b can safely be deleted
233 * @returns NULL if b has been merged with a
234 * append indicates that b should be merged
236 ParanoidNumber * ParanoidNumber::Operation(ParanoidNumber * b, Optype op, ParanoidNumber ** parent)
241 Optype invop = InverseOp(op); // inverse of p
242 ParanoidNumber * append_at = this;
246 if ((op == ADD || op == SUBTRACT) && (m_value == 0))
248 m_value = b->m_value;
249 for (int i = 0; i < NOP; ++i)
251 m_next[i] = b->m_next[i];
256 if ((op == MULTIPLY) && (m_value == 1))
258 m_value = b->m_value;
259 for (int i = 0; i < NOP; ++i)
261 m_next[i] = b->m_next[i];
272 if ((op == ADD || op == SUBTRACT) && (b->m_value == 0))
274 if ((op == MULTIPLY || op == DIVIDE) && (b->m_value == 1))
278 // Operation can be applied directly to the m_value of this and b
279 // ie: op is + or - and this and b have no * or / children
280 // or: op is * or / and this and b have no + or - children
281 if (Pure(op) && (b->Pure(op)))
283 if (ParanoidOp<digit_t>(m_value, b->m_value, op)) // op applied successfully...
287 for (int i = 0; i < NOP; ++i) // Try applying b's children to this
289 delete Operation(b->m_next[i], Optype(i));
292 return b; // can delete b
296 // Try to simplify the cases:
297 // a + b*c == (a/c + b)*c
298 // a + b/c == (a*c + b)/c
299 else if ((op == ADD || op == SUBTRACT) &&
300 (Pure(op) || b->Pure(op)))
303 Debug("Simplify: {%s} %c {%s}", Str().c_str(), OpChar(op), b->Str().c_str());
304 Optype adj[] = {MULTIPLY, DIVIDE};
305 for (int i = 0; i < 2; ++i)
309 Optype invf = InverseOp(f);
311 Debug("Try %c", OpChar(f));
313 if (m_next[f] == NULL && b->m_next[f] == NULL)
316 ParanoidNumber * tmp_a = new ParanoidNumber(*this);
317 ParanoidNumber * tmp_b = new ParanoidNumber(*b);
320 ParanoidNumber * af = (tmp_a->m_next[f] != NULL) ? new ParanoidNumber(*(tmp_a->m_next[f])) : NULL;
321 ParanoidNumber * bf = (tmp_b->m_next[f] != NULL) ? new ParanoidNumber(*(tmp_b->m_next[f])) : NULL;
323 Debug("{%s} %c {%s}", tmp_a->Str().c_str(), OpChar(op), tmp_b->Str().c_str());
324 Debug("{%s} %c {%s}", tmp_a->Str().c_str(), OpChar(op), tmp_b->Str().c_str());
325 if (tmp_a->Operation(af, invf) != af || tmp_b->Operation(bf, invf) != bf)
333 Debug("{%s} %c {%s}", tmp_a->Str().c_str(), OpChar(op), tmp_b->Str().c_str());
335 if (tmp_a->Operation(bf, invf) == bf && tmp_b->Operation(af, invf) == af) // a / c simplifies
337 if (tmp_a->Operation(tmp_b, op) != NULL) // (a/c) + b simplifies
339 this->operator=(*tmp_a);
341 delete Operation(bf, f);
343 delete Operation(af, f);
346 return b; // It simplified after all!
355 //Debug("tmp_a : %s", tmp_a->PStr().c_str());
356 //Debug("tmp_b : %s", tmp_b->PStr().c_str());
362 // See if operation can be applied to children of this in the same dimension
364 // (a / b) / c = a / (b*c)
365 // (a * b) / c = a * (b/c)
366 // (a / b) * c = a / (b/c)
367 // (a * b) * c = a * (b*c)
368 // (a + b) + c = a + (b+c)
369 // (a - b) + c = a - (b-c)
370 // (a + b) - c = a + (b-c)
371 // (a - b) - c = a - (b+c)
374 if (op == DIVIDE || op == SUBTRACT)
379 // opposite direction first (because ideally things will cancel each other out...)
380 if (m_next[invop] != NULL && m_next[invop]->Operation(b, rev, &append_at) != NULL)
383 if (m_next[op] != NULL && m_next[op]->Operation(b, fwd, &append_at) != NULL)
387 // At this point, we have no choice but to merge 'b' with this ParanoidNumber
389 // we are a child; the merge operation needs to be applied by the root, so leave
392 if (m_next[op] == NULL)
393 *parent = this; // last element in list
397 append_at->m_next[op] = b; // Merge with b
399 // MULTIPLY and DIVIDE operations need to be performed on each term in the ADD/SUBTRACT dimension
400 if (op == DIVIDE || op == MULTIPLY)
402 // apply the operation to each term
403 if (m_next[ADD] != NULL) delete m_next[ADD]->Operation(new ParanoidNumber(*b), op);
404 if (m_next[SUBTRACT] != NULL) delete m_next[SUBTRACT]->Operation(new ParanoidNumber(*b), op);
406 // try and simplify this by adding the terms (you never know...)
410 // failed to simplify
414 bool ParanoidNumber::Simplify(Optype op)
416 ParanoidNumber * n = m_next[op];
418 if (Operation(n, Optype(op)))
430 string ParanoidNumber::PStr() const
433 for (int i = 0; i < NOP; ++i)
435 Optype f = Optype(i);
436 s << this << OpChar(f) << m_next[f] << "\n";