1 #include "paranoidnumber.h"
12 int64_t ParanoidNumber::g_count = 0;
15 ParanoidNumber::~ParanoidNumber()
18 for (int i = 0; i < NOP; ++i)
20 for (auto n : m_next[i])
25 ParanoidNumber::ParanoidNumber(const char * str) : m_value(0), m_cached_result(0)
30 while (str[dp] != '\0' && str[dp] != '.')
35 while (str[end] != '\0')
38 for (int i = dp-1; i >= 0; --i)
40 ParanoidNumber b(str[i]-'0');
46 for (int i = dp+1; i < end; ++i)
49 ParanoidNumber b(str[i]-'0');
55 ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
58 m_cached_result = a.m_cached_result;
59 for (int i = 0; i < NOP; ++i)
61 for (unsigned j = 0; j < m_next[i].size() && j < a.m_next[i].size(); ++j)
63 m_next[i][j]->operator=(*(a.m_next[i][j]));
66 for (unsigned j = a.m_next[i].size(); j < m_next[i].size(); ++j)
70 m_next[i].resize(a.m_next[i].size());
76 string ParanoidNumber::Str() const
82 for (auto mul : m_next[MULTIPLY])
86 result += "(" + mul->Str() + ")";
90 for (auto div : m_next[DIVIDE])
94 result += "(" + div->Str() + ")";
99 for (auto add : m_next[ADD])
102 if (!add->Floating())
103 result += "(" + add->Str() + ")";
105 result += add->Str();
107 for (auto sub : m_next[SUBTRACT])
110 if (!sub->Floating())
111 result += "(" + sub->Str() + ")";
113 result += sub->Str();
121 bool TrustingOp<float>(float & a, const float & b, Optype op)
123 feclearexcept(FE_ALL_EXCEPT);
141 return !fetestexcept(FE_ALL_EXCEPT);
145 bool TrustingOp<double>(double & a, const double & b, Optype op)
147 feclearexcept(FE_ALL_EXCEPT);
165 return !fetestexcept(FE_ALL_EXCEPT);
169 bool TrustingOp<int8_t>(int8_t & a, const int8_t & b, Optype op)
177 exact = (abs(sa) <= 127);
181 exact = (abs(sa) <= 127);
185 exact = (abs(sa) <= 127);
188 exact = (b != 0 && sa > b && sa % b == 0);
199 ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a)
201 delete Operation(new ParanoidNumber(a), ADD);
208 ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a)
210 delete Operation(new ParanoidNumber(a), SUBTRACT);
211 //Simplify(SUBTRACT);
216 ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a)
218 delete Operation(new ParanoidNumber(a), MULTIPLY);
223 ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a)
225 delete Operation(new ParanoidNumber(a), DIVIDE);
230 ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
232 m_cached_result = nan("");
233 if (Floating() && m_value == 0) // 0 + b = b
235 m_value = b->m_value;
239 swap(b->m_next[ADD], b->m_next[SUBTRACT]);
242 for (int i = 0; i < NOP; ++i)
244 m_next[i] = b->m_next[i];
245 b->m_next[i].clear();
249 if (b->Floating() && b->m_value == 0) // a + 0 = a
254 if ((NoFactors() && b->NoFactors())
255 || (GetFactors() == b->GetFactors()))
257 if (ParanoidOp<digit_t>(m_value, b->m_value, op))
259 Optype addop = (op == ADD) ? ADD : SUBTRACT;
260 for (auto add : b->m_next[ADD])
262 delete OperationTerm(add, addop);
264 Optype subop = (op == ADD) ? SUBTRACT : ADD;
265 for (auto sub : b->m_next[SUBTRACT])
266 delete OperationTerm(sub, subop);
268 b->m_next[ADD].clear();
269 b->m_next[SUBTRACT].clear();
276 bool parent = (merge_point == NULL);
277 ParanoidNumber * merge = this;
279 assert(mop != NOP); // silence compiler warning
282 merge_point = &merge;
287 merge = *merge_point;
291 Optype invop = InverseOp(op); // inverse of p
300 for (auto prev : m_next[invop])
302 if (prev->OperationTerm(b, rev, merge_point, merge_op) == b)
306 for (auto next : m_next[op])
308 if (next->OperationTerm(b, fwd, merge_point, merge_op) == b)
317 //merge->m_next[*merge_op].push_back(b);
318 m_next[op].push_back(b);
322 if (m_next[op].size() == 0)
331 ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
333 m_cached_result = nan("");
334 if (Floating() && m_value == 0)
339 if (Floating() && m_value == 1 && op == MULTIPLY)
341 m_value = b->m_value;
342 for (int i = 0; i < NOP; ++i)
344 for (auto n : m_next[i])
347 swap(m_next[i], b->m_next[i]);
351 if (b->Floating() && b->m_value == 1)
356 if (NoTerms() && b->NoTerms())
358 if (ParanoidOp<digit_t>(m_value, b->m_value, op))
360 Optype mulop = (op == MULTIPLY) ? MULTIPLY : DIVIDE;
361 for (auto mul : b->m_next[MULTIPLY])
363 delete OperationFactor(mul, mulop);
365 Optype divop = (op == MULTIPLY) ? DIVIDE : MULTIPLY;
366 for (auto div : b->m_next[DIVIDE])
367 delete OperationFactor(div, divop);
369 b->m_next[DIVIDE].clear();
370 b->m_next[MULTIPLY].clear();
379 bool parent = (merge_point == NULL);
380 ParanoidNumber * merge = this;
384 merge_point = &merge;
389 merge = *merge_point;
393 Optype invop = InverseOp(op); // inverse of p
402 ParanoidNumber * cpy_b = NULL;
404 if (m_next[ADD].size() > 0 || m_next[SUBTRACT].size() > 0)
406 cpy_b = new ParanoidNumber(*b);
409 for (auto prev : m_next[invop])
411 if (prev->OperationFactor(b, rev, merge_point, merge_op) == b)
413 for (auto add : m_next[ADD])
414 delete add->OperationFactor(new ParanoidNumber(*cpy_b), op);
415 for (auto sub : m_next[SUBTRACT])
416 delete sub->OperationFactor(new ParanoidNumber(*cpy_b), op);
422 for (auto next : m_next[op])
424 if (next->OperationFactor(b, fwd, merge_point, merge_op) == b)
426 for (auto add : m_next[ADD])
427 delete add->OperationFactor(new ParanoidNumber(*cpy_b), op);
428 for (auto sub : m_next[SUBTRACT])
429 delete sub->OperationFactor(new ParanoidNumber(*cpy_b), op);
437 m_next[op].push_back(b);
438 for (auto add : m_next[ADD])
439 delete add->OperationFactor(new ParanoidNumber(*cpy_b), op);
440 for (auto sub : m_next[SUBTRACT])
441 delete sub->OperationFactor(new ParanoidNumber(*cpy_b), op);
449 * Performs the operation on a with argument b (a += b, a -= b, a *= b, a /= b)
450 * @returns b if b can safely be deleted
451 * @returns NULL if b has been merged with a
452 * append indicates that b should be merged
454 ParanoidNumber * ParanoidNumber::Operation(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
461 if (op == SUBTRACT || op == ADD)
462 return OperationTerm(b, op, merge_point, merge_op);
463 if (op == MULTIPLY || op == DIVIDE)
464 return OperationFactor(b, op, merge_point, merge_op);
470 string ParanoidNumber::PStr() const
473 for (int i = 0; i < NOP; ++i)
475 Optype f = Optype(i);
477 for (auto n : m_next[f])
479 s << OpChar(f) << n->PStr();
485 bool ParanoidNumber::Simplify(Optype op)
487 vector<ParanoidNumber*> next(0);
488 swap(m_next[op], next);
491 delete Operation(n, op);
493 return (next.size() > m_next[op].size());
496 bool ParanoidNumber::FullSimplify()
499 result |= Simplify(MULTIPLY);
500 result |= Simplify(DIVIDE);
501 result |= Simplify(ADD);
502 result |= Simplify(SUBTRACT);
507 ParanoidNumber::digit_t ParanoidNumber::Digit()
509 if (!isnan(m_cached_result))
510 return m_cached_result;
511 m_cached_result = m_value;
512 for (auto mul : m_next[MULTIPLY])
514 m_cached_result *= mul->Digit();
516 for (auto div : m_next[DIVIDE])
518 m_cached_result /= div->Digit();
520 for (auto add : m_next[ADD])
521 m_cached_result += add->Digit();
522 for (auto sub : m_next[SUBTRACT])
523 m_cached_result -= sub->Digit();
524 return m_cached_result;
528 ParanoidNumber::digit_t ParanoidNumber::GetFactors()
531 for (auto mul : m_next[MULTIPLY])
532 value *= mul->Digit();
533 for (auto div : m_next[DIVIDE])
534 value /= div->Digit();
539 ParanoidNumber::digit_t ParanoidNumber::GetTerms()
542 for (auto add : m_next[ADD])
543 value += add->Digit();
544 for (auto sub : m_next[SUBTRACT])
545 value -= sub->Digit();