1 #include "paranoidnumber.h"
9 // here be many copy paste bugs
16 #ifdef PARANOID_USE_ARENA
17 ParanoidNumber::Arena ParanoidNumber::g_arena;
18 #endif //PARANOID_USE_ARENA
20 ParanoidNumber::~ParanoidNumber()
22 for (int i = 0; i < NOP; ++i)
24 for (auto n : m_next[i])
29 ParanoidNumber::ParanoidNumber(const string & str) : m_value(0), m_next()
31 #ifdef PARANOID_SIZE_LIMIT
34 #ifdef PARANOID_CACHE_RESULTS
35 m_cached_result = NAN;
40 while (str[dp] != '\0' && str[dp] != '.')
45 while (str[end] != '\0')
48 for (int i = dp-1; i >= 0; --i)
50 ParanoidNumber b(str[i]-'0');
56 for (int i = dp+1; i < end; ++i)
59 ParanoidNumber b(str[i]-'0');
65 ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a)
67 //assert(this != NULL);
69 #ifdef PARANOID_SIZE_LIMIT
74 #ifdef PARANOID_CACHE_RESULT
75 m_cached_result = a.m_cached_result;
77 for (int i = 0; i < NOP; ++i)
79 for (auto n : m_next[i])
82 for (auto n : a.m_next[i])
83 m_next[i].push_back(new ParanoidNumber(*n));
85 #ifdef PARANOID_COMPARE_EPSILON
86 CompareForSanity(a.Digit(),a.Digit());
92 string ParanoidNumber::Str() const
95 //assert(this != NULL);
100 for (auto mul : m_next[MULTIPLY])
103 if (!mul->Floating())
104 result += "(" + mul->Str() + ")";
106 result += mul->Str();
108 for (auto div : m_next[DIVIDE])
111 if (!div->Floating())
112 result += "(" + div->Str() + ")";
114 result += div->Str();
117 for (auto add : m_next[ADD])
120 if (!add->Floating())
121 result += "(" + add->Str() + ")";
123 result += add->Str();
125 for (auto sub : m_next[SUBTRACT])
128 if (!sub->Floating())
129 result += "(" + sub->Str() + ")";
131 result += sub->Str();
139 bool TrustingOp<float>(float & a, const float & b, Optype op)
143 feclearexcept(FE_ALL_EXCEPT);
158 a = (a >= 0) ? INFINITY : -INFINITY;
167 return !fetestexcept(FE_ALL_EXCEPT);
171 bool TrustingOp<double>(double & a, const double & b, Optype op)
173 feclearexcept(FE_ALL_EXCEPT);
188 a = (a >= 0) ? INFINITY : -INFINITY;
196 return !fetestexcept(FE_ALL_EXCEPT);
202 bool TrustingOp<long double>(long double & a, const long double & b, Optype op)
206 feclearexcept(FE_ALL_EXCEPT);
221 a = (a >= 0) ? INFINITY : -INFINITY;
230 return !fetestexcept(FE_ALL_EXCEPT);
235 bool TrustingOp<int8_t>(int8_t & a, const int8_t & b, Optype op)
243 exact = (abs(sa) <= 127);
247 exact = (abs(sa) <= 127);
251 exact = (abs(sa) <= 127);
254 exact = (b != 0 && sa > b && sa % b == 0);
265 ParanoidNumber & ParanoidNumber::operator+=(const digit_t & a)
267 #ifdef PARANOID_COMPARE_EPSILON
268 digit_t compare = Digit();
271 delete Operation(new ParanoidNumber(a), ADD);
274 #ifdef PARANOID_COMPARE_EPSILON
275 CompareForSanity(compare, a);
281 ParanoidNumber & ParanoidNumber::operator-=(const digit_t & a)
283 #ifdef PARANOID_COMPARE_EPSILON
284 digit_t compare = Digit();
287 delete Operation(new ParanoidNumber(a), SUBTRACT);
290 #ifdef PARANOID_COMPARE_EPSILON
291 CompareForSanity(compare, a);
296 ParanoidNumber & ParanoidNumber::operator*=(const digit_t & a)
298 #ifdef PARANOID_COMPARE_EPSILON
299 digit_t compare = Digit();
302 delete Operation(new ParanoidNumber(a), MULTIPLY);
305 #ifdef PARANOID_COMPARE_EPSILON
306 CompareForSanity(compare, a);
312 ParanoidNumber & ParanoidNumber::operator/=(const digit_t & a)
314 #ifdef PARANOID_COMPARE_EPSILON
315 digit_t compare = Digit();
318 delete Operation(new ParanoidNumber(a), DIVIDE);
321 #ifdef PARANOID_COMPARE_EPSILON
322 CompareForSanity(compare, a);
328 ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a)
330 #ifdef PARANOID_COMPARE_EPSILON
331 digit_t compare = Digit();
332 compare += a.Digit();
334 delete Operation(new ParanoidNumber(a), ADD);
337 #ifdef PARANOID_COMPARE_EPSILON
338 CompareForSanity(compare, a.Digit());
344 ParanoidNumber & ParanoidNumber::operator-=(const ParanoidNumber & a)
346 #ifdef PARANOID_COMPARE_EPSILON
347 digit_t compare = Digit();
348 compare -= a.Digit();
350 delete Operation(new ParanoidNumber(a), SUBTRACT);
353 #ifdef PARANOID_COMPARE_EPSILON
354 CompareForSanity(compare, a.Digit());
359 ParanoidNumber & ParanoidNumber::operator*=(const ParanoidNumber & a)
361 #ifdef PARANOID_COMPARE_EPSILON
362 digit_t compare = Digit();
363 compare *= a.Digit();
365 delete Operation(new ParanoidNumber(a), MULTIPLY);
368 #ifdef PARANOID_COMPARE_EPSILON
369 CompareForSanity(compare, a.Digit());
375 ParanoidNumber & ParanoidNumber::operator/=(const ParanoidNumber & a)
377 #ifdef PARANOID_COMPARE_EPSILON
378 digit_t compare = Digit();
379 compare /= a.Digit();
381 delete Operation(new ParanoidNumber(a), DIVIDE);
384 #ifdef PARANOID_COMPARE_EPSILON
385 CompareForSanity(compare, a.Digit());
390 ParanoidNumber & ParanoidNumber::operator=(const digit_t & a)
393 for (int i = 0; i < NOP; ++i)
395 for (auto n : m_next[i])
400 #ifdef PARANOID_CACHE_RESULT
404 #ifdef PARANOID_COMPARE_EPSILON
405 CompareForSanity(a,a);
412 ParanoidNumber * ParanoidNumber::OperationTerm(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
414 ////assert(b->SanityCheck());
415 #ifdef PARANOID_CACHE_RESULTS
416 m_cached_result = NAN;
418 #ifdef PARANOID_SIZE_LIMIT
419 if (m_size >= PARANOID_SIZE_LIMIT)
423 m_value += b->Digit() / GetFactors();
427 m_value -= b->Digit() / GetFactors();
431 //Debug("At size limit %d", m_size);
435 if (Floating() && m_value == 0) // 0 + b = b
437 m_value = b->m_value;
441 swap(b->m_next[ADD], b->m_next[SUBTRACT]);
444 for (int i = 0; i < NOP; ++i)
446 m_next[i] = b->m_next[i];
447 b->m_next[i].clear();
450 //assert(SanityCheck());
453 if (b->Floating() && b->m_value == 0) // a + 0 = a
458 if ((NoFactors() && b->NoFactors())
459 || (GetFactors() == b->GetFactors()))
461 if (ParanoidOp<digit_t>(m_value, b->m_value, op))
463 Optype addop = (op == ADD) ? ADD : SUBTRACT;
464 for (auto add : b->m_next[ADD])
466 delete (OperationTerm(add, addop));
468 Optype subop = (op == ADD) ? SUBTRACT : ADD;
469 for (auto sub : b->m_next[SUBTRACT])
470 delete (OperationTerm(sub, subop));
472 b->m_next[ADD].clear();
473 b->m_next[SUBTRACT].clear();
474 //assert(SanityCheck());
481 bool parent = (merge_point == NULL);
482 ParanoidNumber * merge = this;
484 //assert(mop != NOP); // silence compiler warning
487 merge_point = &merge;
492 merge = *merge_point;
496 Optype invop = InverseOp(op); // inverse of p
505 for (auto prev : m_next[invop])
507 if (prev->OperationTerm(b, rev, merge_point, merge_op) == b)
509 //assert(SanityCheck());
514 for (auto next : m_next[op])
516 if (next->OperationTerm(b, fwd, merge_point, merge_op) == b)
518 //assert(SanityCheck());
528 //merge->m_next[*merge_op].push_back(b);
529 m_next[op].push_back(b);
530 #ifdef PARANOID_SIZE_LIMIT
531 m_size += 1+b->m_size;
536 if (m_next[op].size() == 0)
543 //assert(SanityCheck());
548 ParanoidNumber * ParanoidNumber::OperationFactor(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
550 #ifdef PARANOID_CACHE_RESULTS
551 m_cached_result = NAN;
553 #ifdef PARANOID_SIZE_LIMIT
554 if (m_size >= PARANOID_SIZE_LIMIT)
557 m_value *= b->Digit();
559 m_value /= b->Digit();
561 for (auto n : m_next[ADD])
562 delete n->OperationFactor(new ParanoidNumber(*b), op);
563 for (auto n : m_next[SUBTRACT])
564 delete n->OperationFactor(new ParanoidNumber(*b), op);
570 if (Floating() && m_value == 0)
575 if (Floating() && m_value == 1 && op == MULTIPLY)
577 m_value = b->m_value;
578 for (int i = 0; i < NOP; ++i)
580 for (auto n : m_next[i])
583 swap(m_next[i], b->m_next[i]);
585 //assert(SanityCheck());
588 if (b->Floating() && b->m_value == 1)
590 if (b->Floating() && b->m_value == 0 && op == MULTIPLY)
597 if (NoTerms() && b->NoTerms())
599 if (ParanoidOp<digit_t>(m_value, b->m_value, op))
601 Optype mulop = (op == MULTIPLY) ? MULTIPLY : DIVIDE;
602 for (auto mul : b->m_next[MULTIPLY])
604 delete(OperationFactor(mul, mulop));
606 Optype divop = (op == MULTIPLY) ? DIVIDE : MULTIPLY;
607 for (auto div : b->m_next[DIVIDE])
608 delete(OperationFactor(div, divop));
610 b->m_next[DIVIDE].clear();
611 b->m_next[MULTIPLY].clear();
617 bool parent = (merge_point == NULL);
618 ParanoidNumber * merge = this;
622 merge_point = &merge;
627 merge = *merge_point;
631 Optype invop = InverseOp(op); // inverse of p
640 ParanoidNumber * cpy_b = new ParanoidNumber(*b);
641 for (auto prev : m_next[invop])
643 if (prev->OperationFactor(b, rev, merge_point, merge_op) == b)
645 for (auto add : m_next[ADD])
646 delete(add->OperationFactor(new ParanoidNumber(*cpy_b), op));
647 for (auto sub : m_next[SUBTRACT])
648 delete(sub->OperationFactor(new ParanoidNumber(*cpy_b), op));
654 for (auto next : m_next[op])
656 if (next->OperationFactor(b, fwd, merge_point, merge_op) == b)
658 for (auto add : m_next[ADD])
660 delete(add->OperationFactor(new ParanoidNumber(*cpy_b), op));
662 for (auto sub : m_next[SUBTRACT])
664 delete(sub->OperationFactor(new ParanoidNumber(*cpy_b), op));
674 m_next[op].push_back(b);
675 for (auto add : m_next[ADD])
676 delete(add->OperationFactor(new ParanoidNumber(*cpy_b), op));
677 for (auto sub : m_next[SUBTRACT])
678 delete(sub->OperationFactor(new ParanoidNumber(*cpy_b), op));
680 #ifdef PARANOID_SIZE_LIMIT
681 m_size += 1+b->m_size;
684 //assert(SanityCheck());
694 * Performs the operation on a with argument b (a += b, a -= b, a *= b, a /= b)
695 * @returns b if b can safely be deleted
696 * @returns NULL if b has been merged with a
697 * append indicates that b should be merged
699 ParanoidNumber * ParanoidNumber::Operation(ParanoidNumber * b, Optype op, ParanoidNumber ** merge_point, Optype * merge_op)
706 if (op == SUBTRACT || op == ADD)
707 return OperationTerm(b, op, merge_point, merge_op);
708 if (op == MULTIPLY || op == DIVIDE)
709 return OperationFactor(b, op, merge_point, merge_op);
715 string ParanoidNumber::PStr() const
718 for (int i = 0; i < NOP; ++i)
720 Optype f = Optype(i);
722 for (auto n : m_next[f])
724 s << OpChar(f) << n->PStr();
730 bool ParanoidNumber::Simplify(Optype op)
736 //assert(SanityCheck());
737 vector<ParanoidNumber*> next;
739 swap(m_next[op], next);
741 //assert(m_next[op].size() == 0);
742 //assert(SanityCheck());
746 else if (op == SUBTRACT)
750 vector<ParanoidNumber*> hold[2];
751 if (op == MULTIPLY || op == DIVIDE)
753 swap(m_next[ADD], hold[0]);
754 swap(m_next[SUBTRACT], hold[1]);
757 for (vector<ParanoidNumber*>::iterator n = next.begin(); n != next.end(); ++n)
761 for (vector<ParanoidNumber*>::iterator m = n; m != next.end(); ++m)
768 ParanoidNumber * parent = this;
770 ParanoidNumber * result = (*n)->Operation(*m, fwd, &parent, &mop);
773 #ifdef PARANOID_SIZE_LIMIT
774 m_size -= (1+result->m_size);
788 #ifdef PARANOID_SIZE_LIMIT
789 if (Operation(n, op) == n)
791 m_size -= (1+n->m_size);
795 delete(Operation(n, op));
800 if (op == MULTIPLY || op == DIVIDE)
802 swap(m_next[ADD], hold[0]);
803 swap(m_next[SUBTRACT], hold[1]);
806 set<ParanoidNumber*> s;
807 //if (!SanityCheck(s))
809 // Error("Simplify broke Sanity");
811 return (next.size() > m_next[op].size());
814 bool ParanoidNumber::FullSimplify()
817 result |= Simplify(MULTIPLY);
818 result |= Simplify(DIVIDE);
819 result |= Simplify(ADD);
820 result |= Simplify(SUBTRACT);
824 ParanoidNumber::digit_t ParanoidNumber::Digit() const
827 // Get around the absurd requirement that const correctness be observed.
828 #ifdef PARANOID_CACHE_RESULTS
829 digit_t & result = ((ParanoidNumber*)(this))->m_cached_result;
831 if (!isnan(float(result))) // le sigh ambiguous function compiler warnings
837 for (auto mul : m_next[MULTIPLY])
839 result *= mul->Digit();
841 for (auto div : m_next[DIVIDE])
843 result /= div->Digit();
845 for (auto add : m_next[ADD])
846 result += add->Digit();
847 for (auto sub : m_next[SUBTRACT])
848 result -= sub->Digit();
853 ParanoidNumber::digit_t ParanoidNumber::GetFactors() const
856 for (auto mul : m_next[MULTIPLY])
857 value *= mul->Digit();
858 for (auto div : m_next[DIVIDE])
859 value /= div->Digit();
864 ParanoidNumber::digit_t ParanoidNumber::GetTerms() const
867 for (auto add : m_next[ADD])
868 value += add->Digit();
869 for (auto sub : m_next[SUBTRACT])
870 value -= sub->Digit();
874 bool ParanoidNumber::SanityCheck(set<ParanoidNumber*> & visited) const
878 Error("NULL pointer in tree");
882 if (visited.find((ParanoidNumber*)this) != visited.end())
884 Error("I think I've seen this tree before...");
888 visited.insert((ParanoidNumber*)this);
890 for (auto add : m_next[ADD])
892 if (!add->SanityCheck(visited))
895 for (auto sub : m_next[SUBTRACT])
897 if (!sub->SanityCheck(visited))
900 for (auto mul : m_next[MULTIPLY])
902 if (!mul->SanityCheck(visited))
906 for (auto div : m_next[DIVIDE])
908 if (!div->SanityCheck(visited))
910 if (div->Digit() == 0)
912 Error("Divide by zero");
919 #ifdef PARANOID_USE_ARENA
921 void * ParanoidNumber::operator new(size_t s)
923 return g_arena.allocate(s);
926 void ParanoidNumber::operator delete(void * p)
928 g_arena.deallocate(p);
931 ParanoidNumber::Arena::Arena(int64_t block_size) : m_block_size(block_size), m_spare(NULL)
933 m_blocks.push_back({malloc(block_size*sizeof(ParanoidNumber)),0});
936 ParanoidNumber::Arena::~Arena()
938 for (auto block : m_blocks)
945 void * ParanoidNumber::Arena::allocate(size_t s)
949 void * result = m_spare;
954 Block & b = m_blocks.back();
955 void * result = (ParanoidNumber*)(b.memory) + (b.used++);
956 if (b.used >= m_block_size)
959 Debug("Add block of size %d", m_block_size);
960 m_blocks.push_back({malloc(m_block_size*sizeof(ParanoidNumber)), 0});
965 void ParanoidNumber::Arena::deallocate(void * p)
969 #endif //PARANOID_USE_ARENA