+ }
+
+ if (op == MULTIPLY || op == DIVIDE)
+ {
+ swap(m_next[ADD], hold[0]);
+ swap(m_next[SUBTRACT], hold[1]);
+ }
+
+ set<ParanoidNumber*> s;
+ //if (!SanityCheck(s))
+ //{
+ // Error("Simplify broke Sanity");
+ //}
+ return (next.size() > m_next[op].size());
+}
+
+bool ParanoidNumber::FullSimplify()
+{
+ bool result = false;
+ result |= Simplify(MULTIPLY);
+ result |= Simplify(DIVIDE);
+ result |= Simplify(ADD);
+ result |= Simplify(SUBTRACT);
+ return result;
+}
+
+ParanoidNumber::digit_t ParanoidNumber::Digit() const
+{
+
+ // Get around the absurd requirement that const correctness be observed.
+ #ifdef PARANOID_CACHE_RESULTS
+ if (m_cache_valid) // le sigh ambiguous function compiler warnings
+ return m_cached_result;
+
+ digit_t & result = ((ParanoidNumber*)(this))->m_cached_result;
+
+ #else
+ digit_t result;
+ #endif
+ result = m_value;
+ for (auto mul : m_next[MULTIPLY])
+ {
+ result *= mul->Digit();
+ }
+ for (auto div : m_next[DIVIDE])
+ {
+ result /= div->Digit();
+ }
+ for (auto add : m_next[ADD])
+ result += add->Digit();
+ for (auto sub : m_next[SUBTRACT])
+ result -= sub->Digit();
+
+ #ifdef PARANOID_CACHE_RESULTS
+ ((ParanoidNumber*)(this))->m_cache_valid = true;
+ #endif
+ return result;
+
+}
+
+ParanoidNumber::digit_t ParanoidNumber::GetFactors() const
+{
+ digit_t value = 1;
+ for (auto mul : m_next[MULTIPLY])
+ value *= mul->Digit();
+ for (auto div : m_next[DIVIDE])
+ value /= div->Digit();
+ return value;
+}
+
+
+ParanoidNumber::digit_t ParanoidNumber::GetTerms() const
+{
+ digit_t value = 0;
+ for (auto add : m_next[ADD])
+ value += add->Digit();
+ for (auto sub : m_next[SUBTRACT])
+ value -= sub->Digit();
+ return value;
+}
+
+bool ParanoidNumber::SanityCheck(set<ParanoidNumber*> & visited) const
+{
+ if (this == NULL)
+ {
+ Error("NULL pointer in tree");
+ return false;
+ }
+
+ if (visited.find((ParanoidNumber*)this) != visited.end())
+ {
+ Error("I think I've seen this tree before...");
+ return false;
+ }
+
+ visited.insert((ParanoidNumber*)this);
+
+ for (auto add : m_next[ADD])
+ {
+ if (!add->SanityCheck(visited))
+ return false;
+ }
+ for (auto sub : m_next[SUBTRACT])
+ {
+ if (!sub->SanityCheck(visited))
+ return false;
+ }
+ for (auto mul : m_next[MULTIPLY])
+ {
+ if (!mul->SanityCheck(visited))
+ return false;
+ }
+
+ for (auto div : m_next[DIVIDE])
+ {
+ if (!div->SanityCheck(visited))
+ return false;
+ if (div->Digit() == 0)