a2e8542bc207940591f7325e21dbe6e5ceb63cbf
[ipdf/code.git] / src / paranoidnumber.h
1 #ifndef _PARANOIDNUMBER_H
2 #define _PARANOIDNUMBER_H
3
4 #include <list>
5 #include <cfloat>
6 #include <map>
7 #include <string>
8 #include "log.h"
9
10
11
12 namespace IPDF
13 {
14         class ParanoidNumber
15         {
16                 public:
17                         typedef enum {ADD, SUBTRACT, MULTIPLY, DIVIDE} Optype;
18                         
19                         ParanoidNumber(float value=0, Optype type = ADD) : m_value(value), m_op(type), m_next_term(NULL), m_next_factor(NULL)
20                         {
21                                 
22                         }
23                         
24                         ParanoidNumber(const ParanoidNumber & cpy) : m_value(cpy.m_value), m_op(cpy.m_op), m_next_term(NULL), m_next_factor(NULL)
25                         {
26                                 if (cpy.m_next_term != NULL)
27                                 {
28                                         m_next_term = new ParanoidNumber(*(cpy.m_next_term));
29                                 }
30                                 if (cpy.m_next_factor != NULL)
31                                 {
32                                         m_next_factor = new ParanoidNumber(*(cpy.m_next_factor));
33                                 }
34                         }
35                         
36                         ParanoidNumber(const ParanoidNumber & cpy, Optype type) : m_value(cpy.m_value), m_op(type), m_next_term(NULL), m_next_factor(NULL)
37                         {
38                                 if (cpy.m_next_term != NULL)
39                                 {
40                                         m_next_term = new ParanoidNumber(*(cpy.m_next_term));
41                                 }
42                                 if (cpy.m_next_factor != NULL)
43                                 {
44                                         m_next_factor = new ParanoidNumber(*(cpy.m_next_factor));
45                                 }
46                         }
47                         
48                         ParanoidNumber(const char * str);
49                         ParanoidNumber(const std::string & str) : ParanoidNumber(str.c_str()) {}
50                         
51                         virtual ~ParanoidNumber()
52                         {
53                                 if (m_next_term != NULL)
54                                         delete m_next_term;
55                                 if (m_next_factor != NULL)
56                                         delete m_next_factor;
57                         }
58                         
59                         template <class T> T Convert() const;
60                         double ToDouble() const {return Convert<double>();}
61                         float ToFloat() const {return Convert<float>();}
62                         
63                         bool Floating() const {return (m_next_term == NULL && m_next_factor == NULL);}
64                         bool Sunken() const {return !Floating();} // I could not resist...
65                         
66                         ParanoidNumber & operator+=(const ParanoidNumber & a);
67                         ParanoidNumber & operator-=(const ParanoidNumber & a);
68                         ParanoidNumber & operator*=(const ParanoidNumber & a);
69                         ParanoidNumber & operator/=(const ParanoidNumber & a);
70                         ParanoidNumber & operator=(const ParanoidNumber & a);
71                         
72                         
73                         bool operator<(const ParanoidNumber & a) const {return ToDouble() < a.ToDouble();}
74                         bool operator<=(const ParanoidNumber & a) const {return this->operator<(a) || this->operator==(a);}
75                         bool operator>(const ParanoidNumber & a) const {return !(this->operator<=(a));}
76                         bool operator>=(const ParanoidNumber & a) const {return !(this->operator<(a));}
77                         bool operator==(const ParanoidNumber & a) const {return ToDouble() == a.ToDouble();}
78                         bool operator!=(const ParanoidNumber & a) const {return !(this->operator==(a));}
79                         
80                         ParanoidNumber operator+(const ParanoidNumber & a) const
81                         {
82                                 ParanoidNumber result(*this);
83                                 result += a;
84                                 return result;
85                         }
86                         ParanoidNumber operator-(const ParanoidNumber & a) const
87                         {
88                                 ParanoidNumber result(*this);
89                                 result -= a;
90                                 return result;
91                         }
92                         ParanoidNumber operator*(const ParanoidNumber & a) const
93                         {
94                                 ParanoidNumber result(*this);
95                                 result *= a;
96                                 return result;
97                         }
98                         ParanoidNumber operator/(const ParanoidNumber & a) const
99                         {
100                                 ParanoidNumber result(*this);
101                                 result /= a;
102                                 return result;
103                         }
104                         
105                         std::string Str() const;
106                         static char OpChar(Optype op) 
107                         {
108                                 static char opch[] = {'+','-','*','/'};
109                                 return opch[(int)op];
110                         }
111                 
112                 private:
113                         void Simplify();
114                         void SimplifyTerms();
115                         void SimplifyFactors();
116                         
117                         
118                         float m_value;
119                         Optype m_op;
120                         ParanoidNumber * m_next_term;
121                         ParanoidNumber * m_next_factor;
122                         
123                         
124
125                         
126                         
127
128         };
129
130
131 template <class T>
132 T ParanoidNumber::Convert() const
133 {
134         T value = (m_op == SUBTRACT) ? -m_value : m_value;
135         const ParanoidNumber * n = m_next_factor;
136         if (n != NULL)
137         {
138                 switch (n->m_op)
139                 {
140                         case MULTIPLY:
141                                 value *= n->Convert<T>();
142                                 break;
143                         case DIVIDE:
144                                 value /= n->Convert<T>();
145                                 break;
146                         default:
147                                 Fatal("Shouldn't happen");
148                                 break;
149                 }
150         }
151         n = m_next_term;
152         if (n != NULL)
153         {
154                 switch (n->m_op)
155                 {
156                         case ADD:
157                         case SUBTRACT:
158                                 value += n->Convert<T>();
159                                 break;
160                         default:
161                                 Fatal("Shouldn't happen");
162                 }
163         }
164         return value;
165 }
166
167
168 }
169
170 #endif //_PARANOIDNUMBER_H
171

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