Break maths some more
authorSam Moore <matches@ucc.asn.au>
Thu, 11 Sep 2014 17:33:37 +0000 (01:33 +0800)
committerSam Moore <matches@ucc.asn.au>
Thu, 11 Sep 2014 17:33:37 +0000 (01:33 +0800)
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
src/paranoidnumber.h
src/tests/calculator.cpp
src/tests/paranoidcalculator.cpp
src/tests/paranoidtester.cpp

index b11543e..53729a3 100644 (file)
@@ -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<digit_t>(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<digit_t>(a->m_value, b->Head<digit_t>(), ADD);
+                       if (a->m_next_factor != NULL || b->m_next_factor != NULL)
+                       {
+                               digit_t aa(a->Head<digit_t>());
+                               digit_t ab = (a->m_next_factor != NULL) ? a->m_next_factor->Head<digit_t>() : 1;
+                               digit_t bc(b->Head<digit_t>());
+                               digit_t bd = (b->m_next_factor != NULL) ? b->m_next_factor->Head<digit_t>() : 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<digit_t>(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<digit_t>(a->m_value, b->Head<digit_t>(), ADD);
+                       }
                        if (simplify)
                        {
                                bprev->m_next_term = b->m_next_term;
index f767ffa..9005a15 100644 (file)
@@ -8,7 +8,7 @@
 #include "log.h"
 #include <fenv.h>
 
-#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<T>(c, b, DIVIDE) || ParanoidOp(d, b, DIVIDE))
                                && TrustingOp<T>(c, d, MULTIPLY) && TrustingOp<T>(a,c,ADD)
                                && TrustingOp<T>(a, b, MULTIPLY)) // (a + (cd)/b) * b
@@ -66,6 +67,8 @@ namespace IPDF
                }
                else if (aop == DIVIDE && cop == DIVIDE)
                {
+
+       
                        if (TrustingOp<T>(a, d, MULTIPLY) && TrustingOp<T>(c, b, MULTIPLY)
                                && TrustingOp<T>(a, c, ADD) && TrustingOp<T>(b, d, MULTIPLY))
                        {
index 13903d6..ec20918 100644 (file)
@@ -40,7 +40,8 @@ int main(int argc, char ** argv)
                                break;
                }
                
-               cout << Double(c) << '\n';
+               //cout << Double(c) << '\n';
+               printf("%.40lf\n", Double(c));
                
        }
 }
index 156247f..eb30860 100644 (file)
@@ -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<int64_t>());
                Debug("floats give: %.40f\n", fa);
                Debug("double gives: %.40f\n", da);
                
index 98c056d..84c4bb0 100644 (file)
@@ -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);
                        
                        

UCC git Repository :: git.ucc.asn.au