Paranoia is setting in
[ipdf/code.git] / src / tests / paranoidtester.cpp
1 #include "main.h"
2 #include "real.h"
3 #include <cmath>
4 #include <cassert>
5 #include <list>
6 #include <bitset>
7 #include <iostream>
8 #include <cfloat>
9 #include <fenv.h>
10 #include "paranoidnumber.h"
11 #include "progressbar.h"
12
13 using namespace std;
14 using namespace IPDF;
15
16 string RandomNumberAsString(int max_digits = 12)
17 {
18         string result("");
19         int digits = 1+(rand() % max_digits);
20         int dp = (rand() % digits)+1;
21         for (int i = 0; i < digits; ++i)
22         {
23                 if (i == dp)
24                 {
25                         result += ".";
26                         continue;
27                 }
28                 result += ('0'+rand() % 10);
29         }
30         return result;
31 }
32
33 bool CloseEnough(double d, ParanoidNumber & p)
34 {
35         double pd = p.ToDouble();
36                 
37         if (d == 0)
38                 return fabs(pd) <= 1e-6;
39         return fabs((fabs(pd - d) / d)) <= 1e-6;
40 }
41
42 #define TEST_CASES 1000
43
44 int main(int argc, char ** argv)
45 {
46         srand(time(NULL));
47         string number(RandomNumberAsString());
48         ParanoidNumber a(number);
49         float fa = strtof(number.c_str(), NULL);
50         double da = strtod(number.c_str(), NULL);
51         double diff = 0;
52         long double lda = strtold(number.c_str(), NULL);
53         
54         if (fabs(a.ToDouble() - da) > 1e-6)
55         {
56                 Error("double %lf, pn %lf {%s}", da, a.ToDouble(), a.Str().c_str());
57                 Fatal("Didn't construct correctly off %s", number.c_str());
58         }
59         
60         char opch[] = {'+','-','*','/'};
61         int opcount[] = {0,0,0,0};
62         for (int i = 0; i < TEST_CASES; ++i)
63         {
64                 ProgressBar(i, TEST_CASES); fprintf(stderr, "%.30lf (%d)+ (%d)- (%d)* (%d)/ [Paranoia %ld]",diff, opcount[0],opcount[1],opcount[2],opcount[3], ParanoidNumber::Paranoia());
65                 number = RandomNumberAsString();
66                 ParanoidNumber b(number);
67                 float fb = strtof(number.c_str(), NULL);
68                 double db = strtod(number.c_str(), NULL);
69                 if (db == 0)
70                 {
71                         --i;
72                         continue;
73                 }
74                 long double ldb = strtold(number.c_str(), NULL);
75                 int op = rand() % 4;//= 2*(rand() % 2);
76                 while (op == 1)
77                         op = rand() % 4;
78                 //if (rand() % 2 == 0)
79                         //op = 2+(rand() % 2);
80                         
81                 opcount[op]++;
82                 ParanoidNumber olda(a);
83                 double oldda(da);
84                 switch (op)
85                 {
86                         case 0:
87                                 a += b;
88                                 fa += fb;
89                                 da += db;
90                                 lda += ldb;
91                                 break;
92                         case 1:
93                                 a -= b;
94                                 fa -= fb;
95                                 da -= db;
96                                 lda -= ldb;
97                                 break;
98                         case 2:
99                                 a *= b;
100                                 fa *= fb;
101                                 da *= db;
102                                 lda *= ldb;
103                                 break;
104                         case 3:
105                                 a /= b;
106                                 fa /= fb;
107                                 da /= db;
108                                 lda /= ldb;
109                                 break;
110                 }
111                 diff = 100.0*(fabs(a.ToDouble() - da) / da);
112                 if (!CloseEnough(da, a))
113                 {
114                         Error("Op %i: ParanoidNumber probably doesn't work", i);
115                         Error("Operation: %lf %c %lf", oldda, opch[op], db);
116                         Error("As PN: %lf %c %lf", olda.ToDouble(), opch[op], b.ToDouble());
117                         Error("PN String: %s", a.Str().c_str());
118                         Error("Diff is %.40lf", diff);
119                         Fatal("%.40lf, expected aboout %.40lf", a.ToDouble(), da);
120                         
121                         
122                 }
123                 
124         }
125         printf("ParanoidNumber: {%s} = %.40lf\n", a.Str().c_str(), a.ToDouble());
126         printf("float: %.40f\n", fa);
127         printf("double: %.40lf\n", da);
128         printf("long double: %.40Lf\n", lda);
129         printf("diff %.40lf\n", diff);
130 }

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