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)
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 for (int i = 0; i < NOP; ++i)
60 for (unsigned j = 0; j < m_next[i].size() && j < a.m_next[i].size(); ++j)
62 m_next[i][j]->operator=(*(a.m_next[i][j]));
65 for (unsigned j = a.m_next[i].size(); j < m_next[i].size(); ++j)
69 m_next[i].resize(a.m_next[i].size());
75 string ParanoidNumber::Str() const
81 for (auto mul : m_next[MULTIPLY])
85 result += "(" + mul->Str() + ")";
89 for (auto div : m_next[DIVIDE])
93 result += "(" + div->Str() + ")";
98 for (auto add : m_next[ADD])
101 if (!add->Floating())
102 result += "(" + add->Str() + ")";
104 result += add->Str();
106 for (auto sub : m_next[SUBTRACT])
109 if (!sub->Floating())
110 result += "(" + sub->Str() + ")";
112 result += sub->Str();
120 bool TrustingOp<float>(float & a, const float & b, Optype op)
122 feclearexcept(FE_ALL_EXCEPT);
140 return !fetestexcept(FE_ALL_EXCEPT);
144 bool TrustingOp<double>(double & a, const double & b, Optype op)
146 feclearexcept(FE_ALL_EXCEPT);
164 return !fetestexcept(FE_ALL_EXCEPT);
168 bool TrustingOp<int8_t>(int8_t & a, const int8_t & b, Optype op)
176 exact = (abs(sa) <= 127);
180 exact = (abs(sa) <= 127);
184 exact = (abs(sa) <= 127);
187 exact = (b != 0 && sa > b && sa % b == 0);
198 ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a)
200 delete Operation(new ParanoidNumber(a), ADD);
205 ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a)
207 delete Operation(new ParanoidNumber(a), SUBTRACT);
211 ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a)
213 delete Operation(new ParanoidNumber(a), MULTIPLY);
218 ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a)
220 delete Operation(new ParanoidNumber(a), DIVIDE);
225 ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
228 if (Floating() && m_value == 0) // 0 + b = b
230 m_value = b->m_value;
234 swap(b->m_next[ADD], b->m_next[SUBTRACT]);
237 for (int i = 0; i < NOP; ++i)
239 m_next[i] = b->m_next[i];
240 b->m_next[i].clear();
244 if (b->Floating() && b->m_value == 0) // a + 0 = a
249 if (NoFactors() && b->NoFactors())
251 if (ParanoidOp<digit_t>(m_value, b->m_value, op))
253 Optype addop = (op == ADD) ? ADD : SUBTRACT;
254 for (auto add : b->m_next[ADD])
256 delete OperationTerm(add, addop);
258 Optype subop = (op == ADD) ? SUBTRACT : ADD;
259 for (auto sub : b->m_next[SUBTRACT])
260 delete OperationTerm(sub, subop);
262 b->m_next[ADD].clear();
263 b->m_next[SUBTRACT].clear();
271 bool parent = (merge_point == NULL);
272 ParanoidNumber * merge = this;
274 assert(mop != NOP); // silence compiler warning
277 merge_point = &merge;
282 merge = *merge_point;
286 Optype invop = InverseOp(op); // inverse of p
295 for (auto prev : m_next[invop])
297 if (prev->OperationTerm(b, rev, merge_point, merge_op) == b)
301 for (auto next : m_next[op])
303 if (next->OperationTerm(b, fwd, merge_point, merge_op) == b)
312 merge->m_next[*merge_op].push_back(b);
316 if (m_next[op].size() == 0)
325 ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
328 if (Floating() && m_value == 0)
333 if (Floating() && m_value == 1 && op == MULTIPLY)
335 m_value = b->m_value;
336 for (int i = 0; i < NOP; ++i)
338 for (auto n : m_next[i])
341 swap(m_next[i], b->m_next[i]);
345 if (b->Floating() && b->m_value == 1)
348 if (NoTerms() && b->NoTerms())
350 if (ParanoidOp<digit_t>(m_value, b->m_value, op))
352 Optype mulop = (op == MULTIPLY) ? MULTIPLY : DIVIDE;
353 for (auto mul : b->m_next[MULTIPLY])
355 delete OperationFactor(mul, mulop);
357 Optype divop = (op == MULTIPLY) ? DIVIDE : MULTIPLY;
358 for (auto div : b->m_next[DIVIDE])
359 delete OperationFactor(div, divop);
361 b->m_next[DIVIDE].clear();
362 b->m_next[MULTIPLY].clear();
368 bool parent = (merge_point == NULL);
369 ParanoidNumber * merge = this;
373 merge_point = &merge;
378 merge = *merge_point;
382 Optype invop = InverseOp(op); // inverse of p
391 ParanoidNumber * cpy_b = NULL;
393 if (m_next[ADD].size() > 0 || m_next[SUBTRACT].size() > 0)
395 cpy_b = new ParanoidNumber(*b);
398 for (auto prev : m_next[invop])
400 if (prev->OperationFactor(b, rev, merge_point, merge_op) == b)
402 for (auto add : m_next[ADD])
403 delete add->OperationFactor(new ParanoidNumber(*cpy_b), op);
404 for (auto sub : m_next[SUBTRACT])
405 delete sub->OperationFactor(new ParanoidNumber(*cpy_b), op);
411 for (auto next : m_next[op])
413 if (next->OperationFactor(b, fwd, merge_point, merge_op) == b)
415 for (auto add : m_next[ADD])
416 delete add->OperationFactor(new ParanoidNumber(*cpy_b), op);
417 for (auto sub : m_next[SUBTRACT])
418 delete sub->OperationFactor(new ParanoidNumber(*cpy_b), op);
426 m_next[op].push_back(b);
427 for (auto add : m_next[ADD])
428 delete add->OperationFactor(new ParanoidNumber(*cpy_b), op);
429 for (auto sub : m_next[SUBTRACT])
430 delete sub->OperationFactor(new ParanoidNumber(*cpy_b), op);
438 * Performs the operation on a with argument b (a += b, a -= b, a *= b, a /= b)
439 * @returns b if b can safely be deleted
440 * @returns NULL if b has been merged with a
441 * append indicates that b should be merged
443 ParanoidNumber * ParanoidNumber::Operation(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
450 if (op == SUBTRACT || op == ADD)
451 return OperationTerm(b, op, merge_point, merge_op);
452 if (op == MULTIPLY || op == DIVIDE)
453 return OperationFactor(b, op, merge_point, merge_op);
459 string ParanoidNumber::PStr() const
462 for (int i = 0; i < NOP; ++i)
464 Optype f = Optype(i);
466 for (auto n : m_next[f])
468 s << OpChar(f) << n->PStr();
474 bool ParanoidNumber::Simplify(Optype op)
476 vector<ParanoidNumber*> next(0);
477 swap(m_next[op], next);
480 ParanoidNumber * result = Operation(n, op);
484 m_next[op].push_back(n);
486 return (next.size() > m_next[op].size());