From 0fe42dc1237a03b6368e6fa430c1503ed669bee2 Mon Sep 17 00:00:00 2001 From: Sam Moore Date: Fri, 12 Sep 2014 01:33:37 +0800 Subject: [PATCH] Break maths some more CombineTerms is somewhat horribly broken But it works well enough to beat doubles at "0.3 + 0.3 + 0.3" ... And nothing else I've tried. In fact it's worse or equal to doubles at everything else so far. But I haven't done many operations because CombineTerms breaks everything. Maybe it will get better if that isn't broken horribly. --- src/paranoidnumber.cpp | 33 ++++++++++++++++++++++++++++---- src/paranoidnumber.h | 5 ++++- src/tests/calculator.cpp | 3 ++- src/tests/paranoidcalculator.cpp | 4 ++++ src/tests/paranoidtester.cpp | 1 + 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/paranoidnumber.cpp b/src/paranoidnumber.cpp index b11543e..53729a3 100644 --- a/src/paranoidnumber.cpp +++ b/src/paranoidnumber.cpp @@ -68,7 +68,6 @@ ParanoidNumber & ParanoidNumber::operator=(const ParanoidNumber & a) ParanoidNumber & ParanoidNumber::operator+=(const ParanoidNumber & a) { - if (m_next_factor == NULL && a.Floating()) { if (ParanoidOp(m_value, a.m_value, ADD)) @@ -237,7 +236,7 @@ void ParanoidNumber::SimplifyTerms() for (ParanoidNumber * a = this; a != NULL; a = a->m_next_term) { ParanoidNumber * b = a->m_next_term; - if (a->m_next_factor != NULL) + if (a->m_next_factor != NULL && !a->m_next_factor->Floating()) { continue; } @@ -247,14 +246,40 @@ void ParanoidNumber::SimplifyTerms() { //Debug("Simplify factors of %s", b->Str().c_str()); b->SimplifyFactors(); - if (b->m_next_factor != NULL) + if (b->m_next_factor != NULL && !b->m_next_factor->Floating()) { bprev = b; b = b->m_next_term; continue; } + bool simplify = false; - simplify = ParanoidOp(a->m_value, b->Head(), ADD); + if (a->m_next_factor != NULL || b->m_next_factor != NULL) + { + digit_t aa(a->Head()); + digit_t ab = (a->m_next_factor != NULL) ? a->m_next_factor->Head() : 1; + digit_t bc(b->Head()); + digit_t bd = (b->m_next_factor != NULL) ? b->m_next_factor->Head() : 1; + Optype aop = (a->m_next_factor != NULL) ? a->m_next_factor->m_op : DIVIDE; + Optype cop = (b->m_next_factor != NULL) ? b->m_next_factor->m_op : DIVIDE; + simplify = CombineTerms(aa, aop, ab, bc, cop, bd); + if (simplify) + { + a->m_value = aa; + if (a->m_next_factor != NULL) + a->m_next_factor->m_value = ab; + else if (ab != 1) + { + a->m_next_factor = b->m_next_factor; + b->m_next_factor = NULL; + a->m_next_factor->m_value = ab; + } + } + } + else + { + simplify = ParanoidOp(a->m_value, b->Head(), ADD); + } if (simplify) { bprev->m_next_term = b->m_next_term; diff --git a/src/paranoidnumber.h b/src/paranoidnumber.h index f767ffa..9005a15 100644 --- a/src/paranoidnumber.h +++ b/src/paranoidnumber.h @@ -8,7 +8,7 @@ #include "log.h" #include -#define PARANOID_DIGIT_T int8_t // we could theoretically replace this with a template +#define PARANOID_DIGIT_T float // we could theoretically replace this with a template // but let's not do that... namespace IPDF @@ -42,6 +42,7 @@ namespace IPDF T a(aa); T b(bb); T c(cc); T d(dd); if (aop == MULTIPLY && cop == MULTIPLY) // a*b + c*d { + if ((ParanoidOp(c, b, DIVIDE) || ParanoidOp(d, b, DIVIDE)) && TrustingOp(c, d, MULTIPLY) && TrustingOp(a,c,ADD) && TrustingOp(a, b, MULTIPLY)) // (a + (cd)/b) * b @@ -66,6 +67,8 @@ namespace IPDF } else if (aop == DIVIDE && cop == DIVIDE) { + + if (TrustingOp(a, d, MULTIPLY) && TrustingOp(c, b, MULTIPLY) && TrustingOp(a, c, ADD) && TrustingOp(b, d, MULTIPLY)) { diff --git a/src/tests/calculator.cpp b/src/tests/calculator.cpp index 13903d6..ec20918 100644 --- a/src/tests/calculator.cpp +++ b/src/tests/calculator.cpp @@ -40,7 +40,8 @@ int main(int argc, char ** argv) break; } - cout << Double(c) << '\n'; + //cout << Double(c) << '\n'; + printf("%.40lf\n", Double(c)); } } diff --git a/src/tests/paranoidcalculator.cpp b/src/tests/paranoidcalculator.cpp index 156247f..eb30860 100644 --- a/src/tests/paranoidcalculator.cpp +++ b/src/tests/paranoidcalculator.cpp @@ -19,6 +19,8 @@ int main(int argc, char ** argv) Debug("FLT_EPSILON = %.40f", FLT_EPSILON); Debug("Sizeof ParanoidNumber::digit_t is %u", sizeof(ParanoidNumber::digit_t)); Debug("Sizeof ParanoidNumber is %u", sizeof(ParanoidNumber)); + Debug("Sizeof double is %u", sizeof(double)); + Debug("Sizeof ParanoidNumber* %u", sizeof(ParanoidNumber*)); string token(""); cin >> token; @@ -70,6 +72,8 @@ int main(int argc, char ** argv) Debug("a is: %s", a.Str().c_str()); Debug("a as double: %.40f\n", a.ToDouble()); + Debug("a as float: %.40f\n", a.ToFloat()); + Debug("a as int64_t: %ld\n", a.Convert()); Debug("floats give: %.40f\n", fa); Debug("double gives: %.40f\n", da); diff --git a/src/tests/paranoidtester.cpp b/src/tests/paranoidtester.cpp index 98c056d..84c4bb0 100644 --- a/src/tests/paranoidtester.cpp +++ b/src/tests/paranoidtester.cpp @@ -116,6 +116,7 @@ int main(int argc, char ** argv) Error("As PN: %lf %c %lf", olda.ToDouble(), opch[op], b.ToDouble()); Error("PN String: %s", a.Str().c_str()); Error("Diff is %.40lf", diff); + Error("LONG double gives %.40llf", lda); Fatal("%.40lf, expected aboout %.40lf", a.ToDouble(), da); -- 2.20.1